89 lines
1.6 KiB
Go
89 lines
1.6 KiB
Go
package tableflip
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"strings"
|
|
)
|
|
|
|
type testProcess struct {
|
|
fds []*os.File
|
|
env env
|
|
signals chan os.Signal
|
|
sigErr chan error
|
|
waitErr chan error
|
|
quit chan struct{}
|
|
}
|
|
|
|
func newTestProcess(fds []*os.File, envstr []string) (*testProcess, error) {
|
|
environ := make(map[string]string)
|
|
for _, entry := range envstr {
|
|
parts := strings.SplitN(entry, "=", 2)
|
|
if len(parts) != 2 {
|
|
return nil, fmt.Errorf("invalid env entry: %s", entry)
|
|
}
|
|
environ[parts[0]] = parts[1]
|
|
}
|
|
|
|
return &testProcess{
|
|
fds,
|
|
env{
|
|
newFile: func(fd uintptr, name string) *os.File {
|
|
return fds[fd-3]
|
|
},
|
|
getenv: func(key string) string {
|
|
return environ[key]
|
|
},
|
|
closeOnExec: func(int) {},
|
|
},
|
|
make(chan os.Signal, 1),
|
|
make(chan error),
|
|
make(chan error),
|
|
make(chan struct{}),
|
|
}, nil
|
|
}
|
|
|
|
func (tp *testProcess) Signal(sig os.Signal) error {
|
|
select {
|
|
case tp.signals <- sig:
|
|
return <-tp.sigErr
|
|
case <-tp.quit:
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func (tp *testProcess) Wait() error {
|
|
select {
|
|
case err := <-tp.waitErr:
|
|
return err
|
|
case <-tp.quit:
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func (tp *testProcess) String() string {
|
|
return fmt.Sprintf("tp=%p", tp)
|
|
}
|
|
|
|
func (tp *testProcess) exit(err error) {
|
|
select {
|
|
case tp.waitErr <- err:
|
|
close(tp.quit)
|
|
case <-tp.quit:
|
|
}
|
|
}
|
|
|
|
func (tp *testProcess) recvSignal(err error) os.Signal {
|
|
sig := <-tp.signals
|
|
tp.sigErr <- err
|
|
return sig
|
|
}
|
|
|
|
func (tp *testProcess) notify() (map[fileName]*file, <-chan error, error) {
|
|
parent, files, err := newParent(&tp.env)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
return files, parent.result, parent.sendReady()
|
|
}
|