1package buildtags 2 3import "testing" 4 5func TestGoString(t *testing.T) { 6 cases := []struct { 7 Constraint Interface 8 Expect string 9 }{ 10 {Term("amd64"), "// +build amd64\n"}, 11 {Any(Opt(Term("linux"), Term("386")), Opt("darwin", Not("cgo"))), "// +build linux,386 darwin,!cgo\n"}, 12 {And(Any(Term("linux"), Term("darwin")), Term("386")), "// +build linux darwin\n// +build 386\n"}, 13 } 14 for _, c := range cases { 15 got := c.Constraint.ToConstraints().GoString() 16 if got != c.Expect { 17 t.Errorf("constraint %#v GoString() got %q; expected %q", c.Constraint, got, c.Expect) 18 } 19 } 20} 21 22func TestValidateOK(t *testing.T) { 23 cases := []Interface{ 24 Term("name"), 25 Term("!name"), 26 } 27 for _, c := range cases { 28 if err := c.ToConstraints().Validate(); err != nil { 29 t.Errorf("unexpected validation error for %#v: %q", c, err) 30 } 31 } 32} 33 34func TestValidateErrors(t *testing.T) { 35 cases := []struct { 36 Constraint Interface 37 ExpectMessage string 38 }{ 39 {Term(""), "empty tag name"}, 40 {Term("!"), "empty tag name"}, 41 {Term("!!"), "at most one '!' allowed"}, 42 {Term("!abc!def"), "character '!' disallowed in tags"}, 43 { 44 And(Any(Term("linux"), Term("my-os")), Term("386")).ToConstraints(), 45 "invalid term \"my-os\": character '-' disallowed in tags", 46 }, 47 } 48 for _, c := range cases { 49 err := c.Constraint.Validate() 50 if err == nil { 51 t.Fatalf("expect validation error for constraint:\n%s", c.Constraint.GoString()) 52 } 53 if err.Error() != c.ExpectMessage { 54 t.Fatalf("unexpected error message\n\tgot:\t%q\n\texpect:\t%q\n", err, c.ExpectMessage) 55 } 56 } 57} 58 59func TestParseConstraintRoundTrip(t *testing.T) { 60 exprs := []string{ 61 "amd64", 62 "amd64,linux", 63 "!a", 64 "!a,b c,!d,e", 65 "linux,386 darwin,!cgo", 66 } 67 for _, expr := range exprs { 68 c := AssertParseConstraint(t, expr) 69 got := c.GoString() 70 expect := "// +build " + expr + "\n" 71 if got != expect { 72 t.Fatalf("roundtrip error\n\tgot\t%q\n\texpect\t%q\n", got, expect) 73 } 74 } 75} 76 77func TestParseConstraintError(t *testing.T) { 78 expr := "linux,386 my-os,!cgo" 79 _, err := ParseConstraint(expr) 80 if err == nil { 81 t.Fatalf("expected error parsing %q", expr) 82 } 83} 84 85func TestEvaluate(t *testing.T) { 86 cases := []struct { 87 Constraint Interface 88 Values map[string]bool 89 Expect bool 90 }{ 91 {Term("a"), SetTags("a"), true}, 92 {Term("!a"), SetTags("a"), false}, 93 {Term("!a"), SetTags(), true}, 94 {Term("inval-id"), SetTags("inval-id"), false}, 95 96 {Opt(Term("a"), Term("b")), SetTags(), false}, 97 {Opt(Term("a"), Term("b")), SetTags("a"), false}, 98 {Opt(Term("a"), Term("b")), SetTags("b"), false}, 99 {Opt(Term("a"), Term("b")), SetTags("a", "b"), true}, 100 {Opt(Term("a"), Term("b-a-d")), SetTags("a", "b-a-d"), false}, 101 102 { 103 Any(Opt(Term("linux"), Term("386")), Opt("darwin", Not("cgo"))), 104 SetTags("linux", "386"), 105 true, 106 }, 107 { 108 Any(Opt(Term("linux"), Term("386")), Opt("darwin", Not("cgo"))), 109 SetTags("darwin"), 110 true, 111 }, 112 { 113 Any(Opt(Term("linux"), Term("386")), Opt("darwin", Not("cgo"))), 114 SetTags("linux", "darwin", "cgo"), 115 false, 116 }, 117 118 { 119 And(Any(Term("linux"), Term("darwin")), Term("386")), 120 SetTags("darwin", "386"), 121 true, 122 }, 123 } 124 for _, c := range cases { 125 got := c.Constraint.Evaluate(c.Values) 126 if c.Constraint.Validate() != nil && got { 127 t.Fatal("invalid expressions must evaluate false") 128 } 129 if got != c.Expect { 130 t.Errorf("%#v evaluated with %#v got %v expect %v", c.Constraint, c.Values, got, c.Expect) 131 } 132 } 133} 134 135func AssertParseConstraint(t *testing.T, expr string) Constraint { 136 t.Helper() 137 c, err := ParseConstraint(expr) 138 if err != nil { 139 t.Fatalf("error parsing expression %q: %q", expr, err) 140 } 141 return c 142} 143