summaryrefslogtreecommitdiff
path: root/data/datasource_merge_test.go
blob: 48d1f85e7ec522d536cf266735631b0c634e0f26 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
package data

import (
	"context"
	"io/fs"
	"net/url"
	"os"
	"path"
	"path/filepath"
	"testing"
	"testing/fstest"

	"github.com/hairyhenderson/gomplate/v4/internal/datafs"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
)

func TestReadMerge(t *testing.T) {
	ctx := context.Background()

	jsonContent := `{"hello": "world"}`
	yamlContent := "hello: earth\ngoodnight: moon\n"
	arrayContent := `["hello", "world"]`

	mergedContent := "goodnight: moon\nhello: world\n"

	wd, _ := os.Getwd()

	// MapFS doesn't support windows path separators, so we use / exclusively
	// in this test
	vol := filepath.VolumeName(wd)
	if vol != "" && wd != vol {
		wd = wd[len(vol)+1:]
	} else if wd[0] == '/' {
		wd = wd[1:]
	}
	wd = filepath.ToSlash(wd)

	fsys := datafs.WrapWdFS(fstest.MapFS{
		"tmp":                          {Mode: fs.ModeDir | 0o777},
		"tmp/jsonfile.json":            {Data: []byte(jsonContent)},
		"tmp/array.json":               {Data: []byte(arrayContent)},
		"tmp/yamlfile.yaml":            {Data: []byte(yamlContent)},
		"tmp/textfile.txt":             {Data: []byte(`plain text...`)},
		path.Join(wd, "jsonfile.json"): {Data: []byte(jsonContent)},
		path.Join(wd, "array.json"):    {Data: []byte(arrayContent)},
		path.Join(wd, "yamlfile.yaml"): {Data: []byte(yamlContent)},
		path.Join(wd, "textfile.txt"):  {Data: []byte(`plain text...`)},
	})

	source := &Source{Alias: "foo", URL: mustParseURL("merge:file:///tmp/jsonfile.json|file:///tmp/yamlfile.yaml")}
	source.fs = fsys
	d := &Data{
		Sources: map[string]*Source{
			"foo":       source,
			"bar":       {Alias: "bar", URL: mustParseURL("file:///tmp/jsonfile.json")},
			"baz":       {Alias: "baz", URL: mustParseURL("file:///tmp/yamlfile.yaml")},
			"text":      {Alias: "text", URL: mustParseURL("file:///tmp/textfile.txt")},
			"badscheme": {Alias: "badscheme", URL: mustParseURL("bad:///scheme.json")},
			"badtype":   {Alias: "badtype", URL: mustParseURL("file:///tmp/textfile.txt?type=foo/bar")},
			"array":     {Alias: "array", URL: mustParseURL("file:///tmp/array.json?type=" + url.QueryEscape(jsonArrayMimetype))},
		},
	}

	actual, err := d.readMerge(ctx, source)
	require.NoError(t, err)
	assert.Equal(t, mergedContent, string(actual))

	source.URL = mustParseURL("merge:bar|baz")
	actual, err = d.readMerge(ctx, source)
	require.NoError(t, err)
	assert.Equal(t, mergedContent, string(actual))

	source.URL = mustParseURL("merge:jsonfile.json|baz")
	actual, err = d.readMerge(ctx, source)
	require.NoError(t, err)
	assert.Equal(t, mergedContent, string(actual))

	source.URL = mustParseURL("merge:./jsonfile.json|baz")
	actual, err = d.readMerge(ctx, source)
	require.NoError(t, err)
	assert.Equal(t, mergedContent, string(actual))

	source.URL = mustParseURL("merge:file:///tmp/jsonfile.json")
	_, err = d.readMerge(ctx, source)
	assert.Error(t, err)

	source.URL = mustParseURL("merge:bogusalias|file:///tmp/jsonfile.json")
	_, err = d.readMerge(ctx, source)
	assert.Error(t, err)

	source.URL = mustParseURL("merge:file:///tmp/jsonfile.json|badscheme")
	_, err = d.readMerge(ctx, source)
	assert.Error(t, err)

	source.URL = mustParseURL("merge:file:///tmp/jsonfile.json|badtype")
	_, err = d.readMerge(ctx, source)
	assert.Error(t, err)

	source.URL = mustParseURL("merge:file:///tmp/jsonfile.json|array")
	_, err = d.readMerge(ctx, source)
	assert.Error(t, err)
}

func TestMergeData(t *testing.T) {
	def := map[string]interface{}{
		"f": true,
		"t": false,
		"z": "def",
	}
	out, err := mergeData([]map[string]interface{}{def})
	require.NoError(t, err)
	assert.Equal(t, "f: true\nt: false\nz: def\n", string(out))

	over := map[string]interface{}{
		"f": false,
		"t": true,
		"z": "over",
	}
	out, err = mergeData([]map[string]interface{}{over, def})
	require.NoError(t, err)
	assert.Equal(t, "f: false\nt: true\nz: over\n", string(out))

	over = map[string]interface{}{
		"f": false,
		"t": true,
		"z": "over",
		"m": map[string]interface{}{
			"a": "aaa",
		},
	}
	out, err = mergeData([]map[string]interface{}{over, def})
	require.NoError(t, err)
	assert.Equal(t, "f: false\nm:\n  a: aaa\nt: true\nz: over\n", string(out))

	uber := map[string]interface{}{
		"z": "über",
	}
	out, err = mergeData([]map[string]interface{}{uber, over, def})
	require.NoError(t, err)
	assert.Equal(t, "f: false\nm:\n  a: aaa\nt: true\nz: über\n", string(out))

	uber = map[string]interface{}{
		"m": "notamap",
		"z": map[string]interface{}{
			"b": "bbb",
		},
	}
	out, err = mergeData([]map[string]interface{}{uber, over, def})
	require.NoError(t, err)
	assert.Equal(t, "f: false\nm: notamap\nt: true\nz:\n  b: bbb\n", string(out))

	uber = map[string]interface{}{
		"m": map[string]interface{}{
			"b": "bbb",
		},
	}
	out, err = mergeData([]map[string]interface{}{uber, over, def})
	require.NoError(t, err)
	assert.Equal(t, "f: false\nm:\n  a: aaa\n  b: bbb\nt: true\nz: over\n", string(out))
}