Loading get.go +143 −62 Original line number Diff line number Diff line Loading @@ -15,17 +15,16 @@ const ( Err Channel = 3 ) type Streams struct { match chan Match done chan bool } type Expect struct { stdin bytes.Buffer stdout bytes.Buffer stderr bytes.Buffer wg sync.WaitGroup ss map[Channel]Streams matchStream chan struct { c Channel m Match } terminateStream chan bool finishedStream chan bool } type Match struct { Loading @@ -34,45 +33,32 @@ type Match struct { } func New() (*Expect, error) { matchOutStream := make(chan Match) startedOutStream := make(chan bool) doneOutStream := make(chan bool) ssOut := Streams{ match: matchOutStream, done: doneOutStream, } matchErrStream := make(chan Match) startedErrStream := make(chan bool) doneErrStream := make(chan bool) ssErr := Streams{ match: matchErrStream, done: doneErrStream, } ss := make(map[Channel]Streams) ss[Out] = ssOut ss[Err] = ssErr x := &Expect{ ss: ss, matchStream: make(chan struct { c Channel m Match }), terminateStream: make(chan bool), finishedStream: make(chan bool), } x.wg.Add(2) go process(&x.wg, &x.stdout, &x.stdin, startedOutStream, matchOutStream, doneOutStream) go process(&x.wg, &x.stderr, &x.stdin, startedErrStream, matchErrStream, doneErrStream) <-startedOutStream <-startedErrStream startedChannel := make(chan bool) defer close(startedChannel) go x.worker(startedChannel) <-startedChannel return x, nil } func (x *Expect) Close() error { for _, b := range x.ss { b.done <- true func async(c chan<- bool, b bool) { go func() { c <- b }() } x.wg.Wait() func (x *Expect) Close() error { async(x.terminateStream, true) <-x.finishedStream return nil } Loading @@ -89,19 +75,117 @@ func (x *Expect) Stderr() io.Writer { } func (x *Expect) Wait(c Channel, match, text string) error { x.ss[c].match <- Match{p: match, v: text} x.matchStream <- struct { c Channel m Match }{ c: c, m: Match{p: match, v: text}, } return nil } func (x *Expect) worker(started chan<- bool) { var wg sync.WaitGroup matchOutStream := make(chan Match) startedOutStream := make(chan bool) terminateOutStream := make(chan bool) terminatedOutStream := make(chan bool) terminatedOut := false matchErrStream := make(chan Match) startedErrStream := make(chan bool) terminateErrStream := make(chan bool) terminatedErrStream := make(chan bool) terminatedErr := false checkStream := make(chan bool) defer close(checkStream) wg.Add(2) go func() { defer wg.Done() process(&x.stdout, &x.stdin, startedOutStream, matchOutStream, terminateOutStream, terminatedOutStream) }() go func() { defer wg.Done() process(&x.stderr, &x.stdin, startedErrStream, matchErrStream, terminateErrStream, terminatedErrStream) }() <-startedOutStream <-startedErrStream started <- true for { select { case match, valid := <-x.matchStream: if !valid { continue } switch match.c { case Out: matchOutStream <- match.m case Err: matchErrStream <- match.m } case terminate, valid := <-x.terminateStream: if !valid { continue } if !terminate { continue } async(terminateOutStream, true) async(terminateErrStream, true) case terminated, valid := <-terminatedOutStream: if !valid { continue } if !terminated { continue } terminatedOut = true async(checkStream, true) case terminated, valid := <-terminatedErrStream: if !valid { continue } if !terminated { continue } terminatedErr = true async(checkStream, true) case check, valid := <-checkStream: if !valid { continue } if !check { continue } if !terminatedOut { continue } if !terminatedErr { continue } wg.Wait() x.finishedStream <- true } } } func process( wg *sync.WaitGroup, in io.Reader, out io.Writer, startedStream chan<- bool, matchStream <-chan Match, doneStream <-chan bool, terminateStream <-chan bool, terminatedStream chan<- bool, ) { defer wg.Done() matches := []Match{} startedStream <- true Loading @@ -113,18 +197,20 @@ func process( continue } matches = append(matches, match) case done, valid := <-doneStream: case terminate, valid := <-terminateStream: if !valid { continue } if !done { if !terminate { continue } terminatedStream <- true return default: bytes, err := io.ReadAll(in) switch err { case nil: if err != nil { continue } if len(bytes) == 0 { continue } Loading @@ -136,11 +222,6 @@ func process( io.WriteString(out, m.v) break } //case io.EOF: // return default: continue } } } } get_test.go +2 −2 Original line number Diff line number Diff line Loading @@ -20,7 +20,7 @@ const ( func TestPasswdChange(t *testing.T) { x, err := New() if err != nil { t.Fatalf("New() failed with: %s", err) t.Fatalf("get.New() failed with: %s", err) } defer x.Close() Loading @@ -34,7 +34,7 @@ func TestPasswdChange(t *testing.T) { p, err := passwd.New(x.Stdin(), x.Stdout(), x.Stderr(), lp2User) if err != nil { t.Fatalf("New() failed with: %s", err) t.Fatalf("passwd.New() failed with: %s", err) } if err := p.Run(); err != nil { Loading mock/passwd/passwd.go +3 −3 Original line number Diff line number Diff line Loading @@ -81,7 +81,7 @@ func (cmd *Passwd) Run() error { fmt.Fprintf(cmd.stderr, "Current password: ") var p0 string if _, err := fmt.Fscanf(cmd.stdin, "%s\n", &p0); err != nil { return err return fmt.Errorf("p0: %s", err) } if p0 != lp.Pass { t := "wrong password" Loading @@ -92,13 +92,13 @@ func (cmd *Passwd) Run() error { fmt.Fprintf(cmd.stderr, "New password: ") var p1 string if _, err := fmt.Fscanf(cmd.stdin, "%s\n", &p1); err != nil { return err return fmt.Errorf("p1: %s", err) } fmt.Fprintf(cmd.stderr, "Retype new password: ") var p2 string if _, err := fmt.Fscanf(cmd.stdin, "%s\n", &p2); err != nil { return err return fmt.Errorf("p2: %s", err) } if p1 != p2 { return errors.New("passwords do not match") Loading Loading
get.go +143 −62 Original line number Diff line number Diff line Loading @@ -15,17 +15,16 @@ const ( Err Channel = 3 ) type Streams struct { match chan Match done chan bool } type Expect struct { stdin bytes.Buffer stdout bytes.Buffer stderr bytes.Buffer wg sync.WaitGroup ss map[Channel]Streams matchStream chan struct { c Channel m Match } terminateStream chan bool finishedStream chan bool } type Match struct { Loading @@ -34,45 +33,32 @@ type Match struct { } func New() (*Expect, error) { matchOutStream := make(chan Match) startedOutStream := make(chan bool) doneOutStream := make(chan bool) ssOut := Streams{ match: matchOutStream, done: doneOutStream, } matchErrStream := make(chan Match) startedErrStream := make(chan bool) doneErrStream := make(chan bool) ssErr := Streams{ match: matchErrStream, done: doneErrStream, } ss := make(map[Channel]Streams) ss[Out] = ssOut ss[Err] = ssErr x := &Expect{ ss: ss, matchStream: make(chan struct { c Channel m Match }), terminateStream: make(chan bool), finishedStream: make(chan bool), } x.wg.Add(2) go process(&x.wg, &x.stdout, &x.stdin, startedOutStream, matchOutStream, doneOutStream) go process(&x.wg, &x.stderr, &x.stdin, startedErrStream, matchErrStream, doneErrStream) <-startedOutStream <-startedErrStream startedChannel := make(chan bool) defer close(startedChannel) go x.worker(startedChannel) <-startedChannel return x, nil } func (x *Expect) Close() error { for _, b := range x.ss { b.done <- true func async(c chan<- bool, b bool) { go func() { c <- b }() } x.wg.Wait() func (x *Expect) Close() error { async(x.terminateStream, true) <-x.finishedStream return nil } Loading @@ -89,19 +75,117 @@ func (x *Expect) Stderr() io.Writer { } func (x *Expect) Wait(c Channel, match, text string) error { x.ss[c].match <- Match{p: match, v: text} x.matchStream <- struct { c Channel m Match }{ c: c, m: Match{p: match, v: text}, } return nil } func (x *Expect) worker(started chan<- bool) { var wg sync.WaitGroup matchOutStream := make(chan Match) startedOutStream := make(chan bool) terminateOutStream := make(chan bool) terminatedOutStream := make(chan bool) terminatedOut := false matchErrStream := make(chan Match) startedErrStream := make(chan bool) terminateErrStream := make(chan bool) terminatedErrStream := make(chan bool) terminatedErr := false checkStream := make(chan bool) defer close(checkStream) wg.Add(2) go func() { defer wg.Done() process(&x.stdout, &x.stdin, startedOutStream, matchOutStream, terminateOutStream, terminatedOutStream) }() go func() { defer wg.Done() process(&x.stderr, &x.stdin, startedErrStream, matchErrStream, terminateErrStream, terminatedErrStream) }() <-startedOutStream <-startedErrStream started <- true for { select { case match, valid := <-x.matchStream: if !valid { continue } switch match.c { case Out: matchOutStream <- match.m case Err: matchErrStream <- match.m } case terminate, valid := <-x.terminateStream: if !valid { continue } if !terminate { continue } async(terminateOutStream, true) async(terminateErrStream, true) case terminated, valid := <-terminatedOutStream: if !valid { continue } if !terminated { continue } terminatedOut = true async(checkStream, true) case terminated, valid := <-terminatedErrStream: if !valid { continue } if !terminated { continue } terminatedErr = true async(checkStream, true) case check, valid := <-checkStream: if !valid { continue } if !check { continue } if !terminatedOut { continue } if !terminatedErr { continue } wg.Wait() x.finishedStream <- true } } } func process( wg *sync.WaitGroup, in io.Reader, out io.Writer, startedStream chan<- bool, matchStream <-chan Match, doneStream <-chan bool, terminateStream <-chan bool, terminatedStream chan<- bool, ) { defer wg.Done() matches := []Match{} startedStream <- true Loading @@ -113,18 +197,20 @@ func process( continue } matches = append(matches, match) case done, valid := <-doneStream: case terminate, valid := <-terminateStream: if !valid { continue } if !done { if !terminate { continue } terminatedStream <- true return default: bytes, err := io.ReadAll(in) switch err { case nil: if err != nil { continue } if len(bytes) == 0 { continue } Loading @@ -136,11 +222,6 @@ func process( io.WriteString(out, m.v) break } //case io.EOF: // return default: continue } } } }
get_test.go +2 −2 Original line number Diff line number Diff line Loading @@ -20,7 +20,7 @@ const ( func TestPasswdChange(t *testing.T) { x, err := New() if err != nil { t.Fatalf("New() failed with: %s", err) t.Fatalf("get.New() failed with: %s", err) } defer x.Close() Loading @@ -34,7 +34,7 @@ func TestPasswdChange(t *testing.T) { p, err := passwd.New(x.Stdin(), x.Stdout(), x.Stderr(), lp2User) if err != nil { t.Fatalf("New() failed with: %s", err) t.Fatalf("passwd.New() failed with: %s", err) } if err := p.Run(); err != nil { Loading
mock/passwd/passwd.go +3 −3 Original line number Diff line number Diff line Loading @@ -81,7 +81,7 @@ func (cmd *Passwd) Run() error { fmt.Fprintf(cmd.stderr, "Current password: ") var p0 string if _, err := fmt.Fscanf(cmd.stdin, "%s\n", &p0); err != nil { return err return fmt.Errorf("p0: %s", err) } if p0 != lp.Pass { t := "wrong password" Loading @@ -92,13 +92,13 @@ func (cmd *Passwd) Run() error { fmt.Fprintf(cmd.stderr, "New password: ") var p1 string if _, err := fmt.Fscanf(cmd.stdin, "%s\n", &p1); err != nil { return err return fmt.Errorf("p1: %s", err) } fmt.Fprintf(cmd.stderr, "Retype new password: ") var p2 string if _, err := fmt.Fscanf(cmd.stdin, "%s\n", &p2); err != nil { return err return fmt.Errorf("p2: %s", err) } if p1 != p2 { return errors.New("passwords do not match") Loading