Repository: rclone/rclone
File: fs/operations/operations_test.go (Go)

Code before:

	for _, test := range []struct {
		offset    int64
		count     int64
		separator string
		a         string
		b         string
	}{
		{0, -1, "", "ABCDEFGHIJ", "012345678"},
		{0, 5, "", "ABCDE", "01234"},
		{-3, -1, "", "HIJ", "678"},
		{1, 3, "", "BCD", "123"},
		{0, -1, "\n", "ABCDEFGHIJ", "012345678"},
	} {
		var buf bytes.Buffer
		err := operations.Cat(ctx, r.Fremote, &buf, test.offset, test.count, []byte(test.separator))
		require.NoError(t, err)
		res := buf.String()

		if res != test.a+test.separator+test.b+test.separator && res != test.b+test.separator+test.a+test.separator {
			t.Errorf("Incorrect output from Cat(%d,%d,%s): %q", test.offset, test.count, test.separator, res)
		}
	}
}

// test that Purge fallback does not result in deadlock from concurrently listing and removing
func TestPurgeListDeadlock(t *testing.T) {
	ctx := context.Background()
	r := fstest.NewRunIndividual(t) // make new container (azureblob has delayed mkdir after rmdir)
	r.Mkdir(ctx, r.Fremote)
	r.Fremote.Features().Disable("Purge") // force fallback-purge

	// make a lot of files to prevent it from finishing too quickly
	for i := 0; i < 100; i++ {
		dst := "file" + fmt.Sprint(i) + ".txt"
		r.WriteObject(ctx, dst, "hello", t1)
	}

	require.NoError(t, operations.Purge(ctx, r.Fremote, ""))
}

func TestPurge(t *testing.T) {
	ctx := context.Background()
	r := fstest.NewRunIndividual(t) // make new container (azureblob has delayed mkdir after rmdir)
	r.Mkdir(ctx, r.Fremote)

	// Make some files and dirs
	r.ForceMkdir(ctx, r.Fremote)
	file1 := r.WriteObject(ctx, "A1/B1/C1/one", "aaa", t1)
	//..and dirs we expect to delete
	require.NoError(t, operations.Mkdir(ctx, r.Fremote, "A2"))

Review comment (performance):
This test should probably be in the internal tests for the memory backend as creating a lot of files will slow down all the integration tests!

Code after:

	for _, test := range []struct {
		offset    int64
		count     int64
		separator string
		a         string
		b         string
	}{
		{0, -1, "", "ABCDEFGHIJ", "012345678"},
		{0, 5, "", "ABCDE", "01234"},
		{-3, -1, "", "HIJ", "678"},
		{1, 3, "", "BCD", "123"},
		{0, -1, "\n", "ABCDEFGHIJ", "012345678"},
	} {
		var buf bytes.Buffer
		err := operations.Cat(ctx, r.Fremote, &buf, test.offset, test.count, []byte(test.separator))
		require.NoError(t, err)
		res := buf.String()

		if res != test.a+test.separator+test.b+test.separator && res != test.b+test.separator+test.a+test.separator {
			t.Errorf("Incorrect output from Cat(%d,%d,%s): %q", test.offset, test.count, test.separator, res)
		}
	}
}

func TestPurge(t *testing.T) {
	ctx := context.Background()
	r := fstest.NewRunIndividual(t) // make new container (azureblob has delayed mkdir after rmdir)
	r.Mkdir(ctx, r.Fremote)

	// Make some files and dirs
	r.ForceMkdir(ctx, r.Fremote)
	file1 := r.WriteObject(ctx, "A1/B1/C1/one", "aaa", t1)
	//..and dirs we expect to delete
	require.NoError(t, operations.Mkdir(ctx, r.Fremote, "A2"))
	require.NoError(t, operations.Mkdir(ctx, r.Fremote, "A1/B2"))
	require.NoError(t, operations.Mkdir(ctx, r.Fremote, "A1/B2/C2"))
	require.NoError(t, operations.Mkdir(ctx, r.Fremote, "A1/B1/C3"))
	require.NoError(t, operations.Mkdir(ctx, r.Fremote, "A3"))
	require.NoError(t, operations.Mkdir(ctx, r.Fremote, "A3/B3"))
	require.NoError(t, operations.Mkdir(ctx, r.Fremote, "A3/B3/C4"))
	//..and one more file at the end
	file2 := r.WriteObject(ctx, "A1/two", "bbb", t2)

	fstest.CheckListingWithPrecision(
		t,
		r.Fremote,
		[]fstest.Item{
			file1, file2,
		},
		[]string{