package nixbuild_test import ( "errors" "os" "runtime" "slices" "strings" "testing" "git.gensokyo.uk/yonah/nixbuild" ) func TestDecodeInstantiated(t *testing.T) { testCases := []struct { name string out string want []string wantErr error }{ {"bad fields", segmentPrefix + `instantiated 'config.sub-948ae97' ` + segmentSuffix, nil, &nixbuild.MalformedInstantiatedError{Type: nixbuild.InstantiatedBadFields}}, {"unexpected quotes left", segmentPrefix + `instantiated 'config.sub-948ae97' -> /n'` + segmentSuffix, nil, &nixbuild.MalformedInstantiatedError{Type: nixbuild.InstantiatedUnexpectedQuotes}}, {"unexpected quotes right", segmentPrefix + `instantiated 'config.sub-948ae97' -> '/n` + segmentSuffix, nil, &nixbuild.MalformedInstantiatedError{Type: nixbuild.InstantiatedUnexpectedQuotes}}, {"unexpected quotes short", segmentPrefix + `instantiated 'config.sub-948ae97' -> ''` + segmentSuffix, nil, &nixbuild.MalformedInstantiatedError{Type: nixbuild.InstantiatedUnexpectedQuotes}}, {"not absolute", segmentPrefix + `instantiated 'config.sub-948ae97' -> ' '` + segmentSuffix, nil, &nixbuild.MalformedInstantiatedError{Type: nixbuild.InstantiatedNotAbsolute}}, {"good segment", segmentPrefix + segmentBody + segmentSuffix, []string{ "/nix/store/3zilrlmq7r6rpzfd94mwss32b62yinj5-bootstrap-stage0-stdenv-linux.drv", "/nix/store/7yfwy95p6lcdpljdajs5aw10h6q0sfx0-update-autotools-gnu-config-scripts-hook.drv", "/nix/store/bamwxswxacs3cjdcydv0z7bj22d7g2kc-config.guess-948ae97.drv", "/nix/store/gyks6vvl7x0gq214ldjhi3w4rg37nh8i-zlib-1.3.1.tar.gz.drv", "/nix/store/nbsdqpfzh1jlpmh95s69b3iivfcvv3lh-config.sub-948ae97.drv", "/nix/store/ysp83x9nrks28zkblqmnc1s1kb68dr69-gnu-config-2024-01-01.drv", }, nil}, {"getchoo atlas", getchooAtlasOut, getchooAtlas, nil}, {"getchoo glados", getchooGladosOut, getchooGlados, nil}, {"pluiedev pappardelle", pluiedevPappardelleOut, pluiedevPappardelle, nil}, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { if tc.wantErr != nil { w := nixbuild.Stderr nixbuild.Stderr = os.Stderr t.Cleanup(func() { nixbuild.Stderr = w }) } stderr := strings.NewReader(tc.out) got, err := nixbuild.NewInstantiatedDecoder(stderr).Decode() if !errors.Is(err, tc.wantErr) { t.Fatalf("DecodeInstantiated: error = %v, want %v", err, tc.wantErr) } if tc.wantErr != nil { t.Logf("DecodeInstantiated: error = %v", err) return } if !slices.Equal(got, tc.want) { t.Errorf("DecodeInstantiated: %#v, want %#v", got, tc.want) } }) } t.Run("stop early", func(t *testing.T) { want := []string{ "/nix/store/gyks6vvl7x0gq214ldjhi3w4rg37nh8i-zlib-1.3.1.tar.gz.drv", "/nix/store/bamwxswxacs3cjdcydv0z7bj22d7g2kc-config.guess-948ae97.drv", "/nix/store/nbsdqpfzh1jlpmh95s69b3iivfcvv3lh-config.sub-948ae97.drv", } decoder := nixbuild.NewInstantiatedDecoder(strings.NewReader(segmentPrefix + segmentBody + segmentSuffix)) counter := 3 got := make([]string, 0, counter) for drv := range decoder.Drv() { got = append(got, drv) counter-- if counter == 0 { break } } if !slices.Equal(got, want) { t.Errorf("Drv: %#v, want %#v", got, want) } }) t.Run("errors", func(t *testing.T) { t.Run("bad type", func(t *testing.T) { badErr := errors.New("") if errors.Is(new(nixbuild.MalformedInstantiatedError), badErr) { t.Error("unexpected MalformedInstantiatedError equivalence") } }) t.Run("nil", func(t *testing.T) { if errors.Is(new(nixbuild.MalformedInstantiatedError), (*nixbuild.MalformedInstantiatedError)(nil)) { t.Error("unexpected MalformedInstantiatedError equivalence") } }) t.Run("unreachable", func(t *testing.T) { defer func() { wantPanic := "unreachable" if r := recover(); r != wantPanic { t.Errorf("Error: panic = %q, want %q", r, wantPanic) } }() _ = (&nixbuild.MalformedInstantiatedError{Type: -1}).Error() }) }) } const ( segmentPrefix = `evaluating file '/nix/store/vdzlppvrdkz9rv14q4j02g9kpjbww2ww-source/pkgs/development/libraries/zlib/default.nix' evaluating file '/nix/store/vdzlppvrdkz9rv14q4j02g9kpjbww2ww-source/pkgs/build-support/fetchurl/boot.nix' performing daemon worker op: 7 instantiated 'zlib-1.3.1.tar.gz' -> '/nix/store/gyks6vvl7x0gq214ldjhi3w4rg37nh8i-zlib-1.3.1.tar.gz.drv' source path '/nix/store/vdzlppvrdkz9rv14q4j02g9kpjbww2ww-source/pkgs/build-support/setup-hooks/update-autotools-gnu-config-scripts.sh' is uncacheable copying '/nix/store/vdzlppvrdkz9rv14q4j02g9kpjbww2ww-source/pkgs/build-support/setup-hooks/update-autotools-gnu-config-scripts.sh' to the store... performing daemon worker op: 7 copied '/nix/store/vdzlppvrdkz9rv14q4j02g9kpjbww2ww-source/pkgs/build-support/setup-hooks/update-autotools-gnu-config-scripts.sh' to '/nix/store/96rvfw5vlv1hwwm9sdxhdkkpjyym6p2x-update-autotools-gnu-config-scripts.sh' copied source '/nix/store/vdzlppvrdkz9rv14q4j02g9kpjbww2ww-source/pkgs/build-support/setup-hooks/update-autotools-gnu-config-scripts.sh' -> '/nix/store/96rvfw5vlv1hwwm9sdxhdkkpjyym6p2x-update-autotools-gnu-config-scripts.sh' evaluating file '/nix/store/vdzlppvrdkz9rv14q4j02g9kpjbww2ww-source/pkgs/by-name/gn/gnu-config/package.nix' performing daemon worker op: 7 instantiated 'config.guess-948ae97' -> '/nix/store/bamwxswxacs3cjdcydv0z7bj22d7g2kc-config.guess-948ae97.drv' performing daemon worker op: 7 ` segmentBody = `instantiated 'config.sub-948ae97' -> '/nix/store/nbsdqpfzh1jlpmh95s69b3iivfcvv3lh-config.sub-948ae97.drv'` segmentSuffix = ` performing daemon worker op: 7 instantiated 'gnu-config-2024-01-01' -> '/nix/store/ysp83x9nrks28zkblqmnc1s1kb68dr69-gnu-config-2024-01-01.drv' performing daemon worker op: 7 instantiated 'bootstrap-stage0-stdenv-linux' -> '/nix/store/3zilrlmq7r6rpzfd94mwss32b62yinj5-bootstrap-stage0-stdenv-linux.drv' performing daemon worker op: 7 instantiated 'update-autotools-gnu-config-scripts-hook' -> '/nix/store/7yfwy95p6lcdpljdajs5aw10h6q0sfx0-update-autotools-gnu-config-scripts-hook.drv' source path '/nix/store/vdzlppvrdkz9rv14q4j02g9kpjbww2ww-source/pkgs/build-support/bintools-wrapper/ld-wrapper.sh' is uncacheable copying '/nix/store/vdzlppvrdkz9rv14q4j02g9kpjbww2ww-source/pkgs/build-support/bintools-wrapper/ld-wrapper.sh' to the store...` ) func BenchmarkDecodeInstantiated(b *testing.B) { stderr := strings.NewReader(pluiedevPappardelleOut) var v []string for i := 0; i < b.N; i++ { v, _ = nixbuild.NewInstantiatedDecoder(stderr).Decode() runtime.KeepAlive(v) } } func BenchmarkDecodeInstantiatedCopy(b *testing.B) { stderr := strings.NewReader(getchooAtlasOut) var v []string for i := 0; i < b.N; i++ { v, _ = nixbuild.NewInstantiatedDecoder(stderr).Decode() runtime.KeepAlive(v) } }