Skip to content

Commit

Permalink
tests: add tests for wait-paths (#1384)
Browse files Browse the repository at this point in the history
Follow up PR to add tests for wait-paths after initial PR #1258
was merged.

Signed-off-by: Maksim An <maksiman@microsoft.com>
  • Loading branch information
anmaxvl authored May 4, 2022
1 parent 1e01dcc commit 1c049f1
Show file tree
Hide file tree
Showing 2 changed files with 151 additions and 7 deletions.
25 changes: 18 additions & 7 deletions cmd/hooks/wait-paths/main.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
// +build linux

package main

import (
"context"
"errors"
"fmt"
"os"
"strings"
Expand All @@ -18,10 +17,20 @@ const (
timeoutFlag = "timeout"
)

var errEmptyPaths = errors.New("paths cannot be empty")

// This is a hook that waits for a specific path to appear.
// The hook has required list of comma-separated paths and a default timeout in seconds.

func main() {
app := newCliApp()
if err := app.Run(os.Args); err != nil {
logrus.Fatalf("%s\n", err)
}
os.Exit(0)
}

func newCliApp() *cli.App {
app := cli.NewApp()
app.Name = "wait-paths"
app.Usage = "Provide a list paths and an optional timeout"
Expand All @@ -38,14 +47,16 @@ func main() {
},
}
app.Action = run
if err := app.Run(os.Args); err != nil {
logrus.Fatalf("%s\n", err)
}
os.Exit(0)
return app
}

func run(cCtx *cli.Context) error {
timeout := cCtx.GlobalInt(timeoutFlag)

pathsVal := cCtx.GlobalString(pathsFlag)
if pathsVal == "" {
return errEmptyPaths
}
paths := strings.Split(cCtx.GlobalString(pathsFlag), ",")

waitCtx, cancel := context.WithTimeout(context.Background(), time.Duration(timeout)*time.Second)
Expand All @@ -59,7 +70,7 @@ func run(cCtx *cli.Context) error {
}
select {
case <-waitCtx.Done():
return fmt.Errorf("timeout while waiting for path %q to appear", path)
return fmt.Errorf("timeout while waiting for path %q to appear: %w", path, context.DeadlineExceeded)
default:
time.Sleep(time.Millisecond * 10)
continue
Expand Down
133 changes: 133 additions & 0 deletions cmd/hooks/wait-paths/wait_paths_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
package main

import (
"context"
"errors"
"math"
"os"
"path/filepath"
"strings"
"sync"
"testing"
"time"
)

func Test_Paths_EmptyString_NotAllowed(t *testing.T) {
args := []string{
"wait-paths",
"-p",
"",
}
app := newCliApp()
err := app.Run(args)
if !errors.Is(err, errEmptyPaths) {
t.Fatalf("expected 'cannot be empty' error, got: %s", err)
}
}

func Test_InvalidWaitPath_DefaultTimeout(t *testing.T) {
args := []string{
"wait-paths",
"-p",
"non-existent",
}
app := newCliApp()
err := app.Run(args)
if cause := errors.Unwrap(err); !errors.Is(cause, context.DeadlineExceeded) {
t.Fatalf("expected 'timeout error', got: %s", err)
}
}

func Test_InvalidWaitPath_5SecondTimeout(t *testing.T) {
args := []string{
"wait-paths",
"-p",
"non-existent",
"-t",
"5",
}
app := newCliApp()
start := time.Now()
err := app.Run(args)
if cause := errors.Unwrap(err); !errors.Is(cause, context.DeadlineExceeded) {
t.Fatalf("expected 'timeout error', got: %s", err)
}

end := time.Now()
diff := end.Sub(start)
diffSeconds := math.Round(diff.Seconds())
if diffSeconds != 5 {
t.Fatalf("expected 5 second timeout, got: %f", diffSeconds)
}
}

func Test_Valid_Paths_AlreadyPresent(t *testing.T) {
tmpDir := t.TempDir()
var files []string
for _, name := range []string{"file1", "file2"} {
filePath := filepath.Join(tmpDir, name)
if f, err := os.Create(filePath); err != nil {
t.Fatalf("failed to create temporary file %s: %s", name, err)
} else {
_ = f.Close()
}
files = append(files, filePath)
}
pathsArg := strings.Join(files, ",")

args := []string{
"wait-paths",
"-p",
pathsArg,
}
app := newCliApp()
if err := app.Run(args); err != nil {
t.Fatalf("expected no error, got: %s", err)
}
}

func Test_Valid_Paths_BecomeAvailableLater(t *testing.T) {
tmpDir := t.TempDir()
var files []string
for _, name := range []string{"file1", "file2"} {
files = append(files, filepath.Join(tmpDir, name))
}
pathsArg := strings.Join(files, ",")

errChan := make(chan error)
var wg sync.WaitGroup
defer func() {
wg.Wait()
close(errChan)
}()

args := []string{
"wait-paths",
"-p",
pathsArg,
}
app := newCliApp()
wg.Add(1)
go func() {
defer wg.Done()
errChan <- app.Run(args)
}()

wg.Add(1)
go func() {
defer wg.Done()
time.Sleep(5 * time.Second)
for _, fileName := range files {
if f, err := os.Create(fileName); err != nil {
errChan <- err
return
} else {
_ = f.Close()
}
}
}()

if err := <-errChan; err != nil {
t.Fatalf("expected no error, got: %s", err)
}
}

0 comments on commit 1c049f1

Please sign in to comment.