pkg: generate per-directory tests from builtin_test.go

- from original tests in cue
- keep some of the original tests around to test builtin logic

Change-Id: I84897b45016034d871b731ba3e76ae9a0cd8a8d0
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/6883
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
Reviewed-by: CUE cueckoo <cueckoo@gmail.com>
diff --git a/cue/builtin_test.go b/cue/builtin_test.go
index 97a1dc8..c8698cd 100644
--- a/cue/builtin_test.go
+++ b/cue/builtin_test.go
@@ -16,9 +16,6 @@
 
 import (
 	"fmt"
-	"math/big"
-	"strconv"
-	"strings"
 	"testing"
 
 	"cuelang.org/go/cue"
@@ -39,11 +36,6 @@
 			[]string{fmt.Sprintf("(%s)", expr)},
 		}}
 	}
-	hexToDec := func(s string) string {
-		var x big.Int
-		x.SetString(s, 16)
-		return x.String()
-	}
 	testCases := []struct {
 		instances []*bimport
 		emit      string
@@ -69,57 +61,6 @@
 		test("crypto/md5", `len(md5.Sum("hash me"))`),
 		`16`,
 	}, {
-		test("crypto/sha1", `len(sha1.Sum("hash me"))`),
-		`20`,
-	}, {
-		test("crypto/sha256", `len(sha256.Sum256("hash me"))`),
-		`32`,
-	}, {
-		test("crypto/sha256", `len(sha256.Sum224("hash me"))`),
-		`28`,
-	}, {
-		test("crypto/sha512", `len(sha512.Sum512("hash me"))`),
-		`64`,
-	}, {
-		test("crypto/sha512", `len(sha512.Sum384("hash me"))`),
-		`48`,
-	}, {
-		test("crypto/sha512", `len(sha512.Sum512_224("hash me"))`),
-		`28`,
-	}, {
-		test("crypto/sha512", `len(sha512.Sum512_256("hash me"))`),
-		`32`,
-	}, {
-		test("encoding/base64", `base64.Encode(null, "foo")`),
-		`"Zm9v"`,
-	}, {
-		test("encoding/base64", `base64.Decode(null, base64.Encode(null, "foo"))`),
-		`'foo'`,
-	}, {
-		test("encoding/base64", `base64.Decode(null, "foo")`),
-		`_|_(error in call to encoding/base64.Decode: illegal base64 data at input byte 0 (and 1 more errors))`,
-	}, {
-		test("encoding/base64", `base64.Decode({}, "foo")`),
-		`_|_(error in call to encoding/base64.Decode: base64: unsupported encoding: cannot use value {} (type struct) as null (and 1 more errors))`,
-	}, {
-		test("encoding/hex", `hex.Encode("foo")`),
-		`"666f6f"`,
-	}, {
-		test("encoding/hex", `hex.Decode(hex.Encode("foo"))`),
-		`'foo'`,
-	}, {
-		test("encoding/hex", `hex.Decode("foo")`),
-		`_|_(error in call to encoding/hex.Decode: encoding/hex: invalid byte: U+006F 'o' (and 1 more errors))`,
-	}, {
-		test("encoding/hex", `hex.Dump('foo')`),
-		`"00000000  66 6f 6f                                          |foo|\n"`,
-	}, {
-		test("encoding/json", `json.Validate("{\"a\":10}", {b:string})`),
-		`true`,
-	}, {
-		test("encoding/json", `json.Validate("{\"a\":10}", {a:<3})`),
-		`_|_(error in call to encoding/json.Validate: a: invalid value 10 (out of bound <3) (and 1 more errors))`,
-	}, {
 		test("encoding/yaml", `yaml.Validate("a: 2\n---\na: 4", {a:<3})`),
 		`_|_(error in call to encoding/yaml.Validate: a: invalid value 4 (out of bound <3) (and 1 more errors))`,
 	}, {
@@ -129,336 +70,21 @@
 		test("encoding/yaml", `yaml.Validate("a: 2\n", {a:<5, b:int})`),
 		`_|_(error in call to encoding/yaml.Validate: b: incomplete value int (and 1 more errors))`,
 	}, {
-		test("encoding/yaml", `yaml.ValidatePartial("a: 2\n---\na: 4", {a:<3})`),
-		`_|_(error in call to encoding/yaml.ValidatePartial: a: invalid value 4 (out of bound <3) (and 1 more errors))`,
-	}, {
-		test("encoding/yaml", `yaml.ValidatePartial("a: 2\n---\na: 4", {a:<5})`),
-		`true`,
-	}, {
-		test("encoding/yaml", `yaml.ValidatePartial("a: 2\n", {a:<5, b:int})`),
-		`true`,
-	}, {
 		test("strconv", `strconv.FormatUint(64, 16)`),
 		`"40"`,
 	}, {
-		// Find a better alternative, as this call should go.
-		test("strconv", `strconv.FormatFloat(3.02, 300, 4, 64)`),
-		`_|_(int 300 overflows byte in argument 1 in call to strconv.FormatFloat (and 1 more errors))`,
-	}, {
-		// Find a better alternative, as this call should go.
-		test("strconv", `strconv.FormatFloat(3.02, -1, 4, 64)`),
-		`_|_(cannot use -1 (type int) as byte in argument 1 to strconv.FormatFloat (and 1 more errors))`,
-	}, {
-		// Find a better alternative, as this call should go.
-		test("strconv", `strconv.FormatFloat(3.02, 1.0, 4, 64)`),
-		`_|_(cannot use 1.0 (type float) as int in argument 2 to strconv.FormatFloat)`,
-	}, {
-		test("list", `list.Avg([1, 2, 3, 4])`),
-		`2.5`,
-	}, {
-		test("list", `list.Avg([])`),
-		`_|_(error in call to list.Avg: empty list (and 1 more errors))`,
-	}, {
-		test("list", `list.Avg("foo")`),
-		`_|_(cannot use "foo" (type string) as list in argument 1 to list.Avg)`,
-	}, {
-		test("list", `list.Drop([1, 2, 3, 4], 0)`),
-		`[1,2,3,4]`,
-	}, {
-		test("list", `list.Drop([1, 2, 3, 4], 2)`),
-		`[3,4]`,
-	}, {
-		test("list", `list.Drop([1, 2, 3, 4], 10)`),
-		`[]`,
-	}, {
-		test("list", `list.Drop([1, 2, 3, 4], -1)`),
-		`_|_(error in call to list.Drop: negative index (and 1 more errors))`,
-	}, {
-		test("list", `list.FlattenN([1, [[2, 3], []], [4]], -1)`),
-		`[1,2,3,4]`,
-	}, {
-		test("list", `list.FlattenN([1, [[2, 3], []], [4]], 0)`),
-		`[1,[[2,3],[]],[4]]`,
-	}, {
-		test("list", `list.FlattenN([1, [[2, 3], []], [4]], 1)`),
-		`[1,[2,3],[],4]`,
-	}, {
-		test("list", `list.FlattenN([1, [[2, 3], []], [4]], 2)`),
-		`[1,2,3,4]`,
-	}, {
-		test("list", `list.FlattenN([[1, 2] | *[]], -1)`),
-		`[]`,
-	}, {
-		test("list", `list.FlattenN("foo", 1)`),
-		`_|_(error in call to list.FlattenN: cannot use value "foo" (type string) as list (and 1 more errors))`,
-	}, {
-		test("list", `list.FlattenN([], "foo")`),
-		`_|_(cannot use "foo" (type string) as int in argument 2 to list.FlattenN)`,
-	}, {
-		test("list", `list.Max([1, 2, 3, 4])`),
-		`4`,
-	}, {
-		test("list", `list.Max([])`),
-		`_|_(error in call to list.Max: empty list (and 1 more errors))`,
-	}, {
-		test("list", `list.Max("foo")`),
-		`_|_(cannot use "foo" (type string) as list in argument 1 to list.Max)`,
-	}, {
-		test("list", `list.Min([1, 2, 3, 4])`),
-		`1`,
-	}, {
-		test("list", `list.Min([])`),
-		`_|_(error in call to list.Min: empty list (and 1 more errors))`,
-	}, {
-		test("list", `list.Min("foo")`),
-		`_|_(cannot use "foo" (type string) as list in argument 1 to list.Min)`,
-	}, {
-		test("list", `list.Product([1, 2, 3, 4])`),
-		`24`,
-	}, {
-		test("list", `list.Product([])`),
-		`1`,
-	}, {
-		test("list", `list.Product("foo")`),
-		`_|_(cannot use "foo" (type string) as list in argument 1 to list.Product)`,
-	}, {
-		test("list", `list.Range(0, 5, 0)`),
-		`_|_(error in call to list.Range: step must be non zero (and 1 more errors))`,
-	}, {
-		test("list", `list.Range(5, 0, 1)`),
-		`_|_(error in call to list.Range: end must be greater than start when step is positive (and 1 more errors))`,
-	}, {
-		test("list", `list.Range(0, 5, -1)`),
-		`_|_(error in call to list.Range: end must be less than start when step is negative (and 1 more errors))`,
-	}, {
-		test("list", `list.Range(0, 5, 1)`),
-		`[0,1,2,3,4]`,
-	}, {
-		test("list", `list.Range(0, 1, 1)`),
-		`[0]`,
-	}, {
-		test("list", `list.Range(0, 5, 2)`),
-		`[0,2,4]`,
-	}, {
-		test("list", `list.Range(5, 0, -1)`),
-		`[5,4,3,2,1]`,
-	}, {
-		test("list", `list.Range(0, 5, 0.5)`),
-		`[0,0.5,1.0,1.5,2.0,2.5,3.0,3.5,4.0,4.5]`,
-	}, {
-		test("list", `list.Slice([1, 2, 3, 4], 1, 3)`),
-		`[2,3]`,
-	}, {
-		test("list", `list.Slice([1, 2, 3, 4], -1, 3)`),
-		`_|_(error in call to list.Slice: negative index (and 1 more errors))`,
-	}, {
-		test("list", `list.Slice([1, 2, 3, 4], 3, 1)`),
-		`_|_(error in call to list.Slice: invalid index: 3 > 1 (and 1 more errors))`,
-	}, {
-		test("list", `list.Slice([1, 2, 3, 4], 5, 5)`),
-		`_|_(error in call to list.Slice: slice bounds out of range (and 1 more errors))`,
-	}, {
-		test("list", `list.Slice([1, 2, 3, 4], 1, 5)`),
-		`_|_(error in call to list.Slice: slice bounds out of range (and 1 more errors))`,
-	}, {
-		test("list", `list.Sort([], list.Ascending)`),
-		`[]`,
-	}, {
-		test("list", `list.Sort([2, 3, 1, 4], {x:_, y:_, less: x<y})`),
-		`[1,2,3,4]`,
-	}, {
-		test("list", `list.SortStable([{a:2,v:1}, {a:1,v:2}, {a:1,v:3}], {
-			x:_,
-			y:_,
-			less: (x.a < y.a)
-		})`),
-		`[{a:1,v:2},{a:1,v:3},{a:2,v:1}]`,
-	}, {
-		test("list", `list.Sort([{a:1}, {b:2}], list.Ascending)`),
-		`_|_(error in call to list.Sort: x: conflicting values string and {b:2} (mismatched types string and struct) (and 1 more errors) (and 1 more errors))`,
-	}, {
-		test("list", `list.SortStrings(["b", "a"])`),
-		`["a","b"]`,
-	}, {
-		// TODO: path error. This should be done as part of builtin refactoring.
-		test("list", `list.SortStrings([1, 2])`),
-		`_|_(error in call to list.SortStrings: element 0 of list argument 0: 0: cannot use value 1 (type int) as string (and 1 more errors))`,
-	}, {
-		test("list", `list.Sum([1, 2, 3, 4])`),
-		`10`,
-	}, {
-		test("list", `list.Sum([])`),
-		`0`,
-	}, {
-		test("list", `list.Sum("foo")`),
-		`_|_(cannot use "foo" (type string) as list in argument 1 to list.Sum)`,
-	}, {
-		test("list", `list.Take([1, 2, 3, 4], 0)`),
-		`[]`,
-	}, {
-		test("list", `list.Take([1, 2, 3, 4], 2)`),
-		`[1,2]`,
-	}, {
-		test("list", `list.Take([1, 2, 3, 4], 10)`),
-		`[1,2,3,4]`,
-	}, {
-		test("list", `list.Take([1, 2, 3, 4], -1)`),
-		`_|_(error in call to list.Take: negative index (and 1 more errors))`,
-	}, {
-		test("list", `list.MinItems([1, 2, 3, 4], 2)`),
-		`true`,
-	}, {
-		test("list", `list.MinItems([1, 2, 3, 4], 5)`),
-		`false`,
-	}, {
-		test("list", `list.MaxItems([1, 2, 3, 4], 5)`),
-		`true`,
-	}, {
-		test("list", `list.MaxItems([1, 2, 3, 4], 2)`),
-		`false`,
-	}, {
-		// Panics
-		test("math", `math.Jacobi(1000, 2000)`),
-		`_|_(error in call to math.Jacobi: big: invalid 2nd argument to Int.Jacobi: need odd integer but got 2000 (and 1 more errors))`,
-	}, {
-		test("math", `math.Jacobi(1000, 201)`),
-		`1`,
-	}, {
-		test("math", `math.Asin(2.0e400)`),
-		`_|_(cannot use 2.0E+400 (type float) as float64 in argument 0 to math.Asin: value was rounded up (and 1 more errors))`,
-	}, {
-		test("math", `math.MultipleOf(4, 2)`), `true`,
-	}, {
-		test("math", `math.MultipleOf(5, 2)`), `false`,
-	}, {
-		test("math", `math.MultipleOf(5, 0)`),
-		`_|_(error in call to math.MultipleOf: division by zero (and 1 more errors))`,
-	}, {
-		test("math", `math.MultipleOf(100, 1.00001)`), `false`,
-	}, {
-		test("math", `math.MultipleOf(1, 1)`), `true`,
-	}, {
-		test("math", `math.MultipleOf(5, 2.5)`), `true`,
-	}, {
-		test("math", `math.MultipleOf(100e100, 10)`), `true`,
-	}, {
-		test("encoding/csv", `csv.Decode("1,2,3\n4,5,6")`),
-		`[["1","2","3"],["4","5","6"]]`,
-	}, {
 		test("regexp", `regexp.Find(#"f\w\w"#, "afoot")`),
 		`"foo"`,
 	}, {
 		test("regexp", `regexp.Find(#"f\w\w"#, "bar")`),
 		`_|_(error in call to regexp.Find: no match (and 1 more errors))`,
 	}, {
-		test("regexp", `regexp.FindAll(#"f\w\w"#, "afoot afloat from", 2)`),
-		`["foo","flo"]`,
-	}, {
-		test("regexp", `regexp.FindAll(#"f\w\w"#, "afoot afloat from", 2)`),
-		`["foo","flo"]`,
-	}, {
-		test("regexp", `regexp.FindAll(#"f\w\w"#, "bla bla", -1)`),
-		`_|_(error in call to regexp.FindAll: no match (and 1 more errors))`,
-	}, {
-		test("regexp", `regexp.FindSubmatch(#"f(\w)(\w)"#, "afloat afoot from")`),
-		`["flo","l","o"]`,
-	}, {
-		test("regexp", `regexp.FindAllSubmatch(#"f(\w)(\w)"#, "afloat afoot from", -1)`),
-		`[["flo","l","o"],["foo","o","o"],["fro","r","o"]]`,
-	}, {
-		test("regexp", `regexp.FindAllSubmatch(#"f(\w)(\w)"#, "aglom", -1)`),
-		`_|_(error in call to regexp.FindAllSubmatch: no match (and 1 more errors))`,
-	}, {
-		test("regexp", `regexp.FindNamedSubmatch(#"f(?P<A>\w)(?P<B>\w)"#, "afloat afoot from")`),
-		`{A:"l",B:"o"}`,
-	}, {
-		test("regexp", `regexp.FindAllNamedSubmatch(#"f(?P<A>\w)(?P<B>\w)"#, "afloat afoot from", -1)`),
-		`[{A:"l",B:"o"},{A:"o",B:"o"},{A:"r",B:"o"}]`,
-	}, {
-		test("regexp", `regexp.FindAllNamedSubmatch(#"f(?P<A>optional)?"#, "fbla", -1)`),
-		`[{A:""}]`,
-	}, {
-		test("regexp", `regexp.FindAllNamedSubmatch(#"f(?P<A>\w)(?P<B>\w)"#, "aglom", -1)`),
-		`_|_(error in call to regexp.FindAllNamedSubmatch: no match (and 1 more errors))`,
-	}, {
-		test("regexp", `regexp.Valid & "valid"`),
-		`"valid"`,
-	}, {
-		test("regexp", `regexp.Valid & "invalid)"`),
-		"_|_(error in call to regexp.Valid: error parsing regexp: unexpected ): `invalid)`)",
-	}, {
-		test("strconv", `strconv.FormatBool(true)`),
-		`"true"`,
-	}, {
-		test("strings", `strings.Join(["Hello", "World!"], " ")`),
-		`"Hello World!"`,
-	}, {
-		test("strings", `strings.Join([1, 2], " ")`),
-		`_|_(error in call to strings.Join: element 0 of list argument 0: 0: cannot use value 1 (type int) as string (and 1 more errors))`,
-	}, {
-		test("strings", `strings.ByteAt("a", 0)`),
-		strconv.Itoa('a'),
-	}, {
-		test("strings", `strings.ByteSlice("Hello", 2, 5)`),
-		`'llo'`,
-	}, {
-		test("strings", `strings.SliceRunes("✓ Hello", 0, 3)`),
-		`"✓ H"`,
-	}, {
-		test("strings", `strings.Runes("Café")`),
-		strings.Replace(fmt.Sprint([]rune{'C', 'a', 'f', 'é'}), " ", ",", -1),
-	}, {
-		test("math/bits", `bits.Or(0x8, 0x1)`),
-		`9`,
-	}, {
-		testExpr(`len({})`),
-		`0`,
-	}, {
-		testExpr(`len({a: 1, b: 2, {[foo=_]: int}, _c: 3})`),
-		`2`,
-	}, {
 		testExpr(`len([1, 2, 3])`),
 		`3`,
 	}, {
 		testExpr(`len("foo")`),
 		`3`,
 	}, {
-		testExpr(`len('f\x20\x20')`),
-		`3`,
-	}, {
-		testExpr(`and([string, "foo"])`),
-		`"foo"`,
-	}, {
-		testExpr(`and([string, =~"fo"]) & "foo"`),
-		`"foo"`,
-	}, {
-		testExpr(`and([])`),
-		`{}`, // _ & top scope
-	}, {
-		testExpr(`or([1, 2, 3]) & 2`),
-		`2`,
-	}, {
-		testExpr(`or([])`),
-		`_|_(empty list in call to or (and 1 more errors))`,
-	}, {
-		test("encoding/csv", `csv.Encode([[1,2,3],[4,5],[7,8,9]])`),
-		`"1,2,3\n4,5\n7,8,9\n"`,
-	}, {
-		test("encoding/csv", `csv.Encode([["a", "b"], ["c"]])`),
-		`"a,b\nc\n"`,
-	}, {
-		test("encoding/json", `json.Valid("1")`),
-		`true`,
-	}, {
-		test("encoding/json", `json.Compact("[1, 2]")`),
-		`"[1,2]"`,
-	}, {
-		test("encoding/json", `json.Indent(#"{"a": 1, "b": 2}"#, "", "  ")`),
-		`"{\n  \"a\": 1,\n  \"b\": 2\n}"`,
-	}, {
-		test("encoding/json", `json.Unmarshal("1")`),
-		`1`,
-	}, {
 		test("encoding/json", `json.MarshalStream([{a: 1}, {b: 2}])`),
 		`"{\"a\":1}\n{\"b\":2}\n"`,
 	}, {
@@ -471,91 +97,6 @@
 		test("encoding/yaml", `yaml.MarshalStream([{a: 1}, {b: 2}])`),
 		`"a: 1\n---\nb: 2\n"`,
 	}, {
-		test("net", `net.FQDN & "foo.bar."`),
-		`"foo.bar."`,
-	}, {
-		test("net", `net.FQDN("foo.bararararararararararararararararararararararararararararararararara")`),
-		`false`,
-	}, {
-		test("net", `net.SplitHostPort("[::%lo0]:80")`),
-		`["::%lo0","80"]`,
-	}, {
-		test("net", `net.JoinHostPort("example.com", "80")`),
-		`"example.com:80"`,
-	}, {
-		test("net", `net.JoinHostPort("2001:db8::1", 80)`),
-		`"[2001:db8::1]:80"`,
-	}, {
-		test("net", `net.JoinHostPort([192,30,4,2], 80)`),
-		`"192.30.4.2:80"`,
-	}, {
-		// TODO: why is this not printing compactly?
-		test("net", `net.JoinHostPort([192, 30, 4], 80)`),
-		`_|_(error in call to net.JoinHostPort: invalid host [192, 30, 4] (and 1 more errors))`,
-	}, {
-		test("net", `net.IP("23.23.23.23")`),
-		`true`,
-	}, {
-		test("net", `net.IPv4 & "23.23.23.2333"`),
-		`_|_(invalid value "23.23.23.2333" (does not satisfy net.IPv4))`,
-	}, {
-		test("net", `net.IP("23.23.23.23")`),
-		`true`,
-	}, {
-		test("net", `net.IP("2001:db8::1")`),
-		`true`,
-	}, {
-		test("net", `net.IPv4("2001:db8::1")`),
-		`false`,
-	}, {
-		test("net", `net.IPv4() & "ff02::1:3"`),
-		`_|_(invalid value "ff02::1:3" (does not satisfy net.IPv4))`,
-	}, {
-		test("net", `net.LoopbackIP([127, 0, 0, 1])`),
-		`true`,
-	}, {
-		test("net", `net.LoopbackIP("127.0.0.1")`),
-		`true`,
-	}, {
-		test("net", `net.ToIP4("127.0.0.1")`),
-		`[127,0,0,1]`,
-	}, {
-		test("net", `net.ToIP16("127.0.0.1")`),
-		`[0,0,0,0,0,0,0,0,0,0,255,255,127,0,0,1]`,
-	}, {
-		test("strings", `strings.ToCamel("AlphaBeta")`),
-		`"alphaBeta"`,
-	}, {
-		test("strings", `strings.ToTitle("alpha")`),
-		`"Alpha"`,
-	}, {
-		test("strings", `strings.MaxRunes(3) & "foo"`),
-		`"foo"`,
-	}, {
-		test("strings", `strings.MaxRunes(3) & "quux"`),
-		`_|_(invalid value "quux" (does not satisfy strings.MaxRunes(3)))`,
-	}, {
-		test("strings", `strings.MinRunes(1) & "e"`),
-		`"e"`,
-	}, {
-		test("strings", `strings.MaxRunes(0) & "e"`),
-		`_|_(invalid value "e" (does not satisfy strings.MaxRunes(0)))`,
-	}, {
-		test("strings", `strings.MaxRunes(0) & ""`),
-		`""`,
-	}, {
-		test("strings", `strings.MinRunes(3) & "hello"`),
-		`"hello"`,
-	}, {
-		test("strings", `strings.MaxRunes(10) & "hello"`),
-		`"hello"`,
-	}, {
-		test("strings", `strings.MaxRunes(3) & "hello"`),
-		`_|_(invalid value "hello" (does not satisfy strings.MaxRunes(3)))`,
-	}, {
-		test("strings", `strings.MinRunes(10) & "hello"`),
-		`_|_(invalid value "hello" (does not satisfy strings.MinRunes(10)))`,
-	}, {
 		test("struct", `struct.MinFields(0) & ""`),
 		`_|_(conflicting values struct.MinFields(0) and "" (mismatched types struct and string))`,
 	}, {
@@ -565,103 +106,6 @@
 		test("struct", `struct.MinFields(2) & {a: 1}`),
 		`_|_(invalid value {a:1} (does not satisfy struct.MinFields(2)))`,
 	}, {
-		test("struct", `struct.MaxFields(0) & {a: 1}`),
-		`_|_(invalid value {a:1} (does not satisfy struct.MaxFields(0)))`,
-	}, {
-		test("struct", `struct.MaxFields(2) & {a: 1}`),
-		`{a:1}`,
-	}, {
-		test("math", `math.Pow(8, 4)`), `4096`,
-	}, {
-		test("math", `math.Pow10(4)`), `1E+4`,
-	}, {
-		test("math", `math.Signbit(-4)`), `true`,
-	}, {
-		test("math", `math.Round(2.5)`), `3`,
-	}, {
-		test("math", `math.Round(-2.5)`), `-3`,
-	}, {
-		test("math", `math.RoundToEven(2.5)`), `2`,
-	}, {
-		test("math", `math.RoundToEven(-2.5)`), `-2`,
-	}, {
-		test("math", `math.Abs(2.5)`), `2.5`,
-	}, {
-		test("math", `math.Abs(-2.2)`), `2.2`,
-	}, {
-		test("math", `math.Cbrt(2)`), `1.25992104989487316476721`,
-	}, {
-		test("math", `math.Copysign(5, -2.2)`), `-5`,
-	}, {
-		test("math", `math.Exp(3)`), `20.0855369231876677409285`,
-	}, {
-		test("math", `math.Exp2(3.5)`), `11.3137084989847603904135`,
-	}, {
-		test("math", `math.Log(4)`), `1.38629436111989061883446`,
-	}, {
-		test("math", `math.Log10(4)`), `0.602059991327962390427478`,
-	}, {
-		test("math", `math.Log2(5)`),
-		`2.32192809488736234787032`,
-	}, {
-		test("math", `math.Dim(3, 2.5)`), `0.5`,
-	}, {
-		test("math", `math.Dim(5, 7.2)`), `0`,
-	}, {
-		test("math", `math.Ceil(2.5)`), `3`,
-	}, {
-		test("math", `math.Ceil(-2.2)`), `-2`,
-	}, {
-		test("math", `math.Floor(2.9)`), `2`,
-	}, {
-		test("math", `math.Floor(-2.2)`), `-3`,
-	}, {
-		test("math", `math.Trunc(2.5)`), `2`,
-	}, {
-		test("math", `math.Trunc(-2.9)`), `-2`,
-	}, {
-		test("math/bits", `bits.Lsh(0x8, 4)`), `128`,
-	}, {
-		test("math/bits", `bits.Rsh(0x100, 4)`), `16`,
-	}, {
-		test("math/bits", `bits.At(0x100, 8)`), `1`,
-	}, {
-		test("math/bits", `bits.At(0x100, 9)`), `0`,
-	}, {
-		test("math/bits", `bits.Set(0x100, 7, 1)`), `384`,
-	}, {
-		test("math/bits", `bits.Set(0x100, 8, 0)`), `0`,
-	}, {
-		test("math/bits", `bits.And(0x10000000000000F0E, 0xF0F7)`), `6`,
-	}, {
-		test("math/bits", `bits.Or(0x100000000000000F0, 0x0F)`),
-		hexToDec("100000000000000FF"),
-	}, {
-		test("math/bits", `bits.Xor(0x10000000000000F0F, 0xFF0)`),
-		hexToDec("100000000000000FF"),
-	}, {
-		test("math/bits", `bits.Xor(0xFF0, 0x10000000000000F0F)`),
-		hexToDec("100000000000000FF"),
-	}, {
-		test("math/bits", `bits.Clear(0xF, 0x100000000000008)`), `7`,
-	}, {
-		test("math/bits", `bits.Clear(0x1000000000000000008, 0xF)`),
-		hexToDec("1000000000000000000"),
-	}, {
-		test("text/tabwriter", `tabwriter.Write("""
-			a\tb\tc
-			aaa\tbb\tvv
-			""")`),
-		`"a   b  c\naaa bb vv"`,
-	}, {
-		test("text/tabwriter", `tabwriter.Write([
-				"a\tb\tc",
-				"aaa\tbb\tvv"])`),
-		`"a   b  c\naaa bb vv\n"`,
-	}, {
-		test("text/template", `template.Execute("{{.}}-{{.}}", "foo")`),
-		`"foo-foo"`,
-	}, {
 		test("time", `time.Time & "1937-01-01T12:00:27.87+00:20"`),
 		`"1937-01-01T12:00:27.87+00:20"`,
 	}, {
diff --git a/genpkgtests.go b/genpkgtests.go
new file mode 100644
index 0000000..676bc32
--- /dev/null
+++ b/genpkgtests.go
@@ -0,0 +1,82 @@
+// +build ignore
+
+package main
+
+import (
+	"fmt"
+	"go/ast"
+	"go/parser"
+	"go/token"
+	"io/ioutil"
+	"os"
+
+	"strconv"
+
+	"github.com/rogpeppe/go-internal/txtar"
+)
+
+func main() {
+	fset := token.NewFileSet()
+	f, err := parser.ParseFile(fset, "./cue/builtin_test.go", nil, 0)
+	if err != nil {
+		fmt.Println(err)
+		return
+	}
+
+	m := map[string]*txtar.Archive{}
+	count := map[string]int{}
+
+	ast.Inspect(f, func(n ast.Node) bool {
+		call, ok := n.(*ast.CallExpr)
+		if !ok {
+			return true
+		}
+		ident, ok := call.Fun.(*ast.Ident)
+		if !ok || ident.Name != "test" {
+			return true
+		}
+
+		str := call.Args[0].(*ast.BasicLit)
+		pkg, _ := strconv.Unquote(str.Value)
+		a := &txtar.Archive{
+			Comment: []byte(
+				"# generated from the original tests.\n# Henceforth it may be nicer to group tests into separate files."),
+			Files: []txtar.File{{Name: "in.cue"}},
+		}
+		m[pkg] = a
+		return false
+	})
+
+	ast.Inspect(f, func(n ast.Node) bool {
+		call, ok := n.(*ast.CallExpr)
+		if !ok {
+			return true
+		}
+		ident, ok := call.Fun.(*ast.Ident)
+		if !ok || ident.Name != "test" {
+			return true
+		}
+
+		str := call.Args[0].(*ast.BasicLit)
+		pkg, _ := strconv.Unquote(str.Value)
+		str = call.Args[1].(*ast.BasicLit)
+		expr, err := strconv.Unquote(str.Value)
+		if err != nil {
+			panic(err)
+		}
+
+		a := m[pkg]
+		count[pkg]++
+
+		a.Files[0].Data = append(a.Files[0].Data,
+			fmt.Sprintf("t%d: %s\n", count[pkg], expr)...)
+
+		return false
+	})
+
+	for key, a := range m {
+		os.Mkdir(fmt.Sprintf("pkg/%s/testdata", key), 0755)
+		p := fmt.Sprintf("pkg/%s/testdata/gen.txtar", key)
+		ioutil.WriteFile(p, txtar.Format(a), 0644)
+	}
+}
diff --git a/pkg/crypto/md5/md5_test.go b/pkg/crypto/md5/md5_test.go
new file mode 100644
index 0000000..bba9bf7
--- /dev/null
+++ b/pkg/crypto/md5/md5_test.go
@@ -0,0 +1,25 @@
+// Copyright 2020 CUE Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package md5_test
+
+import (
+	"testing"
+
+	"cuelang.org/go/pkg/internal/builtintest"
+)
+
+func TestBuiltin(t *testing.T) {
+	builtintest.Run("md5", t)
+}
diff --git a/pkg/crypto/md5/testdata/gen.txtar b/pkg/crypto/md5/testdata/gen.txtar
new file mode 100644
index 0000000..b3879f7
--- /dev/null
+++ b/pkg/crypto/md5/testdata/gen.txtar
@@ -0,0 +1,10 @@
+# generated from the original tests.
+# Henceforth it may be nicer to group tests into separate files.
+-- in.cue --
+import "crypto/md5"
+
+t1: len(md5.Sum("hash me"))
+-- out/md5 --
+(struct){
+  t1: (int){ 16 }
+}
diff --git a/pkg/crypto/sha1/sha1_test.go b/pkg/crypto/sha1/sha1_test.go
new file mode 100644
index 0000000..b923c13
--- /dev/null
+++ b/pkg/crypto/sha1/sha1_test.go
@@ -0,0 +1,25 @@
+// Copyright 2020 CUE Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package sha1_test
+
+import (
+	"testing"
+
+	"cuelang.org/go/pkg/internal/builtintest"
+)
+
+func TestBuiltin(t *testing.T) {
+	builtintest.Run("sha1", t)
+}
diff --git a/pkg/crypto/sha1/testdata/gen.txtar b/pkg/crypto/sha1/testdata/gen.txtar
new file mode 100644
index 0000000..2eedefa
--- /dev/null
+++ b/pkg/crypto/sha1/testdata/gen.txtar
@@ -0,0 +1,10 @@
+# generated from the original tests.
+# Henceforth it may be nicer to group tests into separate files.
+-- in.cue --
+import "crypto/sha1"
+
+t1: len(sha1.Sum("hash me"))
+-- out/sha1 --
+(struct){
+  t1: (int){ 20 }
+}
diff --git a/pkg/crypto/sha256/sha256_test.go b/pkg/crypto/sha256/sha256_test.go
new file mode 100644
index 0000000..ac0599a
--- /dev/null
+++ b/pkg/crypto/sha256/sha256_test.go
@@ -0,0 +1,25 @@
+// Copyright 2020 CUE Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package sha256_test
+
+import (
+	"testing"
+
+	"cuelang.org/go/pkg/internal/builtintest"
+)
+
+func TestBuiltin(t *testing.T) {
+	builtintest.Run("sha256", t)
+}
diff --git a/pkg/crypto/sha256/testdata/gen.txtar b/pkg/crypto/sha256/testdata/gen.txtar
new file mode 100644
index 0000000..e615110
--- /dev/null
+++ b/pkg/crypto/sha256/testdata/gen.txtar
@@ -0,0 +1,14 @@
+# generated from the original tests.
+# Henceforth it may be nicer to group tests into separate files.
+-- in.cue --
+import "crypto/sha256"
+
+t1: sha256.Sum256("hash me")
+t2: len(sha256.Sum256("hash me"))
+t3: len(sha256.Sum224("hash me"))
+-- out/sha256 --
+(struct){
+  t1: (bytes){ '\xeb \x1a\xf5\xaa\xf0\xd6\x06)\xd3Ҧ\x1eFl\xfc\x0f\xed\xb5\x17\xad\xd81\xec\xacR5\xe1کc\xd6' }
+  t2: (int){ 32 }
+  t3: (int){ 28 }
+}
diff --git a/pkg/crypto/sha512/sha512_test.go b/pkg/crypto/sha512/sha512_test.go
new file mode 100644
index 0000000..31839ad
--- /dev/null
+++ b/pkg/crypto/sha512/sha512_test.go
@@ -0,0 +1,25 @@
+// Copyright 2020 CUE Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package sha512_test
+
+import (
+	"testing"
+
+	"cuelang.org/go/pkg/internal/builtintest"
+)
+
+func TestBuiltin(t *testing.T) {
+	builtintest.Run("sha512", t)
+}
diff --git a/pkg/crypto/sha512/testdata/gen.txtar b/pkg/crypto/sha512/testdata/gen.txtar
new file mode 100644
index 0000000..a97e3da
--- /dev/null
+++ b/pkg/crypto/sha512/testdata/gen.txtar
@@ -0,0 +1,16 @@
+# generated from the original tests.
+# Henceforth it may be nicer to group tests into separate files.
+-- in.cue --
+import "crypto/sha512"
+
+t1: len(sha512.Sum512("hash me"))
+t2: len(sha512.Sum384("hash me"))
+t3: len(sha512.Sum512_224("hash me"))
+t4: len(sha512.Sum512_256("hash me"))
+-- out/sha512 --
+(struct){
+  t1: (int){ 64 }
+  t2: (int){ 48 }
+  t3: (int){ 28 }
+  t4: (int){ 32 }
+}
diff --git a/pkg/encoding/base64/base64_test.go b/pkg/encoding/base64/base64_test.go
new file mode 100644
index 0000000..53e356f
--- /dev/null
+++ b/pkg/encoding/base64/base64_test.go
@@ -0,0 +1,25 @@
+// Copyright 2020 CUE Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package base64_test
+
+import (
+	"testing"
+
+	"cuelang.org/go/pkg/internal/builtintest"
+)
+
+func TestBuiltin(t *testing.T) {
+	builtintest.Run("base64", t)
+}
diff --git a/pkg/encoding/base64/testdata/gen.txtar b/pkg/encoding/base64/testdata/gen.txtar
new file mode 100644
index 0000000..f3fca2e
--- /dev/null
+++ b/pkg/encoding/base64/testdata/gen.txtar
@@ -0,0 +1,26 @@
+# generated from the original tests.
+# Henceforth it may be nicer to group tests into separate files.
+-- in.cue --
+import "encoding/base64"
+
+t1: base64.Encode(null, "foo")
+t2: base64.Decode(null, base64.Encode(null, "foo"))
+t3: base64.Decode(null, "foo")
+t4: base64.Decode({}, "foo")
+-- out/base64 --
+Errors:
+error in call to encoding/base64.Decode: base64: unsupported encoding: cannot use value {} (type struct) as null
+error in call to encoding/base64.Decode: illegal base64 data at input byte 0
+
+Result:
+(_|_){
+  // [eval]
+  t1: (string){ "Zm9v" }
+  t2: (bytes){ 'foo' }
+  t3: (_|_){
+    // [eval] error in call to encoding/base64.Decode: illegal base64 data at input byte 0
+  }
+  t4: (_|_){
+    // [eval] error in call to encoding/base64.Decode: base64: unsupported encoding: cannot use value {} (type struct) as null
+  }
+}
diff --git a/pkg/encoding/csv/csv_test.go b/pkg/encoding/csv/csv_test.go
new file mode 100644
index 0000000..f85b736
--- /dev/null
+++ b/pkg/encoding/csv/csv_test.go
@@ -0,0 +1,25 @@
+// Copyright 2020 CUE Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package csv_test
+
+import (
+	"testing"
+
+	"cuelang.org/go/pkg/internal/builtintest"
+)
+
+func TestBuiltin(t *testing.T) {
+	builtintest.Run("csv", t)
+}
diff --git a/pkg/encoding/csv/testdata/gen.txtar b/pkg/encoding/csv/testdata/gen.txtar
new file mode 100644
index 0000000..99b1fee
--- /dev/null
+++ b/pkg/encoding/csv/testdata/gen.txtar
@@ -0,0 +1,25 @@
+# generated from the original tests.
+# Henceforth it may be nicer to group tests into separate files.
+-- in.cue --
+import "encoding/csv"
+
+t1: csv.Decode("1,2,3\n4,5,6")
+t2: csv.Encode([[1,2,3],[4,5],[7,8,9]])
+t3: csv.Encode([["a", "b"], ["c"]])
+-- out/csv --
+(struct){
+  t1: (#list){
+    0: (#list){
+      0: (string){ "1" }
+      1: (string){ "2" }
+      2: (string){ "3" }
+    }
+    1: (#list){
+      0: (string){ "4" }
+      1: (string){ "5" }
+      2: (string){ "6" }
+    }
+  }
+  t2: (string){ "1,2,3\n4,5\n7,8,9\n" }
+  t3: (string){ "a,b\nc\n" }
+}
diff --git a/pkg/encoding/hex/hex_test.go b/pkg/encoding/hex/hex_test.go
new file mode 100644
index 0000000..4127126
--- /dev/null
+++ b/pkg/encoding/hex/hex_test.go
@@ -0,0 +1,25 @@
+// Copyright 2020 CUE Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package hex_test
+
+import (
+	"testing"
+
+	"cuelang.org/go/pkg/internal/builtintest"
+)
+
+func TestBuiltin(t *testing.T) {
+	builtintest.Run("hex", t)
+}
diff --git a/pkg/encoding/hex/testdata/gen.txtar b/pkg/encoding/hex/testdata/gen.txtar
new file mode 100644
index 0000000..9dfba7a
--- /dev/null
+++ b/pkg/encoding/hex/testdata/gen.txtar
@@ -0,0 +1,23 @@
+# generated from the original tests.
+# Henceforth it may be nicer to group tests into separate files.
+-- in.cue --
+import "encoding/hex"
+
+t1: hex.Encode("foo")
+t2: hex.Decode(hex.Encode("foo"))
+t3: hex.Decode("foo")
+t4: hex.Dump('foo')
+-- out/hex --
+Errors:
+error in call to encoding/hex.Decode: encoding/hex: invalid byte: U+006F 'o'
+
+Result:
+(_|_){
+  // [eval]
+  t1: (string){ "666f6f" }
+  t2: (bytes){ 'foo' }
+  t3: (_|_){
+    // [eval] error in call to encoding/hex.Decode: encoding/hex: invalid byte: U+006F 'o'
+  }
+  t4: (string){ "00000000  66 6f 6f                                          |foo|\n" }
+}
diff --git a/pkg/encoding/json/json_test.go b/pkg/encoding/json/json_test.go
new file mode 100644
index 0000000..9ab3f41
--- /dev/null
+++ b/pkg/encoding/json/json_test.go
@@ -0,0 +1,25 @@
+// Copyright 2020 CUE Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package json_test
+
+import (
+	"testing"
+
+	"cuelang.org/go/pkg/internal/builtintest"
+)
+
+func TestBuiltin(t *testing.T) {
+	builtintest.Run("json", t)
+}
diff --git a/pkg/encoding/json/testdata/gen.txtar b/pkg/encoding/json/testdata/gen.txtar
new file mode 100644
index 0000000..f07dbf7
--- /dev/null
+++ b/pkg/encoding/json/testdata/gen.txtar
@@ -0,0 +1,39 @@
+# generated from the original tests.
+# Henceforth it may be nicer to group tests into separate files.
+-- in.cue --
+import "encoding/json"
+
+t1: json.Validate("{\"a\":10}", {b:string})
+t2: json.Validate("{\"a\":10}", {a:<3})
+t3: json.Valid("1")
+t4: json.Compact("[1, 2]")
+t5: json.Indent(#"{"a": 1, "b": 2}"#, "", "  ")
+t6: json.Unmarshal("1")
+t7: json.MarshalStream([{a: 1}, {b: 2}])
+t8: {
+	x: int
+	y: json.Marshal({a: x})
+}
+-- out/json --
+Errors:
+a: error in call to encoding/json.Validate: invalid value 10 (out of bound <3)
+
+Result:
+(_|_){
+  // [eval]
+  t1: (bool){ true }
+  t2: (_|_){
+    // [eval] a: error in call to encoding/json.Validate: invalid value 10 (out of bound <3)
+  }
+  t3: (bool){ true }
+  t4: (string){ "[1,2]" }
+  t5: (string){ "{\n  \"a\": 1,\n  \"b\": 2\n}" }
+  t6: (int){ 1 }
+  t7: (string){ "{\"a\":1}\n{\"b\":2}\n" }
+  t8: (struct){
+    x: (int){ int }
+    y: (_|_){
+      // [incomplete] cannot convert incomplete value "int" to JSON
+    }
+  }
+}
diff --git a/pkg/encoding/yaml/testdata/gen.txtar b/pkg/encoding/yaml/testdata/gen.txtar
new file mode 100644
index 0000000..269680b
--- /dev/null
+++ b/pkg/encoding/yaml/testdata/gen.txtar
@@ -0,0 +1,35 @@
+# generated from the original tests.
+# Henceforth it may be nicer to group tests into separate files.
+-- in.cue --
+import "encoding/yaml"
+
+t1: yaml.Validate("a: 2\n---\na: 4", {a:<3})
+t2: yaml.Validate("a: 2\n---\na: 4", {a:<5})
+t3: yaml.Validate("a: 2\n", {a:<5, b:int})
+t4: yaml.ValidatePartial("a: 2\n---\na: 4", {a:<3})
+t5: yaml.ValidatePartial("a: 2\n---\na: 4", {a:<5})
+t6: yaml.ValidatePartial("a: 2\n", {a:<5, b:int})
+t7: yaml.MarshalStream([{a: 1}, {b: 2}])
+-- out/yaml --
+Errors:
+a: error in call to encoding/yaml.Validate: invalid value 4 (out of bound <3)
+a: error in call to encoding/yaml.ValidatePartial: invalid value 4 (out of bound <3)
+b: error in call to encoding/yaml.Validate: incomplete value int
+
+Result:
+(_|_){
+  // [eval]
+  t1: (_|_){
+    // [eval] a: error in call to encoding/yaml.Validate: invalid value 4 (out of bound <3)
+  }
+  t2: (bool){ true }
+  t3: (_|_){
+    // [eval] b: error in call to encoding/yaml.Validate: incomplete value int
+  }
+  t4: (_|_){
+    // [eval] a: error in call to encoding/yaml.ValidatePartial: invalid value 4 (out of bound <3)
+  }
+  t5: (bool){ true }
+  t6: (bool){ true }
+  t7: (string){ "a: 1\n---\nb: 2\n" }
+}
diff --git a/pkg/encoding/yaml/yaml_test.go b/pkg/encoding/yaml/yaml_test.go
new file mode 100644
index 0000000..1121a53
--- /dev/null
+++ b/pkg/encoding/yaml/yaml_test.go
@@ -0,0 +1,25 @@
+// Copyright 2020 CUE Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package yaml_test
+
+import (
+	"testing"
+
+	"cuelang.org/go/pkg/internal/builtintest"
+)
+
+func TestBuiltin(t *testing.T) {
+	builtintest.Run("yaml", t)
+}
diff --git a/pkg/internal/builtintest/testing.go b/pkg/internal/builtintest/testing.go
new file mode 100644
index 0000000..d61494e
--- /dev/null
+++ b/pkg/internal/builtintest/testing.go
@@ -0,0 +1,60 @@
+// Copyright 2020 CUE Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package builtintest
+
+import (
+	"fmt"
+	"testing"
+
+	"cuelang.org/go/cue"
+	"cuelang.org/go/internal/core/debug"
+	"cuelang.org/go/internal/core/eval"
+	"cuelang.org/go/internal/core/validate"
+	"cuelang.org/go/internal/cuetxtar"
+)
+
+func Run(name string, t *testing.T) {
+	test := cuetxtar.TxTarTest{
+		Root: "./testdata",
+		Name: name,
+	}
+
+	r := cue.NewRuntime()
+
+	test.Run(t, func(t *cuetxtar.Test) {
+		a := t.ValidInstances()
+
+		v, err := r.Build(a[0])
+		if err != nil {
+			t.Fatal(err)
+		}
+
+		e := eval.New(r)
+		ctx := e.NewContext(v)
+		v.Finalize(ctx)
+
+		if b := validate.Validate(ctx, v, &validate.Config{
+			AllErrors: true,
+		}); b != nil {
+			fmt.Fprintln(t, "Errors:")
+			t.WriteErrors(b.Err)
+			fmt.Fprintln(t, "")
+			fmt.Fprintln(t, "Result:")
+		}
+
+		debug.WriteNode(t, r, v, &debug.Config{Cwd: t.Dir})
+		fmt.Fprintln(t)
+	})
+}
diff --git a/pkg/list/list_test.go b/pkg/list/list_test.go
new file mode 100644
index 0000000..ba7f4d4
--- /dev/null
+++ b/pkg/list/list_test.go
@@ -0,0 +1,25 @@
+// Copyright 2020 CUE Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package list_test
+
+import (
+	"testing"
+
+	"cuelang.org/go/pkg/internal/builtintest"
+)
+
+func TestBuiltin(t *testing.T) {
+	builtintest.Run("list", t)
+}
diff --git a/pkg/list/testdata/gen.txtar b/pkg/list/testdata/gen.txtar
new file mode 100644
index 0000000..2061db7
--- /dev/null
+++ b/pkg/list/testdata/gen.txtar
@@ -0,0 +1,305 @@
+# generated from the original tests.
+# Henceforth it may be nicer to group tests into separate files.
+-- in.cue --
+import "list"
+
+t1: list.Avg([1, 2, 3, 4])
+t2: list.Avg([])
+t3: list.Avg("foo")
+t4: list.Drop([1, 2, 3, 4], 0)
+t5: list.Drop([1, 2, 3, 4], 2)
+t6: list.Drop([1, 2, 3, 4], 10)
+t7: list.Drop([1, 2, 3, 4], -1)
+t8: list.FlattenN([1, [[2, 3], []], [4]], -1)
+t9: list.FlattenN([1, [[2, 3], []], [4]], 0)
+t10: list.FlattenN([1, [[2, 3], []], [4]], 1)
+t11: list.FlattenN([1, [[2, 3], []], [4]], 2)
+t12: list.FlattenN([[1, 2] | *[]], -1)
+t13: list.FlattenN("foo", 1)
+t14: list.FlattenN([], "foo")
+t15: list.Max([1, 2, 3, 4])
+t16: list.Max([])
+t17: list.Max("foo")
+t18: list.Min([1, 2, 3, 4])
+t19: list.Min([])
+t20: list.Min("foo")
+t21: list.Product([1, 2, 3, 4])
+t22: list.Product([])
+t23: list.Product("foo")
+t24: list.Range(0, 5, 0)
+t25: list.Range(5, 0, 1)
+t26: list.Range(0, 5, -1)
+t27: list.Range(0, 5, 1)
+t28: list.Range(0, 1, 1)
+t29: list.Range(0, 5, 2)
+t30: list.Range(5, 0, -1)
+t31: list.Range(0, 5, 0.5)
+t32: list.Slice([1, 2, 3, 4], 1, 3)
+t33: list.Slice([1, 2, 3, 4], -1, 3)
+t34: list.Slice([1, 2, 3, 4], 3, 1)
+t35: list.Slice([1, 2, 3, 4], 5, 5)
+t36: list.Slice([1, 2, 3, 4], 1, 5)
+t37: list.Sort([], list.Ascending)
+t38: list.Sort([2, 3, 1, 4], {x:_, y:_, less: x<y})
+t39: list.SortStable([{a:2,v:1}, {a:1,v:2}, {a:1,v:3}], {
+			x:_,
+			y:_,
+			less: (x.a < y.a)
+		})
+t40: list.Sort([{a:1}, {b:2}], list.Ascending)
+t41: list.SortStrings(["b", "a"])
+t42: list.SortStrings([1, 2])
+t43: list.Sum([1, 2, 3, 4])
+t44: list.Sum([])
+t45: list.Sum("foo")
+t46: list.Take([1, 2, 3, 4], 0)
+t47: list.Take([1, 2, 3, 4], 2)
+t48: list.Take([1, 2, 3, 4], 10)
+t49: list.Take([1, 2, 3, 4], -1)
+t50: list.MinItems([1, 2, 3, 4], 2)
+t51: list.MinItems([1, 2, 3, 4], 5)
+t52: list.MaxItems([1, 2, 3, 4], 5)
+t53: list.MaxItems([1, 2, 3, 4], 2)
+t54: list.Sort([{a:1}, {b:2}], list.Ascending)
+-- out/list --
+Errors:
+error in call to list.Avg: empty list
+error in call to list.Drop: negative index
+error in call to list.FlattenN: cannot use value "foo" (type string) as list
+error in call to list.Max: empty list
+error in call to list.Min: empty list
+error in call to list.Range: end must be greater than start when step is positive
+error in call to list.Range: end must be less than start when step is negative
+error in call to list.Range: step must be non zero
+error in call to list.Slice: invalid index: 3 > 1
+error in call to list.Slice: negative index
+error in call to list.Slice: slice bounds out of range
+error in call to list.Take: negative index
+0: error in call to list.SortStrings: element 0 of list argument 0: cannot use value 1 (type int) as string
+x: error in call to list.Sort: x: conflicting values string and {b:2} (mismatched types string and struct) (and 1 more errors)
+t3: cannot use "foo" (type string) as list in argument 1 to list.Avg:
+    ./in.cue:5:14
+t14: cannot use "foo" (type string) as int in argument 2 to list.FlattenN:
+    ./in.cue:16:24
+t17: cannot use "foo" (type string) as list in argument 1 to list.Max:
+    ./in.cue:19:15
+t20: cannot use "foo" (type string) as list in argument 1 to list.Min:
+    ./in.cue:22:15
+t23: cannot use "foo" (type string) as list in argument 1 to list.Product:
+    ./in.cue:25:19
+t45: cannot use "foo" (type string) as list in argument 1 to list.Sum:
+    ./in.cue:51:15
+
+Result:
+(_|_){
+  // [eval]
+  t1: (number){ 2.5 }
+  t2: (_|_){
+    // [eval] error in call to list.Avg: empty list
+  }
+  t3: (_|_){
+    // [eval] t3: cannot use "foo" (type string) as list in argument 1 to list.Avg:
+    //     ./in.cue:5:14
+  }
+  t4: (#list){
+    0: (int){ 1 }
+    1: (int){ 2 }
+    2: (int){ 3 }
+    3: (int){ 4 }
+  }
+  t5: (#list){
+    0: (int){ 3 }
+    1: (int){ 4 }
+  }
+  t6: (#list){
+  }
+  t7: (_|_){
+    // [eval] error in call to list.Drop: negative index
+  }
+  t8: (#list){
+    0: (int){ 1 }
+    1: (int){ 2 }
+    2: (int){ 3 }
+    3: (int){ 4 }
+  }
+  t9: (#list){
+    0: (int){ 1 }
+    1: (#list){
+      0: (#list){
+        0: (int){ 2 }
+        1: (int){ 3 }
+      }
+      1: (#list){
+      }
+    }
+    2: (#list){
+      0: (int){ 4 }
+    }
+  }
+  t10: (#list){
+    0: (int){ 1 }
+    1: (#list){
+      0: (int){ 2 }
+      1: (int){ 3 }
+    }
+    2: (#list){
+    }
+    3: (int){ 4 }
+  }
+  t11: (#list){
+    0: (int){ 1 }
+    1: (int){ 2 }
+    2: (int){ 3 }
+    3: (int){ 4 }
+  }
+  t12: (#list){
+  }
+  t13: (_|_){
+    // [eval] error in call to list.FlattenN: cannot use value "foo" (type string) as list
+  }
+  t14: (_|_){
+    // [eval] t14: cannot use "foo" (type string) as int in argument 2 to list.FlattenN:
+    //     ./in.cue:16:24
+  }
+  t15: (number){ 4 }
+  t16: (_|_){
+    // [eval] error in call to list.Max: empty list
+  }
+  t17: (_|_){
+    // [eval] t17: cannot use "foo" (type string) as list in argument 1 to list.Max:
+    //     ./in.cue:19:15
+  }
+  t18: (number){ 1 }
+  t19: (_|_){
+    // [eval] error in call to list.Min: empty list
+  }
+  t20: (_|_){
+    // [eval] t20: cannot use "foo" (type string) as list in argument 1 to list.Min:
+    //     ./in.cue:22:15
+  }
+  t21: (number){ 24 }
+  t22: (number){ 1 }
+  t23: (_|_){
+    // [eval] t23: cannot use "foo" (type string) as list in argument 1 to list.Product:
+    //     ./in.cue:25:19
+  }
+  t24: (_|_){
+    // [eval] error in call to list.Range: step must be non zero
+  }
+  t25: (_|_){
+    // [eval] error in call to list.Range: end must be greater than start when step is positive
+  }
+  t26: (_|_){
+    // [eval] error in call to list.Range: end must be less than start when step is negative
+  }
+  t27: (#list){
+    0: (number){ 0 }
+    1: (number){ 1 }
+    2: (number){ 2 }
+    3: (number){ 3 }
+    4: (number){ 4 }
+  }
+  t28: (#list){
+    0: (number){ 0 }
+  }
+  t29: (#list){
+    0: (number){ 0 }
+    1: (number){ 2 }
+    2: (number){ 4 }
+  }
+  t30: (#list){
+    0: (number){ 5 }
+    1: (number){ 4 }
+    2: (number){ 3 }
+    3: (number){ 2 }
+    4: (number){ 1 }
+  }
+  t31: (#list){
+    0: (number){ 0 }
+    1: (number){ 0.5 }
+    2: (number){ 1.0 }
+    3: (number){ 1.5 }
+    4: (number){ 2.0 }
+    5: (number){ 2.5 }
+    6: (number){ 3.0 }
+    7: (number){ 3.5 }
+    8: (number){ 4.0 }
+    9: (number){ 4.5 }
+  }
+  t32: (#list){
+    0: (int){ 2 }
+    1: (int){ 3 }
+  }
+  t33: (_|_){
+    // [eval] error in call to list.Slice: negative index
+  }
+  t34: (_|_){
+    // [eval] error in call to list.Slice: invalid index: 3 > 1
+  }
+  t35: (_|_){
+    // [eval] error in call to list.Slice: slice bounds out of range
+  }
+  t36: (_|_){
+    // [eval] error in call to list.Slice: slice bounds out of range
+  }
+  t37: (#list){
+  }
+  t38: (#list){
+    0: (int){ 1 }
+    1: (int){ 2 }
+    2: (int){ 3 }
+    3: (int){ 4 }
+  }
+  t39: (#list){
+    0: (struct){
+      a: (int){ 1 }
+      v: (int){ 2 }
+    }
+    1: (struct){
+      a: (int){ 1 }
+      v: (int){ 3 }
+    }
+    2: (struct){
+      a: (int){ 2 }
+      v: (int){ 1 }
+    }
+  }
+  t40: (_|_){
+    // [eval] x: error in call to list.Sort: x: conflicting values string and {b:2} (mismatched types string and struct) (and 1 more errors)
+  }
+  t41: (#list){
+    0: (string){ "a" }
+    1: (string){ "b" }
+  }
+  t42: (_|_){
+    // [eval] 0: error in call to list.SortStrings: element 0 of list argument 0: cannot use value 1 (type int) as string
+  }
+  t43: (number){ 10 }
+  t44: (number){ 0 }
+  t45: (_|_){
+    // [eval] t45: cannot use "foo" (type string) as list in argument 1 to list.Sum:
+    //     ./in.cue:51:15
+  }
+  t46: (#list){
+  }
+  t47: (#list){
+    0: (int){ 1 }
+    1: (int){ 2 }
+  }
+  t48: (#list){
+    0: (int){ 1 }
+    1: (int){ 2 }
+    2: (int){ 3 }
+    3: (int){ 4 }
+  }
+  t49: (_|_){
+    // [eval] error in call to list.Take: negative index
+  }
+  t50: (bool){ true }
+  t51: (bool){ false }
+  t52: (bool){ true }
+  t53: (bool){ false }
+  t54: (_|_){
+    // [eval] x: error in call to list.Sort: x: conflicting values string and {b:2} (mismatched types string and struct) (and 1 more errors)
+  }
+}
diff --git a/pkg/math/bits/bits_test.go b/pkg/math/bits/bits_test.go
new file mode 100644
index 0000000..46973bd
--- /dev/null
+++ b/pkg/math/bits/bits_test.go
@@ -0,0 +1,25 @@
+// Copyright 2020 CUE Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package bits_test
+
+import (
+	"testing"
+
+	"cuelang.org/go/pkg/internal/builtintest"
+)
+
+func TestBuiltin(t *testing.T) {
+	builtintest.Run("bits", t)
+}
diff --git a/pkg/math/bits/testdata/gen.txtar b/pkg/math/bits/testdata/gen.txtar
new file mode 100644
index 0000000..af483ac
--- /dev/null
+++ b/pkg/math/bits/testdata/gen.txtar
@@ -0,0 +1,34 @@
+# generated from the original tests.
+# Henceforth it may be nicer to group tests into separate files.
+-- in.cue --
+import "math/bits"
+
+t1: bits.Or(0x8, 0x1)
+t2: bits.Lsh(0x8, 4)
+t3: bits.Rsh(0x100, 4)
+t4: bits.At(0x100, 8)
+t5: bits.At(0x100, 9)
+t6: bits.Set(0x100, 7, 1)
+t7: bits.Set(0x100, 8, 0)
+t8: bits.And(0x10000000000000F0E, 0xF0F7)
+t9: bits.Or(0x100000000000000F0, 0x0F)
+t10: bits.Xor(0x10000000000000F0F, 0xFF0)
+t11: bits.Xor(0xFF0, 0x10000000000000F0F)
+t12: bits.Clear(0xF, 0x100000000000008)
+t13: bits.Clear(0x1000000000000000008, 0xF)
+-- out/bits --
+(struct){
+  t1: (int){ 9 }
+  t2: (int){ 128 }
+  t3: (int){ 16 }
+  t4: (int){ 1 }
+  t5: (int){ 0 }
+  t6: (int){ 384 }
+  t7: (int){ 0 }
+  t8: (int){ 6 }
+  t9: (int){ 18446744073709551871 }
+  t10: (int){ 18446744073709551871 }
+  t11: (int){ 18446744073709551871 }
+  t12: (int){ 7 }
+  t13: (int){ 4722366482869645213696 }
+}
diff --git a/pkg/math/math_test.go b/pkg/math/math_test.go
new file mode 100644
index 0000000..f764ad8
--- /dev/null
+++ b/pkg/math/math_test.go
@@ -0,0 +1,25 @@
+// Copyright 2020 CUE Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package math_test
+
+import (
+	"testing"
+
+	"cuelang.org/go/pkg/internal/builtintest"
+)
+
+func TestBuiltin(t *testing.T) {
+	builtintest.Run("math", t)
+}
diff --git a/pkg/math/testdata/gen.txtar b/pkg/math/testdata/gen.txtar
new file mode 100644
index 0000000..aa29913
--- /dev/null
+++ b/pkg/math/testdata/gen.txtar
@@ -0,0 +1,116 @@
+# generated from the original tests.
+# Henceforth it may be nicer to group tests into separate files.
+-- in.cue --
+import "math"
+
+t1: math.Pi
+t2: math.Floor(math.Pi)
+t3: math.Pi(3)
+t4: math.Floor(3, 5)
+t5: math.Floor("foo")
+t6: math.Jacobi(1000, 2000)
+t7: math.Jacobi(1000, 201)
+t8: math.Asin(2.0e400)
+t9: math.MultipleOf(4, 2)
+t10: math.MultipleOf(5, 2)
+t11: math.MultipleOf(5, 0)
+t12: math.MultipleOf(100, 1.00001)
+t13: math.MultipleOf(1, 1)
+t14: math.MultipleOf(5, 2.5)
+t15: math.MultipleOf(100e100, 10)
+t16: math.Pow(8, 4)
+t17: math.Pow10(4)
+t18: math.Signbit(-4)
+t19: math.Round(2.5)
+t20: math.Round(-2.5)
+t21: math.RoundToEven(2.5)
+t22: math.RoundToEven(-2.5)
+t23: math.Abs(2.5)
+t24: math.Abs(-2.2)
+t25: math.Cbrt(2)
+t26: math.Copysign(5, -2.2)
+t27: math.Exp(3)
+t28: math.Exp2(3.5)
+t29: math.Log(4)
+t30: math.Log10(4)
+t31: math.Log2(5)
+t32: math.Dim(3, 2.5)
+t33: math.Dim(5, 7.2)
+t34: math.Ceil(2.5)
+t35: math.Ceil(-2.2)
+t36: math.Floor(2.9)
+t37: math.Floor(-2.2)
+t38: math.Trunc(2.5)
+t39: math.Trunc(-2.9)
+-- out/math --
+Errors:
+error in call to math.Jacobi: big: invalid 2nd argument to Int.Jacobi: need odd integer but got 2000
+error in call to math.MultipleOf: division by zero
+t3: cannot call non-function math.Pi (type float):
+    ./in.cue:5:5
+t4: too many arguments in call to math.Floor (have 2, want 1):
+    ./in.cue:6:20
+t5: cannot use "foo" (type string) as number in argument 1 to math.Floor:
+    ./in.cue:7:16
+cannot use 2.0E+400 (type float) as float64 in argument 0 to math.Asin: value was rounded up:
+    ./in.cue:10:5
+
+Result:
+(_|_){
+  // [eval]
+  t1: (float){ 3.14159265358979323846264338327950288419716939937510582097494459 }
+  t2: (number){ 3 }
+  t3: (_|_){
+    // [eval] t3: cannot call non-function math.Pi (type float):
+    //     ./in.cue:5:5
+  }
+  t4: (_|_){
+    // [eval] t4: too many arguments in call to math.Floor (have 2, want 1):
+    //     ./in.cue:6:20
+  }
+  t5: (_|_){
+    // [eval] t5: cannot use "foo" (type string) as number in argument 1 to math.Floor:
+    //     ./in.cue:7:16
+  }
+  t6: (_|_){
+    // [eval] error in call to math.Jacobi: big: invalid 2nd argument to Int.Jacobi: need odd integer but got 2000
+  }
+  t7: (int){ 1 }
+  t8: (_|_){
+    // [eval] cannot use 2.0E+400 (type float) as float64 in argument 0 to math.Asin: value was rounded up:
+    //     ./in.cue:10:5
+  }
+  t9: (bool){ true }
+  t10: (bool){ false }
+  t11: (_|_){
+    // [eval] error in call to math.MultipleOf: division by zero
+  }
+  t12: (bool){ false }
+  t13: (bool){ true }
+  t14: (bool){ true }
+  t15: (bool){ true }
+  t16: (number){ 4096 }
+  t17: (number){ 1E+4 }
+  t18: (bool){ true }
+  t19: (number){ 3 }
+  t20: (number){ -3 }
+  t21: (number){ 2 }
+  t22: (number){ -2 }
+  t23: (number){ 2.5 }
+  t24: (number){ 2.2 }
+  t25: (number){ 1.25992104989487316476721 }
+  t26: (number){ -5 }
+  t27: (number){ 20.0855369231876677409285 }
+  t28: (number){ 11.3137084989847603904135 }
+  t29: (number){ 1.38629436111989061883446 }
+  t30: (number){ 0.602059991327962390427478 }
+  t31: (number){ 2.32192809488736234787032 }
+  t32: (number){ 0.5 }
+  t33: (number){ 0 }
+  t34: (number){ 3 }
+  t35: (number){ -2 }
+  t36: (number){ 2 }
+  t37: (number){ -3 }
+  t38: (number){ 2 }
+  t39: (number){ -2 }
+}
diff --git a/pkg/net/net_test.go b/pkg/net/net_test.go
new file mode 100644
index 0000000..2ec22a2
--- /dev/null
+++ b/pkg/net/net_test.go
@@ -0,0 +1,25 @@
+// Copyright 2020 CUE Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package net_test
+
+import (
+	"testing"
+
+	"cuelang.org/go/pkg/internal/builtintest"
+)
+
+func TestBuiltin(t *testing.T) {
+	builtintest.Run("net", t)
+}
diff --git a/pkg/net/testdata/gen.txtar b/pkg/net/testdata/gen.txtar
new file mode 100644
index 0000000..7d76d17
--- /dev/null
+++ b/pkg/net/testdata/gen.txtar
@@ -0,0 +1,82 @@
+# generated from the original tests.
+# Henceforth it may be nicer to group tests into separate files.
+-- in.cue --
+import "net"
+
+t1: net.FQDN & "foo.bar."
+t2: net.FQDN("foo.bararararararararararararararararararararararararararararararararara")
+t3: net.SplitHostPort("[::%lo0]:80")
+t4: net.JoinHostPort("example.com", "80")
+t5: net.JoinHostPort("2001:db8::1", 80)
+t6: net.JoinHostPort([192,30,4,2], 80)
+t7: net.JoinHostPort([192, 30, 4], 80)
+t8: net.IP("23.23.23.23")
+t9: net.IPv4 & "23.23.23.2333"
+t10: net.IP("23.23.23.23")
+t11: net.IP("2001:db8::1")
+t12: net.IPv4("2001:db8::1")
+t13: net.IPv4() & "ff02::1:3"
+t14: net.LoopbackIP([127, 0, 0, 1])
+t15: net.LoopbackIP("127.0.0.1")
+t16: net.ToIP4("127.0.0.1")
+t17: net.ToIP16("127.0.0.1")
+-- out/net --
+Errors:
+error in call to net.JoinHostPort: invalid host [192, 30, 4]
+t9: invalid value "23.23.23.2333" (does not satisfy net.IPv4)
+t13: invalid value "ff02::1:3" (does not satisfy net.IPv4):
+    ./in.cue:15:6
+
+Result:
+(_|_){
+  // [eval]
+  t1: (string){ "foo.bar." }
+  t2: (bool){ false }
+  t3: (#list){
+    0: (string){ "::%lo0" }
+    1: (string){ "80" }
+  }
+  t4: (string){ "example.com:80" }
+  t5: (string){ "[2001:db8::1]:80" }
+  t6: (string){ "192.30.4.2:80" }
+  t7: (_|_){
+    // [eval] error in call to net.JoinHostPort: invalid host [192, 30, 4]
+  }
+  t8: (bool){ true }
+  t9: (_|_){
+    // [eval] t9: invalid value "23.23.23.2333" (does not satisfy net.IPv4)
+  }
+  t10: (bool){ true }
+  t11: (bool){ true }
+  t12: (bool){ false }
+  t13: (_|_){
+    // [eval] t13: invalid value "ff02::1:3" (does not satisfy net.IPv4):
+    //     ./in.cue:15:6
+  }
+  t14: (bool){ true }
+  t15: (bool){ true }
+  t16: (#list){
+    0: (int){ 127 }
+    1: (int){ 0 }
+    2: (int){ 0 }
+    3: (int){ 1 }
+  }
+  t17: (#list){
+    0: (int){ 0 }
+    1: (int){ 0 }
+    2: (int){ 0 }
+    3: (int){ 0 }
+    4: (int){ 0 }
+    5: (int){ 0 }
+    6: (int){ 0 }
+    7: (int){ 0 }
+    8: (int){ 0 }
+    9: (int){ 0 }
+    10: (int){ 255 }
+    11: (int){ 255 }
+    12: (int){ 127 }
+    13: (int){ 0 }
+    14: (int){ 0 }
+    15: (int){ 1 }
+  }
+}
diff --git a/pkg/regexp/regexp_test.go b/pkg/regexp/regexp_test.go
new file mode 100644
index 0000000..f3bd0fd
--- /dev/null
+++ b/pkg/regexp/regexp_test.go
@@ -0,0 +1,25 @@
+// Copyright 2020 CUE Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package regexp_test
+
+import (
+	"testing"
+
+	"cuelang.org/go/pkg/internal/builtintest"
+)
+
+func TestBuiltin(t *testing.T) {
+	builtintest.Run("regexp", t)
+}
diff --git a/pkg/regexp/testdata/gen.txtar b/pkg/regexp/testdata/gen.txtar
new file mode 100644
index 0000000..5400e86
--- /dev/null
+++ b/pkg/regexp/testdata/gen.txtar
@@ -0,0 +1,101 @@
+# generated from the original tests.
+# Henceforth it may be nicer to group tests into separate files.
+-- in.cue --
+import "regexp"
+
+t1: regexp.Find(#"f\w\w"#, "afoot")
+t2: regexp.Find(#"f\w\w"#, "bar")
+t3: regexp.FindAll(#"f\w\w"#, "afoot afloat from", 2)
+t4: regexp.FindAll(#"f\w\w"#, "afoot afloat from", 2)
+t5: regexp.FindAll(#"f\w\w"#, "bla bla", -1)
+t6: regexp.FindSubmatch(#"f(\w)(\w)"#, "afloat afoot from")
+t7: regexp.FindAllSubmatch(#"f(\w)(\w)"#, "afloat afoot from", -1)
+t8: regexp.FindAllSubmatch(#"f(\w)(\w)"#, "aglom", -1)
+t9: regexp.FindNamedSubmatch(#"f(?P<A>\w)(?P<B>\w)"#, "afloat afoot from")
+t10: regexp.FindAllNamedSubmatch(#"f(?P<A>\w)(?P<B>\w)"#, "afloat afoot from", -1)
+t11: regexp.FindAllNamedSubmatch(#"f(?P<A>optional)?"#, "fbla", -1)
+t12: regexp.FindAllNamedSubmatch(#"f(?P<A>\w)(?P<B>\w)"#, "aglom", -1)
+t13: regexp.Valid & "valid"
+t14: regexp.Valid & "invalid)"
+-- out/regexp --
+Errors:
+error in call to regexp.Find: no match
+error in call to regexp.FindAll: no match
+error in call to regexp.FindAllNamedSubmatch: no match
+error in call to regexp.FindAllSubmatch: no match
+error in call to regexp.Valid: error parsing regexp: unexpected ): `invalid)`
+
+Result:
+(_|_){
+  // [eval]
+  t1: (string){ "foo" }
+  t2: (_|_){
+    // [eval] error in call to regexp.Find: no match
+  }
+  t3: (#list){
+    0: (string){ "foo" }
+    1: (string){ "flo" }
+  }
+  t4: (#list){
+    0: (string){ "foo" }
+    1: (string){ "flo" }
+  }
+  t5: (_|_){
+    // [eval] error in call to regexp.FindAll: no match
+  }
+  t6: (#list){
+    0: (string){ "flo" }
+    1: (string){ "l" }
+    2: (string){ "o" }
+  }
+  t7: (#list){
+    0: (#list){
+      0: (string){ "flo" }
+      1: (string){ "l" }
+      2: (string){ "o" }
+    }
+    1: (#list){
+      0: (string){ "foo" }
+      1: (string){ "o" }
+      2: (string){ "o" }
+    }
+    2: (#list){
+      0: (string){ "fro" }
+      1: (string){ "r" }
+      2: (string){ "o" }
+    }
+  }
+  t8: (_|_){
+    // [eval] error in call to regexp.FindAllSubmatch: no match
+  }
+  t9: (struct){
+    A: (string){ "l" }
+    B: (string){ "o" }
+  }
+  t10: (#list){
+    0: (struct){
+      A: (string){ "l" }
+      B: (string){ "o" }
+    }
+    1: (struct){
+      A: (string){ "o" }
+      B: (string){ "o" }
+    }
+    2: (struct){
+      A: (string){ "r" }
+      B: (string){ "o" }
+    }
+  }
+  t11: (#list){
+    0: (struct){
+      A: (string){ "" }
+    }
+  }
+  t12: (_|_){
+    // [eval] error in call to regexp.FindAllNamedSubmatch: no match
+  }
+  t13: (string){ "valid" }
+  t14: (_|_){
+    // [eval] error in call to regexp.Valid: error parsing regexp: unexpected ): `invalid)`
+  }
+}
diff --git a/pkg/strconv/strconv_test.go b/pkg/strconv/strconv_test.go
new file mode 100644
index 0000000..eb6268d
--- /dev/null
+++ b/pkg/strconv/strconv_test.go
@@ -0,0 +1,25 @@
+// Copyright 2020 CUE Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package strconv_test
+
+import (
+	"testing"
+
+	"cuelang.org/go/pkg/internal/builtintest"
+)
+
+func TestBuiltin(t *testing.T) {
+	builtintest.Run("strconv", t)
+}
diff --git a/pkg/strconv/testdata/gen.txtar b/pkg/strconv/testdata/gen.txtar
new file mode 100644
index 0000000..479d204
--- /dev/null
+++ b/pkg/strconv/testdata/gen.txtar
@@ -0,0 +1,37 @@
+# generated from the original tests.
+# Henceforth it may be nicer to group tests into separate files.
+-- in.cue --
+import "strconv"
+
+t1: strconv.FormatUint(64, 16)
+t2: strconv.FormatFloat(3.02, 300, 4, 64)
+t3: strconv.FormatFloat(3.02, -1, 4, 64)
+t4: strconv.FormatFloat(3.02, 1.0, 4, 64)
+t5: strconv.FormatBool(true)
+-- out/strconv --
+Errors:
+int 300 overflows byte in argument 1 in call to strconv.FormatFloat:
+    ./in.cue:4:5
+cannot use -1 (type int) as byte in argument 1 to strconv.FormatFloat:
+    ./in.cue:5:5
+t4: cannot use 1.0 (type float) as int in argument 2 to strconv.FormatFloat:
+    ./in.cue:6:31
+
+Result:
+(_|_){
+  // [eval]
+  t1: (string){ "40" }
+  t2: (_|_){
+    // [eval] int 300 overflows byte in argument 1 in call to strconv.FormatFloat:
+    //     ./in.cue:4:5
+  }
+  t3: (_|_){
+    // [eval] cannot use -1 (type int) as byte in argument 1 to strconv.FormatFloat:
+    //     ./in.cue:5:5
+  }
+  t4: (_|_){
+    // [eval] t4: cannot use 1.0 (type float) as int in argument 2 to strconv.FormatFloat:
+    //     ./in.cue:6:31
+  }
+  t5: (string){ "true" }
+}
diff --git a/pkg/strings/strings_test.go b/pkg/strings/strings_test.go
new file mode 100644
index 0000000..60ca236
--- /dev/null
+++ b/pkg/strings/strings_test.go
@@ -0,0 +1,25 @@
+// Copyright 2020 CUE Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package strings_test
+
+import (
+	"testing"
+
+	"cuelang.org/go/pkg/internal/builtintest"
+)
+
+func TestBuiltin(t *testing.T) {
+	builtintest.Run("strings", t)
+}
diff --git a/pkg/strings/testdata/gen.txtar b/pkg/strings/testdata/gen.txtar
new file mode 100644
index 0000000..c06cf77
--- /dev/null
+++ b/pkg/strings/testdata/gen.txtar
@@ -0,0 +1,74 @@
+# generated from the original tests.
+# Henceforth it may be nicer to group tests into separate files.
+-- in.cue --
+import "strings"
+
+t1: strings.Join(["Hello", "World!"], " ")
+t2: strings.Join([1, 2], " ")
+t3: strings.ByteAt("a", 0)
+t4: strings.ByteSlice("Hello", 2, 5)
+t5: strings.SliceRunes("✓ Hello", 0, 3)
+t6: strings.Runes("Café")
+t7: strings.ToCamel("AlphaBeta")
+t8: strings.ToTitle("alpha")
+t9: strings.MaxRunes(3) & "foo"
+t10: strings.MaxRunes(3) & "quux"
+t11: strings.MinRunes(1) & "e"
+t12: strings.MaxRunes(0) & "e"
+t13: strings.MaxRunes(0) & ""
+t14: strings.MinRunes(3) & "hello"
+t15: strings.MaxRunes(10) & "hello"
+t16: strings.MaxRunes(3) & "hello"
+t17: strings.MinRunes(10) & "hello"
+-- out/strings --
+Errors:
+0: error in call to strings.Join: element 0 of list argument 0: cannot use value 1 (type int) as string
+t10: invalid value "quux" (does not satisfy strings.MaxRunes(3)):
+    ./in.cue:12:6
+t12: invalid value "e" (does not satisfy strings.MaxRunes(0)):
+    ./in.cue:14:6
+t16: invalid value "hello" (does not satisfy strings.MaxRunes(3)):
+    ./in.cue:18:6
+t17: invalid value "hello" (does not satisfy strings.MinRunes(10)):
+    ./in.cue:19:6
+
+Result:
+(_|_){
+  // [eval]
+  t1: (string){ "Hello World!" }
+  t2: (_|_){
+    // [eval] 0: error in call to strings.Join: element 0 of list argument 0: cannot use value 1 (type int) as string
+  }
+  t3: (int){ 97 }
+  t4: (bytes){ 'llo' }
+  t5: (string){ "✓ H" }
+  t6: (#list){
+    0: (int){ 67 }
+    1: (int){ 97 }
+    2: (int){ 102 }
+    3: (int){ 233 }
+  }
+  t7: (string){ "alphaBeta" }
+  t8: (string){ "Alpha" }
+  t9: (string){ "foo" }
+  t10: (_|_){
+    // [eval] t10: invalid value "quux" (does not satisfy strings.MaxRunes(3)):
+    //     ./in.cue:12:6
+  }
+  t11: (string){ "e" }
+  t12: (_|_){
+    // [eval] t12: invalid value "e" (does not satisfy strings.MaxRunes(0)):
+    //     ./in.cue:14:6
+  }
+  t13: (string){ "" }
+  t14: (string){ "hello" }
+  t15: (string){ "hello" }
+  t16: (_|_){
+    // [eval] t16: invalid value "hello" (does not satisfy strings.MaxRunes(3)):
+    //     ./in.cue:18:6
+  }
+  t17: (_|_){
+    // [eval] t17: invalid value "hello" (does not satisfy strings.MinRunes(10)):
+    //     ./in.cue:19:6
+  }
+}
diff --git a/pkg/struct/structs_test.go b/pkg/struct/structs_test.go
new file mode 100644
index 0000000..f42e540
--- /dev/null
+++ b/pkg/struct/structs_test.go
@@ -0,0 +1,25 @@
+// Copyright 2020 CUE Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package structs_test
+
+import (
+	"testing"
+
+	"cuelang.org/go/pkg/internal/builtintest"
+)
+
+func TestBuiltin(t *testing.T) {
+	builtintest.Run("structs", t)
+}
diff --git a/pkg/struct/testdata/gen.txtar b/pkg/struct/testdata/gen.txtar
new file mode 100644
index 0000000..2b5e7b5
--- /dev/null
+++ b/pkg/struct/testdata/gen.txtar
@@ -0,0 +1,41 @@
+# generated from the original tests.
+# Henceforth it may be nicer to group tests into separate files.
+-- in.cue --
+import "struct"
+
+t1: struct.MinFields(0) & ""
+t2: struct.MinFields(0) & {a: 1}
+t3: struct.MinFields(2) & {a: 1}
+t4: struct.MaxFields(0) & {a: 1}
+t5: struct.MaxFields(2) & {a: 1}
+-- out/structs --
+Errors:
+t1: conflicting values struct.MinFields(0) and "" (mismatched types struct and string)
+t3: invalid value {a:1} (does not satisfy struct.MinFields(2)):
+    ./in.cue:5:5
+t4: invalid value {a:1} (does not satisfy struct.MaxFields(0)):
+    ./in.cue:6:5
+
+Result:
+(_|_){
+  // [eval]
+  t1: (_|_){
+    // [eval] t1: conflicting values struct.MinFields(0) and "" (mismatched types struct and string)
+  }
+  t2: (struct){
+    a: (int){ 1 }
+  }
+  t3: (_|_){
+    // [eval] t3: invalid value {a:1} (does not satisfy struct.MinFields(2)):
+    //     ./in.cue:5:5
+    a: (int){ 1 }
+  }
+  t4: (_|_){
+    // [eval] t4: invalid value {a:1} (does not satisfy struct.MaxFields(0)):
+    //     ./in.cue:6:5
+    a: (int){ 1 }
+  }
+  t5: (struct){
+    a: (int){ 1 }
+  }
+}
diff --git a/pkg/text/tabwriter/tabwriter_test.go b/pkg/text/tabwriter/tabwriter_test.go
new file mode 100644
index 0000000..2815d30
--- /dev/null
+++ b/pkg/text/tabwriter/tabwriter_test.go
@@ -0,0 +1,25 @@
+// Copyright 2020 CUE Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package tabwriter_test
+
+import (
+	"testing"
+
+	"cuelang.org/go/pkg/internal/builtintest"
+)
+
+func TestBuiltin(t *testing.T) {
+	builtintest.Run("tabwriter", t)
+}
diff --git a/pkg/text/tabwriter/testdata/gen.txtar b/pkg/text/tabwriter/testdata/gen.txtar
new file mode 100644
index 0000000..41c88eb
--- /dev/null
+++ b/pkg/text/tabwriter/testdata/gen.txtar
@@ -0,0 +1,17 @@
+# generated from the original tests.
+# Henceforth it may be nicer to group tests into separate files.
+-- in.cue --
+import "text/tabwriter"
+
+t1: tabwriter.Write("""
+			a\tb\tc
+			aaa\tbb\tvv
+			""")
+t2: tabwriter.Write([
+				"a\tb\tc",
+				"aaa\tbb\tvv"])
+-- out/tabwriter --
+(struct){
+  t1: (string){ "a   b  c\naaa bb vv" }
+  t2: (string){ "a   b  c\naaa bb vv\n" }
+}
diff --git a/pkg/text/template/template_test.go b/pkg/text/template/template_test.go
new file mode 100644
index 0000000..28179f4
--- /dev/null
+++ b/pkg/text/template/template_test.go
@@ -0,0 +1,25 @@
+// Copyright 2020 CUE Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package template_test
+
+import (
+	"testing"
+
+	"cuelang.org/go/pkg/internal/builtintest"
+)
+
+func TestBuiltin(t *testing.T) {
+	builtintest.Run("template", t)
+}
diff --git a/pkg/text/template/testdata/gen.txtar b/pkg/text/template/testdata/gen.txtar
new file mode 100644
index 0000000..faebc85
--- /dev/null
+++ b/pkg/text/template/testdata/gen.txtar
@@ -0,0 +1,10 @@
+# generated from the original tests.
+# Henceforth it may be nicer to group tests into separate files.
+-- in.cue --
+import "text/template"
+
+t1: template.Execute("{{.}}-{{.}}", "foo")
+-- out/template --
+(struct){
+  t1: (string){ "foo-foo" }
+}
diff --git a/pkg/time/builtin_test.go b/pkg/time/builtin_test.go
new file mode 100644
index 0000000..0c89699
--- /dev/null
+++ b/pkg/time/builtin_test.go
@@ -0,0 +1,25 @@
+// Copyright 2020 CUE Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package time_test
+
+import (
+	"testing"
+
+	"cuelang.org/go/pkg/internal/builtintest"
+)
+
+func TestBuiltin(t *testing.T) {
+	builtintest.Run("time", t)
+}
diff --git a/pkg/time/testdata/gen.txtar b/pkg/time/testdata/gen.txtar
new file mode 100644
index 0000000..9ed2159
--- /dev/null
+++ b/pkg/time/testdata/gen.txtar
@@ -0,0 +1,21 @@
+# generated from the original tests.
+# Henceforth it may be nicer to group tests into separate files.
+-- in.cue --
+import "time"
+
+t1: time.Time & "1937-01-01T12:00:27.87+00:20"
+t2: time.Time & "no time"
+t3: time.Unix(1500000000, 123456)
+-- out/time --
+Errors:
+error in call to time.Time: invalid time "no time"
+
+Result:
+(_|_){
+  // [eval]
+  t1: (string){ "1937-01-01T12:00:27.87+00:20" }
+  t2: (_|_){
+    // [eval] error in call to time.Time: invalid time "no time"
+  }
+  t3: (string){ "2017-07-14T02:40:00.000123456Z" }
+}