diff options
| author | Ophestra <cat@gensokyo.uk> | 2026-05-15 06:48:04 +0900 |
|---|---|---|
| committer | Ophestra <cat@gensokyo.uk> | 2026-05-16 14:29:28 +0900 |
| commit | d38d306147979cbc7f161d1150d6786572598497 (patch) | |
| tree | 4e8a4e493333ff7a171baf4eb2547ab3dfc6449f /internal/rosa/azalea/azalea_test.go | |
| parent | c32c06b2e88f7ccc21bf05c2ebfb12bf884e335c (diff) | |
internal/rosa/azalea: ast and parser
This syntax is not final, but acts as a stopgap solution and a proof of concept.
Signed-off-by: Ophestra <cat@gensokyo.uk>
Diffstat (limited to 'internal/rosa/azalea/azalea_test.go')
| -rw-r--r-- | internal/rosa/azalea/azalea_test.go | 156 |
1 files changed, 156 insertions, 0 deletions
diff --git a/internal/rosa/azalea/azalea_test.go b/internal/rosa/azalea/azalea_test.go new file mode 100644 index 00000000..f2dec252 --- /dev/null +++ b/internal/rosa/azalea/azalea_test.go @@ -0,0 +1,156 @@ +package azalea_test + +import ( + _ "embed" + "reflect" + "strings" + "testing" + "text/scanner" + + . "hakurei.app/internal/rosa/azalea" +) + +//go:embed testdata/gcc.az +var sample string + +func TestParse(t *testing.T) { + t.Parallel() + + testCases := []struct { + name string + data string + want []any + err error + }{ + {"invalid", "}", nil, ExprError('}')}, + {"bad sep", "f{v?}", nil, TokenError{'=', '?'}}, + {"bad ident", "f{9}", nil, TokenError{scanner.Ident, scanner.Int}}, + {"share bad sep", "f { v,,v = v; }", nil, ExprError(',')}, + {"share missing sep", "f { v v }", nil, TokenError{',', scanner.Ident}}, + + {"ident", `v`, []any{Ident("v")}, nil}, + {"concat", `f { v = v+"\xfd"+p{}+9; }`, []any{Func{ + Ident: "f", + + Args: []Arg{{K: []Ident{"v"}, V: Val{ + Ident("v"), + String("\xfd"), + Func{Ident: "p"}, + Int(9), + }}}, + }}, nil}, + {"truncated string concat", `f { v = v+; }`, nil, + ExprError(';')}, + + {"empty pairs", `{}`, []any{[]KV(nil)}, nil}, + {"short kv", `{"\x00":v;}`, []any{[]KV{ + {K: "\x00", V: Val{Ident("v")}}, + }}, nil}, + {"truncated kv", `{"\x00"`, nil, ExprError(scanner.EOF)}, + {"ident kv", `{v="";}`, nil, ExprError(scanner.Ident)}, + + {"empty array", `[]`, []any{Array(nil)}, nil}, + {"integer array", `[9]`, []any{Array{{Int(9)}}}, nil}, + {"short array", `[ "\x00" ]`, []any{ + Array{{String("\x00")}}, + }, nil}, + {"short array delim", `[ "\x00", ]`, []any{ + Array{{String("\x00")}}, + }, nil}, + {"missing array value", `[ "\x00", , v ]`, nil, ExprError(',')}, + {"missing array delimiter", `[ v0 v1 ]`, nil, TokenError{',', scanner.Ident}}, + {"truncated array", `[ "\x00"`, nil, + ExprError(scanner.EOF)}, + + {"gcc", sample, []any{Func{ + Ident: Ident("gcc"), + Package: true, + + Args: []Arg{ + {K: []Ident{Ident("description")}, V: Val{String("The GNU Compiler Collection")}}, + {K: []Ident{Ident("website")}, V: Val{String("https://www.gnu.org/software/gcc")}}, + {K: []Ident{Ident("anitya")}, V: Val{Int(6502)}}, + + {K: []Ident{Ident("version")}, V: Val{String("16.1.0")}, R: true}, + {K: []Ident{Ident("source")}, V: Val{Func{ + Ident: Ident("remoteTar"), + + Args: []Arg{ + {K: []Ident{Ident("url")}, V: Val{ + String("https://ftp.tsukuba.wide.ad.jp/software/gcc/releases/"), + String("gcc-"), + Ident("version"), + String("/gcc-"), + Ident("version"), + String(".tar.gz"), + }}, + {K: []Ident{Ident("checksum")}, V: Val{String("4ASoWbxaA2FW7PAB0zzHDPC5XnNhyaAyjtDPpGzceSLeYnEIXsNYZR3PA_Zu5P0K")}}, + {K: []Ident{Ident("compress")}, V: Val{Ident("gzip")}}, + }, + }}}, + {K: []Ident{Ident("patches")}, V: Val{Array{ + {String("musl-off64_t-loff_t.patch")}, + {String("musl-legacy-lfs.patch")}, + }}}, + + {K: []Ident{Ident("exclusive")}, V: Val{Ident("true")}}, + + {K: []Ident{Ident("exec")}, V: Val{Func{ + Ident: Ident("make"), + + Args: []Arg{ + {K: []Ident{Ident("configure")}, V: Val{[]KV{ + {K: String("disable-multilib")}, + {K: String("enable-default-pie")}, + {K: String("disable-nls")}, + {K: String("with-gnu-as")}, + {K: String("with-gnu-ld")}, + {K: String("with-system-zlib")}, + {K: String("enable-languages"), V: Val{String("c,c++,go")}}, + {K: String("with-native-system-header-dir"), V: Val{String("/system/include")}}, + {K: String("with-multilib-list"), V: Val{Func{ + Ident: Ident("arch"), + + Args: []Arg{ + {K: []Ident{Ident("amd64"), Ident("arm64")}, V: Val{String("''")}}, + {K: []Ident{Ident("default")}, V: Val{Ident("unset")}}, + }, + }}}, + }}}, + {K: []Ident{Ident("make")}, V: Val{Array{ + {String("BOOT_CFLAGS='-O2 -g'")}, + { + Func{Ident: Ident("noop"), Args: []Arg{{K: []Ident{Ident("key")}, V: Val{Ident("value")}}}}, + String("\x00"), + }, + {String("bootstrap")}, + }}}, + + {K: []Ident{Ident("skip-check")}, V: Val{Ident("true")}}, + }, + }}}, + + {K: []Ident{Ident("inputs")}, V: Val{Array{ + {Ident("binutils")}, + {Ident("mpc")}, + {Ident("zlib")}, + {Ident("libucontext")}, + {Ident("kernel-headers")}, + }}}, + }, + }}, nil}, + } + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + + p, err := 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) + } + }) + } +} |
