func TestLinkedSubscriptionUnsubscribesTargetOnLink(t *testing.T) { linked := NewLinkedSubscription() sub := NewGenericSubscription() linked.Dispose() assert.True(t, linked.Disposed()) assert.False(t, sub.Disposed()) linked.Link(sub) assert.True(t, linked.Disposed()) assert.True(t, sub.Disposed()) }
func TestLinkedSubscription(t *testing.T) { linked := NewLinkedSubscription() sub := NewGenericSubscription() assert.False(t, linked.Disposed()) assert.False(t, sub.Disposed()) linked.Link(sub) assert.Panics(t, func() { linked.Link(sub) }) linked.Dispose() assert.True(t, sub.Disposed()) assert.True(t, linked.Disposed()) }
func TestCombinedShortFlags(t *testing.T) { app := newTestApp() a := app.Flag("short0", "").Short('0').Bool() b := app.Flag("short1", "").Short('1').Bool() c := app.Flag("short2", "").Short('2').Bool() _, err := app.Parse([]string{"-01"}) assert.NoError(t, err) assert.True(t, *a) assert.True(t, *b) assert.False(t, *c) }
func TestChannelSubscription(t *testing.T) { done := make(chan bool) unsubscribed := false var s Subscription = NewChannelSubscription() events, ok := s.(SubscriptionEvents) assert.True(t, ok) events.OnUnsubscribe(func() { unsubscribed = true; done <- true }) assert.False(t, s.Disposed()) s.Dispose() assert.True(t, s.Disposed()) <-done assert.True(t, unsubscribed) }
func TestDoOnComplete(t *testing.T) { complete := false a, err := EmptyInt().DoOnComplete(func() { complete = true }).ToArrayWithError() assert.NoError(t, err) assert.Equal(t, []int{}, a) assert.True(t, complete) }
func TestBool(t *testing.T) { app := newTestApp() b := app.Flag("b", "").Bool() _, err := app.Parse([]string{"--b"}) assert.NoError(t, err) assert.True(t, *b) }
func TestShortFlag(t *testing.T) { app := newTestApp() f := app.Flag("long", "").Short('s').Bool() _, err := app.Parse([]string{"-s"}) assert.NoError(t, err) assert.True(t, *f) }
func TestNestedCommandWithMergedFlags(t *testing.T) { app := New("app", "") cmd0 := app.Command("a", "") cmd0f0 := cmd0.Flag("aflag", "").Bool() // cmd1 := app.Command("b", "") // cmd1f0 := cmd0.Flag("bflag", "").Bool() cmd00 := cmd0.Command("aa", "") cmd00f0 := cmd00.Flag("aaflag", "").Bool() err := app.init() assert.NoError(t, err) context := tokenize(strings.Split("a aa --aflag --aaflag", " "), false) selected, err := parseAndExecute(app, context) assert.NoError(t, err) assert.True(t, *cmd0f0) assert.True(t, *cmd00f0) assert.Equal(t, "a aa", selected) }
func Test_Renewal(t *testing.T) { res := &http.Response{ StatusCode: 400, } assert.True(t, needsRenewal(res, nil)) res.StatusCode = 200 assert.False(t, needsRenewal(res, nil)) }
func TestTimeout(t *testing.T) { wg := sync.WaitGroup{} start := time.Now() wg.Add(1) actual, err := CreateInt(func(observer IntObserver, subscription Subscription) { observer.Next(1) time.Sleep(time.Millisecond * 500) assert.True(t, subscription.Disposed()) wg.Done() }). Timeout(time.Millisecond * 250). ToArrayWithError() elapsed := time.Now().Sub(start) assert.Error(t, err) assert.Equal(t, ErrTimeout, err) assert.True(t, elapsed > time.Millisecond*250 && elapsed < time.Millisecond*500) assert.Equal(t, []int{1}, actual) wg.Wait() }
func TestDispatchCallbackIsCalled(t *testing.T) { dispatched := false c := newTestApp() c.Command("cmd", "").Action(func(*ParseContext) error { dispatched = true return nil }) _, err := c.Parse([]string{"cmd"}) assert.NoError(t, err) assert.True(t, dispatched) }
func Test_NewHealer(t *testing.T) { _, err := NewHealer("", "/dev/null") assert.Error(t, err) _, err = NewHealer("nope,/dev/null", "invalid") assert.Error(t, err) healer, err := NewHealer("archive,/dev/null", "invalid") assert.NoError(t, err) _, ok := healer.(*ArchiveHealer) assert.True(t, ok) }
func TestNestedCommandsWithArgs(t *testing.T) { app := New("app", "") cmd := app.Command("a", "").Command("b", "") a := cmd.Arg("a", "").String() b := cmd.Arg("b", "").String() context := tokenize([]string{"a", "b", "c", "d"}, false) selected, err := parseAndExecute(app, context) assert.NoError(t, err) assert.True(t, context.EOL()) assert.Equal(t, "a b", selected) assert.Equal(t, "c", *a) assert.Equal(t, "d", *b) }
func Test_FanOut(t *testing.T) { t.Logf("Testing fail fast...") ts := &TestSink{ FailingBlock: BlockLocation{ FileIndex: 2, BlockIndex: 2, }, } fos, err := NewFanOutSink(ts, 8) assert.NoError(t, err) fos.Start() hadError := false for i := 0; i < 8; i++ { for j := 0; j < 8; j++ { loc := BlockLocation{ FileIndex: int64(i), BlockIndex: int64(j), } sErr := fos.Store(loc, []byte{}) if sErr != nil { hadError = true } } } assert.True(t, hadError) err = fos.Close() assert.NoError(t, err) t.Logf("Testing tail errors...") fos, err = NewFanOutSink(ts, 8) assert.NoError(t, err) fos.Start() // Store shouldn't err, just queue it... err = fos.Store(ts.FailingBlock, []byte{}) assert.NoError(t, err) // but close should catch the error err = fos.Close() assert.NotNil(t, err) }
func TestNestedCommandsWithFlags(t *testing.T) { app := New("app", "") cmd := app.Command("a", "").Command("b", "") a := cmd.Flag("aaa", "").Short('a').String() b := cmd.Flag("bbb", "").Short('b').String() err := app.init() assert.NoError(t, err) context := tokenize(strings.Split("a b --aaa x -b x", " "), false) selected, err := parseAndExecute(app, context) assert.NoError(t, err) assert.True(t, context.EOL()) assert.Equal(t, "a b", selected) assert.Equal(t, "x", *a) assert.Equal(t, "x", *b) }
func TestRetry(t *testing.T) { errored := false a := CreateInt(func(observer IntObserver, subscription Subscription) { observer.Next(1) observer.Next(2) observer.Next(3) if errored { observer.Complete() } else { observer.Error(errors.New("error")) errored = true } }) b := a.Retry().ToArray() assert.Equal(t, []int{1, 2, 3, 1, 2, 3}, b) assert.True(t, errored) }
func TestArgMultipleRequired(t *testing.T) { terminated := false app := New("test", "") app.Version("0.0.0").Writer(ioutil.Discard) app.Arg("a", "").Required().String() app.Arg("b", "").Required().String() app.Terminate(func(int) { terminated = true }) _, err := app.Parse([]string{}) assert.Error(t, err) _, err = app.Parse([]string{"A"}) assert.Error(t, err) _, err = app.Parse([]string{"A", "B"}) assert.NoError(t, err) _, err = app.Parse([]string{"--version"}) assert.True(t, terminated) }
func TestNestedCommands(t *testing.T) { app := New("app", "") sub1 := app.Command("sub1", "") sub1.Flag("sub1", "") subsub1 := sub1.Command("sub1sub1", "") subsub1.Command("sub1sub1end", "") sub2 := app.Command("sub2", "") sub2.Flag("sub2", "") sub2.Command("sub2sub1", "") context := tokenize([]string{"sub1", "sub1sub1", "sub1sub1end"}, false) selected, err := parseAndExecute(app, context) assert.NoError(t, err) assert.True(t, context.EOL()) assert.Equal(t, "sub1 sub1sub1 sub1sub1end", selected) }
func TestFork(t *testing.T) { ch := make(chan int, 30) s := FromIntChannel(ch).Fork() a := []int{} b := []int{} sub := s.SubscribeNext(func(n int) { a = append(a, n) }) s.SubscribeNext(func(n int) { b = append(b, n) }) ch <- 1 ch <- 2 ch <- 3 runtime.Gosched() sub.Dispose() assert.True(t, sub.Disposed()) ch <- 4 close(ch) s.Wait() assert.Equal(t, []int{1, 2, 3, 4}, b) assert.Equal(t, []int{1, 2, 3}, a) }
func runPatchingScenario(t *testing.T, scenario patchScenario) { log := func(format string, args ...interface{}) { t.Logf("[%s] %s", scenario.name, fmt.Sprintf(format, args...)) } log("Scenario start") mainDir, err := ioutil.TempDir("", "patch-cycle") assert.NoError(t, err) assert.NoError(t, os.MkdirAll(mainDir, 0755)) defer os.RemoveAll(mainDir) v1 := filepath.Join(mainDir, "v1") makeTestDir(t, v1, scenario.v1) v2 := filepath.Join(mainDir, "v2") makeTestDir(t, v2, scenario.v2) compression := &CompressionSettings{} compression.Algorithm = CompressionAlgorithm_NONE sourceContainer, err := tlc.WalkAny(v2, nil) assert.NoError(t, err) consumer := &state.Consumer{} patchBuffer := new(bytes.Buffer) signatureBuffer := new(bytes.Buffer) func() { targetContainer, dErr := tlc.WalkAny(v1, nil) assert.NoError(t, dErr) targetPool := fspool.New(targetContainer, v1) targetSignature, dErr := ComputeSignature(targetContainer, targetPool, consumer) assert.NoError(t, dErr) pool := fspool.New(sourceContainer, v2) dctx := &DiffContext{ Compression: compression, Consumer: consumer, SourceContainer: sourceContainer, Pool: pool, TargetContainer: targetContainer, TargetSignature: targetSignature, } assert.NoError(t, dctx.WritePatch(patchBuffer, signatureBuffer)) }() v1Before := filepath.Join(mainDir, "v1Before") cpDir(t, v1, v1Before) v1After := filepath.Join(mainDir, "v1After") woundsPath := filepath.Join(mainDir, "wounds.pww") if scenario.extraTests { log("Making sure before-path folder doesn't validate") signature, sErr := ReadSignature(bytes.NewReader(signatureBuffer.Bytes())) assert.NoError(t, sErr) assert.Error(t, AssertValid(v1Before, signature)) runExtraTest := func(setup SetupFunc) error { assert.NoError(t, os.RemoveAll(woundsPath)) assert.NoError(t, os.RemoveAll(v1Before)) cpDir(t, v1, v1Before) actx := &ApplyContext{ TargetPath: v1Before, OutputPath: v1Before, InPlace: true, Consumer: consumer, } if setup != nil { setup(actx) } patchReader := bytes.NewReader(patchBuffer.Bytes()) aErr := actx.ApplyPatch(patchReader) if aErr != nil { return aErr } if actx.Signature == nil { vErr := AssertValid(v1Before, signature) if vErr != nil { return vErr } } return nil } func() { log("In-place with failing vet") var NotVettingError = errors.New("not vetting this") pErr := runExtraTest(func(actx *ApplyContext) { actx.VetApply = func(actx *ApplyContext) error { return NotVettingError } }) assert.Error(t, pErr) assert.True(t, errors.Is(pErr, NotVettingError)) }() func() { log("In-place with signature (failfast, passing)") assert.NoError(t, runExtraTest(func(actx *ApplyContext) { actx.Signature = signature })) }() func() { log("In-place with signature (failfast, failing)") assert.Error(t, runExtraTest(func(actx *ApplyContext) { actx.Signature = signature makeTestDir(t, v1Before, *scenario.corruptions) })) }() func() { log("In-place with signature (wounds, passing)") assert.NoError(t, runExtraTest(func(actx *ApplyContext) { actx.Signature = signature actx.WoundsPath = woundsPath })) _, sErr := os.Lstat(woundsPath) assert.Error(t, sErr) assert.True(t, os.IsNotExist(sErr)) }() func() { log("In-place with signature (wounds, failing)") assert.NoError(t, runExtraTest(func(actx *ApplyContext) { actx.Signature = signature actx.WoundsPath = woundsPath makeTestDir(t, v1Before, *scenario.corruptions) })) _, sErr := os.Lstat(woundsPath) assert.NoError(t, sErr) }() } log("Applying to other directory, with separate check") assert.NoError(t, os.RemoveAll(v1Before)) cpDir(t, v1, v1Before) func() { actx := &ApplyContext{ TargetPath: v1Before, OutputPath: v1After, Consumer: consumer, } patchReader := bytes.NewReader(patchBuffer.Bytes()) aErr := actx.ApplyPatch(patchReader) assert.NoError(t, aErr) assert.Equal(t, 0, actx.Stats.DeletedFiles, "deleted files (other dir)") assert.Equal(t, 0, actx.Stats.DeletedDirs, "deleted dirs (other dir)") assert.Equal(t, 0, actx.Stats.DeletedSymlinks, "deleted symlinks (other dir)") assert.Equal(t, 0, actx.Stats.MovedFiles, "moved files (other dir)") assert.Equal(t, len(sourceContainer.Files), actx.Stats.TouchedFiles, "touched files (other dir)") assert.Equal(t, 0, actx.Stats.NoopFiles, "noop files (other dir)") signature, sErr := ReadSignature(bytes.NewReader(signatureBuffer.Bytes())) assert.NoError(t, sErr) assert.NoError(t, AssertValid(v1After, signature)) }() log("Applying in-place") testAll := func(setup SetupFunc) { assert.NoError(t, os.RemoveAll(v1After)) assert.NoError(t, os.RemoveAll(v1Before)) cpDir(t, v1, v1Before) func() { actx := &ApplyContext{ TargetPath: v1Before, OutputPath: v1Before, InPlace: true, Consumer: consumer, } if setup != nil { setup(actx) } patchReader := bytes.NewReader(patchBuffer.Bytes()) aErr := actx.ApplyPatch(patchReader) assert.NoError(t, aErr) assert.Equal(t, scenario.deletedFiles, actx.Stats.DeletedFiles, "deleted files (in-place)") assert.Equal(t, scenario.deletedSymlinks, actx.Stats.DeletedSymlinks, "deleted symlinks (in-place)") assert.Equal(t, scenario.deletedDirs+scenario.leftDirs, actx.Stats.DeletedDirs, "deleted dirs (in-place)") assert.Equal(t, scenario.touchedFiles, actx.Stats.TouchedFiles, "touched files (in-place)") assert.Equal(t, scenario.movedFiles, actx.Stats.MovedFiles, "moved files (in-place)") assert.Equal(t, len(sourceContainer.Files)-scenario.touchedFiles-scenario.movedFiles, actx.Stats.NoopFiles, "noop files (in-place)") signature, sErr := ReadSignature(bytes.NewReader(signatureBuffer.Bytes())) assert.NoError(t, sErr) assert.NoError(t, AssertValid(v1Before, signature)) }() if scenario.intermediate != nil { log("Applying in-place with %d intermediate files", len(scenario.intermediate.entries)) assert.NoError(t, os.RemoveAll(v1After)) assert.NoError(t, os.RemoveAll(v1Before)) cpDir(t, v1, v1Before) makeTestDir(t, v1Before, *scenario.intermediate) func() { actx := &ApplyContext{ TargetPath: v1Before, OutputPath: v1Before, InPlace: true, Consumer: consumer, } if setup != nil { setup(actx) } patchReader := bytes.NewReader(patchBuffer.Bytes()) aErr := actx.ApplyPatch(patchReader) assert.NoError(t, aErr) assert.Equal(t, scenario.deletedFiles, actx.Stats.DeletedFiles, "deleted files (in-place w/intermediate)") assert.Equal(t, scenario.deletedDirs, actx.Stats.DeletedDirs, "deleted dirs (in-place w/intermediate)") assert.Equal(t, scenario.deletedSymlinks, actx.Stats.DeletedSymlinks, "deleted symlinks (in-place w/intermediate)") assert.Equal(t, scenario.touchedFiles, actx.Stats.TouchedFiles, "touched files (in-place w/intermediate)") assert.Equal(t, scenario.noopFiles, actx.Stats.NoopFiles, "noop files (in-place w/intermediate)") assert.Equal(t, scenario.leftDirs, actx.Stats.LeftDirs, "left dirs (in-place w/intermediate)") signature, sErr := ReadSignature(bytes.NewReader(signatureBuffer.Bytes())) assert.NoError(t, sErr) assert.NoError(t, AssertValid(v1Before, signature)) }() } } testAll(nil) if scenario.testBrokenRename { testAll(func(actx *ApplyContext) { actx.debugBrokenRename = true }) } }
func Test_WriterClose(t *testing.T) { dropSize := 16 t.Logf("validation error on close") buf := make([]byte, dropSize) var validateError = errors.New("validation error") var underWriteError = errors.New("underlying write error") var underCloseError = errors.New("underlying close error") tw := &tracingWriter{} dw := &Writer{ Buffer: buf, Validate: func(buf []byte) error { return validateError }, Writer: tw, } _, wErr := dw.Write([]byte{1, 2, 3, 4}) assert.NoError(t, wErr) cErr := dw.Close() assert.Error(t, cErr) assert.Equal(t, validateError, cErr) assert.True(t, tw.closeCall) t.Logf("underlying write error on close") tw = &tracingWriter{ writeErr: underWriteError, } dw = &Writer{ Buffer: buf, Validate: func(buf []byte) error { return nil }, Writer: tw, } _, wErr = dw.Write([]byte{1, 2, 3, 4}) assert.NoError(t, wErr) cErr = dw.Close() assert.Error(t, cErr) assert.Equal(t, underWriteError, cErr) assert.True(t, tw.closeCall) t.Logf("underlying close error on close") tw = &tracingWriter{ closeErr: underCloseError, } dw = &Writer{ Buffer: buf, Validate: func(buf []byte) error { return nil }, Writer: tw, } _, wErr = dw.Write([]byte{1, 2, 3, 4}) assert.NoError(t, wErr) cErr = dw.Close() assert.Error(t, cErr) assert.Equal(t, underCloseError, cErr) assert.True(t, tw.closeCall) }
func TestUnsubscribe(t *testing.T) { s := NewGenericSubscription() assert.False(t, s.Disposed()) s.Dispose() assert.True(t, s.Disposed()) }