]> git.proxmox.com Git - ceph.git/blame - ceph/src/arrow/go/arrow/schema_test.go
import quincy 17.2.0
[ceph.git] / ceph / src / arrow / go / arrow / schema_test.go
CommitLineData
1d09f67e
TL
1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements. See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership. The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License. You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
16
17package arrow
18
19import (
20 "fmt"
21 "reflect"
22 "testing"
23)
24
25func TestMetadata(t *testing.T) {
26 for _, tc := range []struct {
27 md Metadata
28 kvs map[string]string
29 keys, values []string
30 err string
31 serialize string
32 }{
33 {
34 md: Metadata{
35 keys: []string{"k1", "k2"},
36 values: []string{"v1", "v2"},
37 },
38 keys: []string{"k1", "k2"},
39 values: []string{"v1", "v2"},
40 serialize: `["k1": "v1", "k2": "v2"]`,
41 },
42 {
43 md: Metadata{},
44 serialize: "[]",
45 },
46 {
47 md: Metadata{
48 keys: []string{"k1", "k2"},
49 values: []string{"v1", "v2"},
50 },
51 kvs: map[string]string{"k1": "v1", "k2": "v2"},
52 serialize: `["k1": "v1", "k2": "v2"]`,
53 },
54 {
55 md: Metadata{},
56 keys: []string{"k1", "k2", "k3"},
57 values: []string{"v1", "v2"},
58 err: "arrow: len mismatch",
59 },
60 } {
61 t.Run("", func(t *testing.T) {
62 if tc.err != "" {
63 defer func() {
64 e := recover()
65 if e == nil {
66 t.Fatalf("expected a panic")
67 }
68 if got := e.(string); got != tc.err {
69 t.Fatalf("invalid panic. got=%q, want=%q", got, tc.err)
70 }
71 }()
72 }
73 var md Metadata
74 switch len(tc.kvs) {
75 case 0:
76 md = NewMetadata(tc.keys, tc.values)
77 default:
78 md = MetadataFrom(tc.kvs)
79 }
80 if got, want := md.Len(), len(tc.md.keys); !reflect.DeepEqual(got, want) {
81 t.Fatalf("invalid len: got=%v, want=%v", got, want)
82 }
83 if got, want := md.Keys(), tc.md.keys; !reflect.DeepEqual(got, want) {
84 t.Fatalf("invalid keys: got=%v, want=%v", got, want)
85 }
86 if got, want := md.Values(), tc.md.values; !reflect.DeepEqual(got, want) {
87 t.Fatalf("invalid values: got=%v, want=%v", got, want)
88 }
89 if !reflect.DeepEqual(tc.md, md) {
90 t.Fatalf("invalid md: got=%#v, want=%#v", md, tc.md)
91 }
92 clone := md.clone()
93 if !reflect.DeepEqual(clone, md) {
94 t.Fatalf("invalid clone: got=%#v, want=%#v", clone, md)
95 }
96
97 if got, want := tc.md.String(), tc.serialize; got != want {
98 t.Fatalf("invalid stringer: got=%q, want=%q", got, want)
99 }
100 })
101 }
102
103 t.Run("find-key", func(t *testing.T) {
104 md := NewMetadata([]string{"k1", "k11"}, []string{"v1", "v11"})
105
106 if got, want := md.FindKey("k1"), 0; got != want {
107 t.Fatalf("got=%d, want=%d", got, want)
108 }
109
110 if got, want := md.FindKey(""), -1; got != want {
111 t.Fatalf("got=%d, want=%d", got, want)
112 }
113
114 if got, want := md.FindKey("k"), -1; got != want {
115 t.Fatalf("got=%d, want=%d", got, want)
116 }
117
118 if got, want := md.FindKey(" "), -1; got != want {
119 t.Fatalf("got=%d, want=%d", got, want)
120 }
121
122 if got, want := md.FindKey("k11"), 1; got != want {
123 t.Fatalf("got=%d, want=%d", got, want)
124 }
125
126 if got, want := md.FindKey("k11 "), -1; got != want {
127 t.Fatalf("got=%d, want=%d", got, want)
128 }
129 })
130}
131
132func TestSchema(t *testing.T) {
133 for _, tc := range []struct {
134 fields []Field
135 md *Metadata
136 err error
137 serialize string
138 }{
139 {
140 fields: []Field{
141 {Name: "f1", Type: PrimitiveTypes.Int32},
142 {Name: "f2", Type: PrimitiveTypes.Int64},
143 },
144 md: func() *Metadata {
145 md := MetadataFrom(map[string]string{"k1": "v1", "k2": "v2"})
146 return &md
147 }(),
148 serialize: `schema:
149 fields: 2
150 - f1: type=int32
151 - f2: type=int64
152 metadata: ["k1": "v1", "k2": "v2"]`,
153 },
154 {
155 fields: []Field{
156 {Name: "f1", Type: PrimitiveTypes.Int32},
157 {Name: "f2", Type: PrimitiveTypes.Int64},
158 },
159 md: nil,
160 serialize: `schema:
161 fields: 2
162 - f1: type=int32
163 - f2: type=int64`,
164 },
165 {
166 fields: []Field{
167 {Name: "f1", Type: PrimitiveTypes.Int32},
168 {Name: "f2", Type: nil},
169 },
170 md: nil,
171 err: fmt.Errorf("arrow: field with nil DataType"),
172 },
173 {
174 fields: []Field{
175 {Name: "f1", Type: PrimitiveTypes.Int32},
176 {Name: "f2", Type: PrimitiveTypes.Int64},
177 {Name: "dup", Type: PrimitiveTypes.Int32}, // duplicate
178 {Name: "dup", Type: PrimitiveTypes.Int64}, // duplicate
179 },
180 md: nil,
181 serialize: `schema:
182 fields: 4
183 - f1: type=int32
184 - f2: type=int64
185 - dup: type=int32
186 - dup: type=int64`,
187 },
188 } {
189 t.Run("", func(t *testing.T) {
190 if tc.err != nil {
191 defer func() {
192 e := recover()
193 if e == nil {
194 t.Fatalf("expected a panic %q", tc.err)
195 }
196 switch err := e.(type) {
197 case string:
198 if err != tc.err.Error() {
199 t.Fatalf("invalid panic message. got=%q, want=%q", err, tc.err)
200 }
201 case error:
202 if err.Error() != tc.err.Error() {
203 t.Fatalf("invalid panic message. got=%q, want=%q", err, tc.err)
204 }
205 default:
206 t.Fatalf("invalid type for panic message: %T (err=%v)", err, err)
207 }
208 }()
209 }
210
211 s := NewSchema(tc.fields, tc.md)
212
213 if got, want := len(s.Fields()), len(tc.fields); got != want {
214 t.Fatalf("invalid number of fields. got=%d, want=%d", got, want)
215 }
216
217 if got, want := s.Field(0), tc.fields[0]; !got.Equal(want) {
218 t.Fatalf("invalid field: got=%#v, want=%#v", got, want)
219 }
220
221 if got, want := s.HasMetadata(), tc.md != nil; got != want {
222 t.Fatalf("invalid metadata: got=%v, want=%v", got, want)
223 }
224
225 if tc.md != nil {
226 if got, want := s.Metadata(), *tc.md; !reflect.DeepEqual(got, want) {
227 t.Fatalf("invalid metadata: got=%#v, want=%#v", got, want)
228 }
229 }
230
231 for _, tc := range []struct {
232 name string
233 ok bool
234 fields []Field
235 i []int
236 }{
237 {"f1", true, []Field{tc.fields[0]}, []int{0}},
238 {"f2", true, []Field{tc.fields[1]}, []int{1}},
239 {"N/A", false, nil, nil},
240 } {
241 t.Run(tc.name, func(t *testing.T) {
242 got, ok := s.FieldsByName(tc.name)
243 if ok != tc.ok {
244 t.Fatalf("invalid field %q: got=%v, want=%v", tc.name, ok, tc.ok)
245 }
246 if i := s.FieldIndices(tc.name); !reflect.DeepEqual(i, tc.i) {
247 t.Fatalf("invalid FieldIndices(%s): got=%v, want=%v\nfields: %v", tc.name, i, tc.i, s.fields)
248 }
249 if ok := s.HasField(tc.name); ok != tc.ok {
250 t.Fatalf("invalid HasField(%s): got=%v, want=%v", tc.name, ok, tc.ok)
251 }
252 for i, field := range got {
253 if !field.Equal(tc.fields[i]) {
254 t.Fatalf("invalid field[%d]: got=%#v, want=%#v", i, field, tc.fields[i])
255 }
256 }
257 })
258 }
259
260 if s.HasField("dup") {
261 got := s.FieldIndices("dup")
262 want := []int{2, 3}
263 if !reflect.DeepEqual(got, want) {
264 t.Fatalf("invalid duplicate fields: got=%v, want=%v", got, want)
265 }
266 }
267
268 if got, want := s.String(), tc.serialize; got != want {
269 t.Fatalf("invalid stringer: got=%q, want=%q", got, want)
270 }
271 })
272 }
273}
274
275func TestSchemaEqual(t *testing.T) {
276 fields := []Field{
277 {Name: "f1", Type: PrimitiveTypes.Int32},
278 {Name: "f2", Type: PrimitiveTypes.Int64},
279 }
280 md := func() *Metadata {
281 md := MetadataFrom(map[string]string{"k1": "v1", "k2": "v2"})
282 return &md
283 }()
284
285 for _, tc := range []struct {
286 a, b *Schema
287 want bool
288 }{
289 {
290 a: nil,
291 b: nil,
292 want: true,
293 },
294 {
295 a: nil,
296 b: NewSchema(nil, nil),
297 want: false,
298 },
299 {
300 a: NewSchema(nil, nil),
301 b: nil,
302 want: false,
303 },
304 {
305 a: NewSchema(nil, nil),
306 b: NewSchema(nil, nil),
307 want: true,
308 },
309 {
310 a: NewSchema(fields, nil),
311 b: NewSchema(fields, nil),
312 want: true,
313 },
314 {
315 a: NewSchema(fields, md),
316 b: NewSchema(fields, nil),
317 want: true,
318 },
319 {
320 a: NewSchema(fields, md),
321 b: NewSchema(fields, md),
322 want: true,
323 },
324 {
325 a: NewSchema(fields[:1], md),
326 b: NewSchema(fields, md),
327 want: false,
328 },
329 {
330 a: NewSchema(fields, md),
331 b: NewSchema([]Field{
332 {Name: "f1", Type: PrimitiveTypes.Int32},
333 {Name: "f2", Type: PrimitiveTypes.Int32},
334 }, md),
335 want: false,
336 },
337 {
338 a: NewSchema(fields, md),
339 b: NewSchema([]Field{
340 {Name: "f1", Type: PrimitiveTypes.Int32},
341 {Name: "fx", Type: PrimitiveTypes.Int64},
342 }, md),
343 want: false,
344 },
345 } {
346 t.Run("", func(t *testing.T) {
347 if !tc.a.Equal(tc.a) {
348 t.Fatalf("a != a")
349 }
350 if !tc.b.Equal(tc.b) {
351 t.Fatalf("b != b")
352 }
353 ab := tc.a.Equal(tc.b)
354 if ab != tc.want {
355 t.Fatalf("got=%v, want=%v", ab, tc.want)
356 }
357
358 ba := tc.b.Equal(tc.a)
359 if ab != ba {
360 t.Fatalf("ab != ba")
361 }
362
363 if (tc.a.Fingerprint() == tc.b.Fingerprint()) != tc.want {
364 t.Fatalf("fingerprint: got=%v;%v, wanted=%v", tc.a.Fingerprint(), tc.b.Fingerprint(), tc.want)
365 }
366 })
367 }
368}