Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 12 additions & 54 deletions internal/password/password_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,12 @@ func TestGenerate(t *testing.T) {

func TestWrite(t *testing.T) {
t.Run("Must write to stdout when asked to do so", func(t *testing.T) {
tapper := tapStdOut{}
tapper.Start()
// setup for tapping into os.Stdout
rf, wf, err := os.Pipe()
assert.NoError(t, err)
backUp := os.Stdout
os.Stdout = wf
var outbuff bytes.Buffer
passwordLength := 40
count := 1
options := Options{
Expand All @@ -109,10 +113,13 @@ func TestWrite(t *testing.T) {
passwords, err := Generate(&options)
assert.NoError(t, err)
Write(passwords, &options)
output, err := tapper.Flush()
err = wf.Close()
os.Stdout = backUp
assert.NoError(t, err)
_, err = io.Copy(&outbuff, rf)
assert.NoError(t, err)
msg := fmt.Sprintf("Expected password to be of length %d", passwordLength)
assert.Equal(t, passwordLength, len(output), msg)
assert.Equal(t, passwordLength, len(outbuff.String()), msg)
})

t.Run("Must write to file when asked to do so", func(t *testing.T) {
Expand Down Expand Up @@ -161,57 +168,8 @@ func TestWrite(t *testing.T) {
}
passwd := string(buff)
assert.NoError(t, err)
msg := fmt.Sprintf("Expected password to be of length %d", passwordLength)
msg := fmt.Sprintf("expected password to be of length %d", passwordLength)
assert.Equal(t, passwordLength, len(passwd), msg)
})

}

// tapStdOut provides mechanism to tap into the stdout
// useful for testing only
type tapStdOut struct {
outChan chan string
errChan chan error

writeTo *os.File
stdOutbackup *os.File
}

// Start starts the tapping process and backsup stdout
func (tapper *tapStdOut) Start() error {
tapper.stdOutbackup = os.Stdout
rf, wf, err := os.Pipe()
if err != nil {
return err
}
os.Stdout = wf
tapper.writeTo = wf
tapper.outChan = make(chan string)
tapper.errChan = make(chan error)
go tapper.read(rf)
return nil
}

// read reads from readpipe into channel of tapper
// must be called in a go routine to prevent
// blocking writes to writepipe (such as stdout)
func (tapper *tapStdOut) read(readFrom *os.File) {
var output bytes.Buffer
_, err := io.Copy(&output, readFrom)
tapper.errChan <- err
tapper.outChan <- output.String()
}

// Flush Stops the tapping process, sends the stored output and restores stdout
func (tapper *tapStdOut) Flush() (string, error) {
err := tapper.writeTo.Close()
if err != nil {
return "", err
}
err = <-tapper.errChan
if err != nil {
return "", err
}
os.Stdout = tapper.stdOutbackup
return <-tapper.outChan, nil
}