github.com/hasnat/dolt/go@v0.0.0-20210628190320-9eb5d843fbb7/libraries/doltcore/schema/super_schema_test.go (about) 1 // Copyright 2019 Dolthub, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package schema 16 17 import ( 18 "testing" 19 20 "github.com/stretchr/testify/assert" 21 "github.com/stretchr/testify/require" 22 23 "github.com/dolthub/dolt/go/libraries/doltcore/schema/typeinfo" 24 "github.com/dolthub/dolt/go/store/types" 25 ) 26 27 var sch1 = mustSchema([]Column{ 28 strCol("a", 1, true), 29 strCol("b", 2, false), 30 strCol("c", 3, false), 31 }) 32 33 var sch2 = mustSchema([]Column{ 34 strCol("aa", 1, true), 35 strCol("dd", 4, false), 36 }) 37 38 var sch3 = mustSchema([]Column{ 39 strCol("aaa", 1, true), 40 strCol("bbb", 2, false), 41 strCol("eee", 5, false), 42 }) 43 44 var sch4 = mustSchema([]Column{ 45 strCol("a", 1, true), 46 strCol("eeee", 5, false), 47 strCol("ffff", 6, false), 48 }) 49 50 var nameCollisionWithSch1 = mustSchema([]Column{ 51 strCol("a", 1, true), 52 strCol("b", 22, false), 53 }) 54 55 var tagCollisionWithSch1 = mustSchema([]Column{ 56 strCol("a", 1, true), 57 {"collision", 2, types.IntKind, false, typeinfo.Int32Type, "", false, "", nil}, 58 }) 59 60 type SuperSchemaTest struct { 61 // Name of the test 62 Name string 63 // Schemas to added to the SuperSchema 64 Schemas []Schema 65 // ExpectedSuperSchema to be created 66 ExpectedSuperSchema SuperSchema 67 // ExpectedGeneratedSchema generated by GenerateSchema() 68 ExpectedGeneratedSchema Schema 69 // Expected error message to be returned, if any 70 ExpectedErrString string 71 } 72 73 var SuperSchemaTests = []SuperSchemaTest{ 74 { 75 Name: "SuperSchema of one Schema", 76 Schemas: []Schema{sch1}, 77 ExpectedSuperSchema: SuperSchema{ 78 allCols: mustColColl([]Column{ 79 strCol("", 1, true), 80 strCol("", 2, false), 81 strCol("", 3, false), 82 }), 83 tagNames: map[uint64][]string{1: {"a"}, 2: {"b"}, 3: {"c"}}}, 84 ExpectedGeneratedSchema: sch1, 85 }, 86 { 87 Name: "SuperSchema of multiple Schemas", 88 Schemas: []Schema{sch1, sch2, sch3}, 89 ExpectedSuperSchema: SuperSchema{ 90 allCols: mustColColl([]Column{ 91 strCol("", 1, true), 92 strCol("", 2, false), 93 strCol("", 3, false), 94 strCol("", 4, false), 95 strCol("", 5, false), 96 }), 97 tagNames: map[uint64][]string{1: {"aaa", "aa", "a"}, 2: {"bbb", "b"}, 3: {"c"}, 4: {"dd"}, 5: {"eee"}}, 98 }, 99 ExpectedGeneratedSchema: mustSchema([]Column{ 100 strCol("aaa", 1, true), 101 strCol("bbb", 2, false), 102 strCol("c", 3, false), 103 strCol("dd", 4, false), 104 strCol("eee", 5, false), 105 }), 106 }, 107 { 108 Name: "SuperSchema respects order of added Schemas", 109 Schemas: []Schema{sch3, sch2, sch1}, 110 ExpectedSuperSchema: SuperSchema{ 111 allCols: mustColColl([]Column{ 112 strCol("", 1, true), 113 strCol("", 2, false), 114 strCol("", 5, false), 115 strCol("", 4, false), 116 strCol("", 3, false), 117 }), 118 tagNames: map[uint64][]string{1: {"a", "aa", "aaa"}, 2: {"b", "bbb"}, 3: {"c"}, 4: {"dd"}, 5: {"eee"}}, 119 }, 120 ExpectedGeneratedSchema: mustSchema([]Column{ 121 strCol("a", 1, true), 122 strCol("b", 2, false), 123 strCol("eee", 5, false), 124 strCol("dd", 4, false), 125 strCol("c", 3, false), 126 }), 127 }, 128 { 129 Name: "SuperSchema appends tag to disambiguate name collisions", 130 Schemas: []Schema{sch1, nameCollisionWithSch1}, 131 ExpectedSuperSchema: SuperSchema{ 132 allCols: mustColColl([]Column{ 133 strCol("", 1, true), 134 strCol("", 2, false), 135 strCol("", 3, false), 136 strCol("", 22, false), 137 }), 138 tagNames: map[uint64][]string{1: {"a"}, 2: {"b"}, 3: {"c"}, 22: {"b"}}, 139 }, 140 ExpectedGeneratedSchema: mustSchema([]Column{ 141 strCol("a", 1, true), 142 strCol("b_2", 2, false), 143 strCol("c", 3, false), 144 strCol("b_22", 22, false), 145 }), 146 }, 147 { 148 Name: "SuperSchema errors on tag collision", 149 Schemas: []Schema{sch1, tagCollisionWithSch1}, 150 ExpectedErrString: "tag collision for columns b and collision, different definitions (tag: 2)", 151 }, 152 } 153 154 func TestSuperSchema(t *testing.T) { 155 for _, test := range SuperSchemaTests { 156 t.Run(test.Name, func(t *testing.T) { 157 testSuperSchema(t, test) 158 }) 159 } 160 t.Run("SuperSchemaUnion", func(t *testing.T) { 161 testSuperSchemaUnion(t) 162 }) 163 } 164 165 func testSuperSchema(t *testing.T, test SuperSchemaTest) { 166 ss, err := NewSuperSchema(test.Schemas...) 167 if test.ExpectedErrString != "" { 168 assert.Error(t, err, test.ExpectedErrString) 169 } else { 170 require.NoError(t, err) 171 172 assert.True(t, test.ExpectedSuperSchema.Equals(ss)) 173 // ensure Equals() method works by comparing SuperSchema internals 174 superSchemaDeepEqual(t, &test.ExpectedSuperSchema, ss) 175 176 // ensure naming works correctly in GenerateSchema() 177 gs, err := ss.GenerateSchema() 178 require.NoError(t, err) 179 assert.Equal(t, test.ExpectedGeneratedSchema, gs) 180 181 eq := SchemasAreEqual(test.ExpectedGeneratedSchema, gs) 182 require.NoError(t, err) 183 assert.True(t, eq) 184 } 185 } 186 187 func testSuperSchemaUnion(t *testing.T) { 188 ss12, err := NewSuperSchema(sch1, sch2) 189 require.NoError(t, err) 190 ss34, err := NewSuperSchema(sch3, sch4) 191 require.NoError(t, err) 192 193 unionSuperSchema, err := SuperSchemaUnion(ss12, ss34) 194 require.NoError(t, err) 195 expectedGeneratedSchema := mustSchema([]Column{ 196 strCol("a", 1, true), 197 strCol("bbb", 2, false), 198 strCol("c", 3, false), 199 strCol("dd", 4, false), 200 strCol("eeee", 5, false), 201 strCol("ffff", 6, false), 202 }) 203 gs, err := unionSuperSchema.GenerateSchema() 204 require.NoError(t, err) 205 assert.Equal(t, expectedGeneratedSchema, gs) 206 207 // ensure that SuperSchemaUnion() respects order 208 unionSuperSchema, err = SuperSchemaUnion(ss34, ss12) 209 require.NoError(t, err) 210 expectedGeneratedSchema = mustSchema([]Column{ 211 strCol("aa", 1, true), 212 strCol("b", 2, false), 213 strCol("eeee", 5, false), 214 strCol("ffff", 6, false), 215 strCol("c", 3, false), 216 strCol("dd", 4, false), 217 }) 218 gs, err = unionSuperSchema.GenerateSchema() 219 require.NoError(t, err) 220 assert.Equal(t, expectedGeneratedSchema, gs) 221 } 222 223 func superSchemaDeepEqual(t *testing.T, ss1, ss2 *SuperSchema) { 224 assert.Equal(t, ss1.tagNames, ss2.tagNames) 225 assert.Equal(t, *ss1.allCols, *ss2.allCols) 226 } 227 228 func mustSchema(cols []Column) Schema { 229 return MustSchemaFromCols(mustColColl(cols)) 230 } 231 232 func mustColColl(cols []Column) *ColCollection { 233 return NewColCollection(cols...) 234 } 235 236 func strCol(name string, tag uint64, isPK bool) Column { 237 return Column{name, tag, types.StringKind, isPK, typeinfo.StringDefaultType, "", false, "", nil} 238 }