package fs_test import ( "context" "fmt" "testing" "time" "github.com/rclone/rclone/fs" "github.com/rclone/rclone/fs/object" "github.com/rclone/rclone/fstest/mockfs" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) func TestMetadataSet(t *testing.T) { var m fs.Metadata assert.Nil(t, m) m.Set("key", "value") assert.NotNil(t, m) assert.Equal(t, "value", m["key"]) m.Set("key", "value2") assert.Equal(t, "value2", m["key"]) } func TestMetadataMerge(t *testing.T) { for _, test := range []struct { in fs.Metadata merge fs.Metadata want fs.Metadata }{ { in: fs.Metadata{}, merge: fs.Metadata{}, want: fs.Metadata{}, }, { in: nil, merge: nil, want: nil, }, { in: nil, merge: fs.Metadata{}, want: nil, }, { in: nil, merge: fs.Metadata{"a": "1", "b": "2"}, want: fs.Metadata{"a": "1", "b": "2"}, }, { in: fs.Metadata{"a": "1", "b": "2"}, merge: nil, want: fs.Metadata{"a": "1", "b": "2"}, }, { in: fs.Metadata{"a": "1", "b": "2"}, merge: fs.Metadata{"b": "B", "c": "3"}, want: fs.Metadata{"a": "1", "b": "B", "c": "3"}, }, } { what := fmt.Sprintf("in=%v, merge=%v", test.in, test.merge) test.in.Merge(test.merge) assert.Equal(t, test.want, test.in, what) } } func TestMetadataMergeOptions(t *testing.T) { for _, test := range []struct { in fs.Metadata opts []fs.OpenOption want fs.Metadata }{ { opts: []fs.OpenOption{}, want: nil, }, { opts: []fs.OpenOption{&fs.HTTPOption{}}, want: nil, }, { opts: []fs.OpenOption{fs.MetadataOption{"a": "1", "b": "2"}}, want: fs.Metadata{"a": "1", "b": "2"}, }, { opts: []fs.OpenOption{ &fs.HTTPOption{}, fs.MetadataOption{"a": "1", "b": "2"}, fs.MetadataOption{"b": "B", "c": "3"}, &fs.HTTPOption{}, }, want: fs.Metadata{"a": "1", "b": "B", "c": "3"}, }, { in: fs.Metadata{"a": "first", "z": "OK"}, opts: []fs.OpenOption{ &fs.HTTPOption{}, fs.MetadataOption{"a": "1", "b": "2"}, fs.MetadataOption{"b": "B", "c": "3"}, &fs.HTTPOption{}, }, want: fs.Metadata{"a": "1", "b": "B", "c": "3", "z": "OK"}, }, } { what := fmt.Sprintf("in=%v, opts=%v", test.in, test.opts) test.in.MergeOptions(test.opts) assert.Equal(t, test.want, test.in, what) } } func TestMetadataMapper(t *testing.T) { ctx := context.Background() ctx, ci := fs.AddConfig(ctx) ci.Metadata = true require.NoError(t, ci.MetadataMapper.Set("go run metadata_mapper_code.go")) now := time.Date(2001, 2, 3, 4, 5, 6, 7, time.UTC) f, err := mockfs.NewFs(ctx, "dstFs", "dstFsRoot", nil) require.NoError(t, err) t.Run("Normal", func(t *testing.T) { o := object.NewMemoryObject("file.txt", now, []byte("hello")).WithMetadata(fs.Metadata{ "key1": "potato", "key2": "sausage", "key3": "gravy", }) metadata, err := fs.GetMetadataOptions(ctx, f, o, nil) require.NoError(t, err) assert.Equal(t, fs.Metadata{ "key0": "cabbage", "key1": "two potato", "key2": "sausage", }, metadata) }) t.Run("Error", func(t *testing.T) { o := object.NewMemoryObject("file.txt", now, []byte("hello")).WithMetadata(fs.Metadata{ "error": "Red Alert", }) metadata, err := fs.GetMetadataOptions(ctx, f, o, nil) require.Error(t, err) assert.ErrorContains(t, err, "Red Alert") require.Nil(t, metadata) }) t.Run("Merge", func(t *testing.T) { o := object.NewMemoryObject("file.txt", now, []byte("hello")).WithMetadata(fs.Metadata{ "key1": "potato", "key2": "sausage", "key3": "gravy", }) metadata, err := fs.GetMetadataOptions(ctx, f, o, []fs.OpenOption{fs.MetadataOption(fs.Metadata{ "option": "optionValue", "key1": "new potato", "key2": "salami", })}) require.NoError(t, err) assert.Equal(t, fs.Metadata{ "key0": "cabbage", "key1": "two new potato", "key2": "salami", "option": "optionValue", }, metadata) }) }