github.com/hasnat/dolt/go@v0.0.0-20210628190320-9eb5d843fbb7/libraries/doltcore/diff/async_differ_test.go (about) 1 // Copyright 2021 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 diff 16 17 import ( 18 "context" 19 "testing" 20 "time" 21 22 "github.com/stretchr/testify/assert" 23 "github.com/stretchr/testify/require" 24 25 "github.com/dolthub/dolt/go/store/chunks" 26 "github.com/dolthub/dolt/go/store/datas" 27 "github.com/dolthub/dolt/go/store/types" 28 ) 29 30 func TestAsyncDiffer(t *testing.T) { 31 ctx := context.Background() 32 storage := &chunks.MemoryStorage{} 33 db := datas.NewDatabase(storage.NewView()) 34 35 vals := []types.Value{ 36 types.Uint(0), types.String("a"), 37 types.Uint(1), types.String("b"), 38 types.Uint(3), types.String("d"), 39 types.Uint(4), types.String("e"), 40 types.Uint(6), types.String("g"), 41 types.Uint(7), types.String("h"), 42 types.Uint(9), types.String("j"), 43 types.Uint(10), types.String("k"), 44 types.Uint(12), types.String("m"), 45 types.Uint(13), types.String("n"), 46 types.Uint(15), types.String("p"), 47 types.Uint(16), types.String("q"), 48 types.Uint(18), types.String("s"), 49 types.Uint(19), types.String("t"), 50 types.Uint(21), types.String("v"), 51 types.Uint(22), types.String("w"), 52 types.Uint(24), types.String("y"), 53 types.Uint(25), types.String("z"), 54 } 55 56 m1, err := types.NewMap(ctx, db, vals...) 57 require.NoError(t, err) 58 59 vals = []types.Value{ 60 types.Uint(0), types.String("a"), // unchanged 61 //types.Uint(1), types.String("b"), // deleted 62 types.Uint(2), types.String("c"), // added 63 types.Uint(3), types.String("d"), // unchanged 64 //types.Uint(4), types.String("e"), // deleted 65 types.Uint(5), types.String("f"), // added 66 types.Uint(6), types.String("g"), // unchanged 67 //types.Uint(7), types.String("h"), // deleted 68 types.Uint(8), types.String("i"), // added 69 types.Uint(9), types.String("j"), // unchanged 70 //types.Uint(10), types.String("k"), // deleted 71 types.Uint(11), types.String("l"), // added 72 types.Uint(12), types.String("m2"), // changed 73 //types.Uint(13), types.String("n"), // deleted 74 types.Uint(14), types.String("o"), // added 75 types.Uint(15), types.String("p2"), // changed 76 //types.Uint(16), types.String("q"), // deleted 77 types.Uint(17), types.String("r"), // added 78 types.Uint(18), types.String("s2"), // changed 79 //types.Uint(19), types.String("t"), // deleted 80 types.Uint(20), types.String("u"), // added 81 types.Uint(21), types.String("v2"), // changed 82 //types.Uint(22), types.String("w"), // deleted 83 types.Uint(23), types.String("x"), // added 84 types.Uint(24), types.String("y2"), // changed 85 //types.Uint(25), types.String("z"), // deleted 86 } 87 m2, err := types.NewMap(ctx, db, vals...) 88 require.NoError(t, err) 89 90 tests := []struct { 91 name string 92 createdStarted func(ctx context.Context, m1, m2 types.Map) *AsyncDiffer 93 expectedStats map[types.DiffChangeType]uint64 94 }{ 95 { 96 name: "iter all", 97 createdStarted: func(ctx context.Context, m1, m2 types.Map) *AsyncDiffer { 98 ad := NewAsyncDiffer(4) 99 ad.Start(ctx, m1, m2) 100 return ad 101 }, 102 expectedStats: map[types.DiffChangeType]uint64{ 103 types.DiffChangeModified: 5, 104 types.DiffChangeAdded: 8, 105 types.DiffChangeRemoved: 9, 106 }, 107 }, 108 109 { 110 name: "iter range starting with nil", 111 createdStarted: func(ctx context.Context, m1, m2 types.Map) *AsyncDiffer { 112 ad := NewAsyncDiffer(4) 113 ad.StartWithRange(ctx, m1, m2, nil, func(value types.Value) (bool, error) { 114 return true, nil 115 }) 116 return ad 117 }, 118 expectedStats: map[types.DiffChangeType]uint64{ 119 types.DiffChangeModified: 5, 120 types.DiffChangeAdded: 8, 121 types.DiffChangeRemoved: 9, 122 }, 123 }, 124 125 { 126 name: "iter range staring with Null Value", 127 createdStarted: func(ctx context.Context, m1, m2 types.Map) *AsyncDiffer { 128 ad := NewAsyncDiffer(4) 129 ad.StartWithRange(ctx, m1, m2, types.NullValue, func(value types.Value) (bool, error) { 130 return true, nil 131 }) 132 return ad 133 }, 134 expectedStats: map[types.DiffChangeType]uint64{ 135 types.DiffChangeModified: 5, 136 types.DiffChangeAdded: 8, 137 types.DiffChangeRemoved: 9, 138 }, 139 }, 140 141 { 142 name: "iter range less than 17", 143 createdStarted: func(ctx context.Context, m1, m2 types.Map) *AsyncDiffer { 144 ad := NewAsyncDiffer(4) 145 end := types.Uint(27) 146 ad.StartWithRange(ctx, m1, m2, types.NullValue, func(value types.Value) (bool, error) { 147 return value.Less(m1.Format(), end) 148 }) 149 return ad 150 }, 151 expectedStats: map[types.DiffChangeType]uint64{ 152 types.DiffChangeModified: 5, 153 types.DiffChangeAdded: 8, 154 types.DiffChangeRemoved: 9, 155 }, 156 }, 157 158 { 159 name: "iter range less than 15", 160 createdStarted: func(ctx context.Context, m1, m2 types.Map) *AsyncDiffer { 161 ad := NewAsyncDiffer(4) 162 end := types.Uint(15) 163 ad.StartWithRange(ctx, m1, m2, types.NullValue, func(value types.Value) (bool, error) { 164 return value.Less(m1.Format(), end) 165 }) 166 return ad 167 }, 168 expectedStats: map[types.DiffChangeType]uint64{ 169 types.DiffChangeModified: 1, 170 types.DiffChangeAdded: 5, 171 types.DiffChangeRemoved: 5, 172 }, 173 }, 174 175 { 176 name: "iter range 10 < 15", 177 createdStarted: func(ctx context.Context, m1, m2 types.Map) *AsyncDiffer { 178 ad := NewAsyncDiffer(4) 179 start := types.Uint(10) 180 end := types.Uint(15) 181 ad.StartWithRange(ctx, m1, m2, start, func(value types.Value) (bool, error) { 182 return value.Less(m1.Format(), end) 183 }) 184 return ad 185 }, 186 expectedStats: map[types.DiffChangeType]uint64{ 187 types.DiffChangeModified: 1, 188 types.DiffChangeAdded: 2, 189 types.DiffChangeRemoved: 2, 190 }, 191 }, 192 } 193 194 for _, test := range tests { 195 t.Run(test.name, func(t *testing.T) { 196 ctx := context.Background() 197 ad := test.createdStarted(ctx, m1, m2) 198 err := readAll(ad) 199 require.NoError(t, err) 200 require.Equal(t, test.expectedStats, ad.diffStats) 201 }) 202 } 203 204 t.Run("can close without reading all", func(t *testing.T) { 205 ad := NewAsyncDiffer(1) 206 ad.Start(ctx, m1, m2) 207 res, more, err := ad.GetDiffs(1, -1) 208 require.NoError(t, err) 209 assert.True(t, more) 210 assert.Len(t, res, 1) 211 err = ad.Close() 212 assert.NoError(t, err) 213 }) 214 215 t.Run("can filter based on change type", func(t *testing.T) { 216 ad := NewAsyncDiffer(20) 217 ad.Start(ctx, m1, m2) 218 res, more, err := ad.GetDiffs(10, -1) 219 require.NoError(t, err) 220 assert.True(t, more) 221 assert.Len(t, res, 10) 222 err = ad.Close() 223 assert.NoError(t, err) 224 225 ad = NewAsyncDiffer(20) 226 ad.Start(ctx, m1, m2) 227 res, more, err = ad.GetDiffsWithFilter(10, 20*time.Second, types.DiffChangeModified) 228 require.NoError(t, err) 229 assert.False(t, more) 230 assert.Len(t, res, 5) 231 err = ad.Close() 232 assert.NoError(t, err) 233 234 ad = NewAsyncDiffer(20) 235 ad.Start(ctx, m1, m2) 236 res, more, err = ad.GetDiffsWithFilter(6, -1, types.DiffChangeAdded) 237 require.NoError(t, err) 238 assert.True(t, more) 239 assert.Len(t, res, 6) 240 err = ad.Close() 241 assert.NoError(t, err) 242 }) 243 } 244 245 func readAll(ad *AsyncDiffer) error { 246 for { 247 _, more, err := ad.GetDiffs(10, -1) 248 249 if err != nil { 250 return err 251 } 252 253 if !more { 254 break 255 } 256 } 257 258 return nil 259 }