go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/common/exec/execmock/simple.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 execmock 16 17 import ( 18 "errors" 19 "io" 20 "os" 21 "sync" 22 ) 23 24 // SimpleInput is the options you can provide to Simple.Mock. 25 type SimpleInput struct { 26 // If true, fire off a goroutine to consume (and discard) all of Stdin. 27 ConsumeStdin bool 28 29 // If non-empty, fire off a goroutine to write this string to Stdout. 30 Stdout string 31 32 // If non-empty, fire off a goroutine to write this string to Stderr. 33 Stderr string 34 35 // Exit with this return code. 36 ExitCode int 37 38 // Emit this error back to the Usage. 39 Error string 40 } 41 42 // Simple implements a very basic mock for executables which can read from 43 // stdin, write to stdout and stderr, and emit an exit code. 44 // 45 // Each of the I/O operations operates in a totally independent goroutine, 46 // and all of them must complete for the Runner to exit. 47 // 48 // Omitting the SimpleInput will result in a mock which just exits 0. 49 // 50 // The Output for this is a string which is the stdin which the process consumed 51 // (if ConsumeStdin was set). 52 var Simple = Register(simpleMocker) 53 54 // simpleMocker is the RunnerFunction implementation for Simple. 55 func simpleMocker(opts SimpleInput) (stdin string, code int, err error) { 56 var wg sync.WaitGroup 57 58 if opts.ConsumeStdin { 59 wg.Add(1) 60 go func() { 61 defer wg.Done() 62 raw, err := io.ReadAll(os.Stdin) 63 if err != nil { 64 panic(err) 65 } 66 stdin = string(raw) 67 }() 68 } 69 70 if opts.Stdout != "" { 71 wg.Add(1) 72 go func() { 73 defer wg.Done() 74 if _, err := os.Stdout.WriteString(opts.Stdout); err != nil { 75 panic(err) 76 } 77 }() 78 } 79 80 if opts.Stderr != "" { 81 wg.Add(1) 82 go func() { 83 defer wg.Done() 84 if _, err := os.Stderr.WriteString(opts.Stderr); err != nil { 85 panic(err) 86 } 87 }() 88 } 89 90 wg.Wait() 91 code = opts.ExitCode 92 if opts.Error != "" { 93 err = errors.New(opts.Error) 94 } 95 return 96 }