package azalea_test import ( "reflect" "strings" "testing" "text/scanner" "hakurei.app/internal/rosa/azalea" ) func TestParse(t *testing.T) { t.Parallel() testCases := []struct { name string data string want []any err error }{ {"invalid", "}", nil, azalea.ExprError('}')}, {"bad sep", "f{v?}", nil, azalea.TokenError{'=', '?'}}, {"bad ident", "f{9}", nil, azalea.TokenError{scanner.Ident, scanner.Int}}, {"share bad sep", "f { v,,v = v; }", nil, azalea.ExprError(',')}, {"share missing sep", "f { v v }", nil, azalea.TokenError{',', scanner.Ident}}, {"ident string", `v`, []any{azalea.StringSpec{ {Value: "v", Ident: true}, }}, nil}, {"ident string concat", `v+"\xfd"`, []any{azalea.StringSpec{ {Value: "v", Ident: true}, {Value: "\xfd"}, }}, nil}, {"truncated string concat", `v+`, nil, azalea.TokenError{scanner.String, scanner.EOF}}, {"unexpected string concat", `v+9`, nil, azalea.TokenError{scanner.String, scanner.Int}}, {"empty pairs", `{}`, []any{[]azalea.KV(nil)}, nil}, {"short kv", `{"\x00":v;}`, []any{[]azalea.KV{ {K: "\x00", V: azalea.StringSpec{azalea.String{Value: "v", Ident: true}}}, }}, nil}, {"truncated kv", `{"\x00"`, nil, azalea.ExprError(scanner.EOF)}, {"ident kv", `{v="";}`, nil, azalea.ExprError(scanner.Ident)}, {"empty array", `[]`, []any{[]any(nil)}, nil}, {"integer array", `[9]`, []any{[]any{int64(9)}}, nil}, {"short array", `[ "\x00" ]`, []any{ []any{azalea.StringSpec{{Value: "\x00"}}}, }, nil}, {"short array delim", `[ "\x00", ]`, []any{ []any{azalea.StringSpec{{Value: "\x00"}}}, }, nil}, {"missing array value", `[ "\x00", , v ]`, nil, azalea.ExprError(',')}, {"missing array delimiter", `[ v0 v1 ]`, nil, azalea.TokenError{',', scanner.Ident}}, {"truncated array", `[ "\x00"`, nil, azalea.ExprError(scanner.EOF)}, {"gcc", ` package gcc { description = "The GNU Compiler Collection"; website = "https://www.gnu.org/software/gcc"; anitya = 6502; version* = "16.1.0"; source = remoteTar { url = "https://ftp.tsukuba.wide.ad.jp/software/gcc/releases/"+ "gcc-"+version+"/gcc-"+version+".tar.gz"; checksum = "4ASoWbxaA2FW7PAB0zzHDPC5XnNhyaAyjtDPpGzceSLeYnEIXsNYZR3PA_Zu5P0K"; compress = gzip; }; patches = [ "musl-off64_t-loff_t.patch", "musl-legacy-lfs.patch", ]; // GCC spends most of its time in its many configure scripts, however // it also saturates the CPU for a consequential amount of time. exclusive = true; exec = make { configure = { "disable-multilib"; "enable-default-pie"; "disable-nls"; "with-gnu-as"; "with-gnu-ld"; "with-system-zlib"; "enable-languages": "c,c++,go"; "with-native-system-header-dir": "/system/include"; "with-multilib-list": arch { amd64, arm64 = "''"; default = unset; }; }; make = [ "BOOT_CFLAGS='-O2 -g'", noop { key = value; }, "bootstrap", ]; // This toolchain is hacked to pieces, it is not expected to ever work // well in its current state. That does not matter as long as the // toolchain it produces passes its own test suite. skip-check = true; }; inputs = [ binutils, mpc, zlib, libucontext, kernel-headers, ]; } `, []any{azalea.Func{ Ident: "gcc", Package: true, Args: []azalea.Arg{ {K: []string{"description"}, V: azalea.StringSpec{{Value: "The GNU Compiler Collection"}}}, {K: []string{"website"}, V: azalea.StringSpec{{Value: "https://www.gnu.org/software/gcc"}}}, {K: []string{"anitya"}, V: int64(6502)}, {K: []string{"version"}, V: azalea.StringSpec{{Value: "16.1.0"}}, R: true}, {K: []string{"source"}, V: azalea.Func{Ident: "remoteTar", Package: false, Args: []azalea.Arg{ {K: []string{"url"}, V: azalea.StringSpec{ {Value: "https://ftp.tsukuba.wide.ad.jp/software/gcc/releases/"}, {Value: "gcc-"}, {Value: "version", Ident: true}, {Value: "/gcc-"}, {Value: "version", Ident: true}, {Value: ".tar.gz"}, }}, {K: []string{"checksum"}, V: azalea.StringSpec{ {Value: "4ASoWbxaA2FW7PAB0zzHDPC5XnNhyaAyjtDPpGzceSLeYnEIXsNYZR3PA_Zu5P0K"}, }}, {K: []string{"compress"}, V: azalea.StringSpec{{Value: "gzip", Ident: true}}}, }}}, {K: []string{"patches"}, V: []any{ azalea.StringSpec{{Value: "musl-off64_t-loff_t.patch"}}, azalea.StringSpec{{Value: "musl-legacy-lfs.patch"}}, }}, {K: []string{"exclusive"}, V: azalea.StringSpec{{Value: "true", Ident: true}}}, {K: []string{"exec"}, V: azalea.Func{ Ident: "make", Args: []azalea.Arg{ {K: []string{"configure"}, V: []azalea.KV{ {K: "disable-multilib"}, {K: "enable-default-pie"}, {K: "disable-nls"}, {K: "with-gnu-as"}, {K: "with-gnu-ld"}, {K: "with-system-zlib"}, {K: "enable-languages", V: azalea.StringSpec{{Value: "c,c++,go"}}}, {K: "with-native-system-header-dir", V: azalea.StringSpec{{Value: "/system/include"}}}, {K: "with-multilib-list", V: azalea.Func{ Ident: "arch", Args: []azalea.Arg{ {K: []string{"amd64", "arm64"}, V: azalea.StringSpec{{Value: "''"}}}, {K: []string{"default"}, V: azalea.StringSpec{{Value: "unset", Ident: true}}}, }, }}, }}, {K: []string{"make"}, V: []any{ azalea.StringSpec{{Value: "BOOT_CFLAGS='-O2 -g'"}}, azalea.Func{ Ident: "noop", Args: []azalea.Arg{ {K: []string{"key"}, V: azalea.StringSpec{ {Value: "value", Ident: true}, }}, }, }, azalea.StringSpec{{Value: "bootstrap"}}, }}, {K: []string{"skip-check"}, V: azalea.StringSpec{{Value: "true", Ident: true}}}, }, }}, {K: []string{"inputs"}, V: []any{ azalea.StringSpec{{Value: "binutils", Ident: true}}, azalea.StringSpec{{Value: "mpc", Ident: true}}, azalea.StringSpec{{Value: "zlib", Ident: true}}, azalea.StringSpec{{Value: "libucontext", Ident: true}}, azalea.StringSpec{{Value: "kernel-headers", Ident: true}}, }}, }, }}, nil}, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { t.Parallel() p, err := azalea.Parse(strings.NewReader(tc.data)) if !reflect.DeepEqual(p, tc.want) { t.Errorf("Parse: %#v, want %#v", p, tc.want) } if !reflect.DeepEqual(err, tc.err) { t.Errorf("Parse: error = %v, want %v", err, tc.err) } }) } }