Пример #1
0
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())
}
Пример #2
0
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())
}
Пример #3
0
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)
}
Пример #4
0
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)
}
Пример #5
0
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)
}
Пример #6
0
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)
}
Пример #7
0
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)
}
Пример #8
0
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)
}
Пример #9
0
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))
}
Пример #10
0
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()
}
Пример #11
0
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)
}
Пример #12
0
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)
}
Пример #13
0
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)
}
Пример #14
0
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)
}
Пример #15
0
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)
}
Пример #16
0
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)
}
Пример #17
0
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)
}
Пример #18
0
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)
}
Пример #19
0
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)
}
Пример #20
0
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
		})
	}
}
Пример #21
0
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)
}
Пример #22
0
func TestUnsubscribe(t *testing.T) {
	s := NewGenericSubscription()
	assert.False(t, s.Disposed())
	s.Dispose()
	assert.True(t, s.Disposed())
}