go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/cipkg/base/actions/reexec_test.go (about) 1 // Copyright 2023 The LUCI Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package actions 16 17 import ( 18 "context" 19 "errors" 20 "os" 21 "os/exec" 22 "path/filepath" 23 "runtime" 24 "testing" 25 26 "go.chromium.org/luci/cipkg/core" 27 "go.chromium.org/luci/common/system/environ" 28 29 . "github.com/smartystreets/goconvey/convey" 30 "google.golang.org/protobuf/encoding/protojson" 31 "google.golang.org/protobuf/proto" 32 "google.golang.org/protobuf/types/known/anypb" 33 ) 34 35 func TestSetExecutor(t *testing.T) { 36 Convey("Test set executor", t, func() { 37 reg := NewReexecRegistry() 38 39 Convey("ok", func() { 40 err := SetExecutor[*anypb.Any](reg, func(ctx context.Context, msg *anypb.Any, out string) error { return nil }) 41 So(err, ShouldBeNil) 42 }) 43 44 Convey("duplicated", func() { 45 err := SetExecutor[*anypb.Any](reg, func(ctx context.Context, msg *anypb.Any, out string) error { return nil }) 46 So(err, ShouldBeNil) 47 err = SetExecutor[*anypb.Any](reg, func(ctx context.Context, msg *anypb.Any, out string) error { return nil }) 48 So(errors.Is(err, ErrExecutorExisted), ShouldBeTrue) 49 }) 50 51 Convey("sealed", func() { 52 reg.interceptWithArgs(context.Background(), environ.New(nil), []string{}, func(i int) {}) 53 err := SetExecutor[*anypb.Any](reg, func(ctx context.Context, msg *anypb.Any, out string) error { return nil }) 54 So(errors.Is(err, ErrReexecRegistrySealed), ShouldBeTrue) 55 }) 56 }) 57 } 58 59 func runWithDrv(ctx context.Context, drv *core.Derivation, out string) { 60 env := environ.New(drv.Env) 61 env.Set("out", out) 62 code := -1 63 NewReexecRegistry().interceptWithArgs(ctx, env, drv.Args, func(i int) { 64 code = i 65 }) 66 So(code, ShouldEqual, 0) 67 } 68 69 func checkReexecArg(args []string, m proto.Message) { 70 m, err := anypb.New(m) 71 So(err, ShouldBeNil) 72 b, err := protojson.Marshal(m) 73 So(err, ShouldBeNil) 74 So(args, ShouldContain, string(b)) 75 } 76 77 // This test is for windows's default binary searching behaviour, which lookup 78 // from current working directory. Because of its relative nature, this is 79 // forbidden by golang and causing error. We expect if Intercept() is called, 80 // NoDefaultCurrentDirectoryInExePath will be set to prevent that behaviour. 81 func TestBinLookup(t *testing.T) { 82 if runtime.GOOS != "windows" { 83 t.SkipNow() 84 } 85 86 Convey("lookup from cwd", t, func() { 87 bin := t.TempDir() 88 89 f, err := os.CreateTemp(bin, "something*.exe") 90 So(err, ShouldBeNil) 91 err = f.Close() 92 So(err, ShouldBeNil) 93 94 olddir, err := os.Getwd() 95 So(err, ShouldBeNil) 96 err = os.Chdir(bin) 97 So(err, ShouldBeNil) 98 t.Cleanup(func() { 99 if err := os.Chdir(olddir); err != nil { 100 t.Fatal(err) 101 } 102 }) 103 104 fname := filepath.Base(f.Name()) 105 106 err = os.Unsetenv("NoDefaultCurrentDirectoryInExePath") 107 So(err, ShouldBeNil) 108 109 _, err = exec.LookPath(fname) 110 So(errors.Is(err, exec.ErrDot), ShouldBeTrue) 111 112 err = os.Setenv("NoDefaultCurrentDirectoryInExePath", "1") 113 So(err, ShouldBeNil) 114 115 _, err = exec.LookPath(fname) 116 So(errors.Is(err, exec.ErrNotFound), ShouldBeTrue) 117 }) 118 }