@@ -144,45 +144,63 @@ describe('.findMax()', () => {
144144 } ) ;
145145} ) ;
146146
147- describe ( '.clone()' , ( ) => {
148- const setup = ( ) => {
149- const model = Model . create ( { foo : 'bar' } ) ;
150- const log1 = Log . fromNewModel ( model ) ;
151- log1 . metadata = { time : 123 } ;
152- log1 . end . api . obj ( [ ] ) . set ( { x : 1 } ) ;
153- log1 . end . api . flush ( ) ;
154- log1 . end . api . obj ( [ ] ) . set ( { y : 2 } ) ;
155- log1 . end . api . flush ( ) ;
156- log1 . end . api . obj ( [ ] ) . set ( { foo : 'baz' } ) ;
157- log1 . end . api . flush ( ) ;
158- const log2 = log1 . clone ( ) ;
159- return { log1, log2} ;
160- } ;
147+ const setupTwoLogs = ( ) => {
148+ const model = Model . create ( { foo : 'bar' } ) ;
149+ const log1 = Log . fromNewModel ( model ) ;
150+ log1 . metadata = { time : 123 } ;
151+ log1 . end . api . obj ( [ ] ) . set ( { x : 1 } ) ;
152+ log1 . end . api . flush ( ) ;
153+ log1 . end . api . obj ( [ ] ) . set ( { y : 2 } ) ;
154+ log1 . end . api . flush ( ) ;
155+ log1 . end . api . obj ( [ ] ) . set ( { foo : 'baz' } ) ;
156+ log1 . end . api . flush ( ) ;
157+ const log2 = log1 . clone ( ) ;
158+ return { log1, log2} ;
159+ } ;
161160
161+ const assertLogsEqual = ( log1 : Log < any , any > , log2 : Log < any , any > ) => {
162+ expect ( log1 . start ( ) ) . not . toBe ( log2 . start ( ) ) ;
163+ expect ( deepEqual ( log1 . start ( ) . view ( ) , log2 . start ( ) . view ( ) ) ) . toBe ( true ) ;
164+ expect ( log1 . start ( ) . clock . sid ) . toEqual ( log2 . start ( ) . clock . sid ) ;
165+ expect ( log1 . start ( ) . clock . time ) . toEqual ( log2 . start ( ) . clock . time ) ;
166+ expect ( log1 . end ) . not . toBe ( log2 . end ) ;
167+ expect ( deepEqual ( log1 . end . view ( ) , log2 . end . view ( ) ) ) . toBe ( true ) ;
168+ expect ( log1 . end . clock . sid ) . toEqual ( log2 . end . clock . sid ) ;
169+ expect ( log1 . end . clock . time ) . toEqual ( log2 . end . clock . time ) ;
170+ expect ( log1 . metadata ) . not . toBe ( log2 . metadata ) ;
171+ expect ( deepEqual ( log1 . metadata , log2 . metadata ) ) . toBe ( true ) ;
172+ expect ( log1 . patches . size ( ) ) . toBe ( log2 . patches . size ( ) ) ;
173+ expect ( log1 . patches . min ! . v . toBinary ( ) ) . toEqual ( log2 . patches . min ! . v . toBinary ( ) ) ;
174+ expect ( log1 . patches . max ! . v . toBinary ( ) ) . toEqual ( log2 . patches . max ! . v . toBinary ( ) ) ;
175+ expect ( log1 . patches . min ! . v ) . not . toBe ( log2 . patches . min ! . v ) ;
176+ expect ( log1 . patches . max ! . v ) . not . toBe ( log2 . patches . max ! . v ) ;
177+ } ;
178+
179+ describe ( '.clone()' , ( ) => {
162180 test ( 'start model has the same view and clock' , ( ) => {
163- const { log1, log2} = setup ( ) ;
181+ const { log1, log2} = setupTwoLogs ( ) ;
164182 expect ( log1 . start ( ) ) . not . toBe ( log2 . start ( ) ) ;
165183 expect ( deepEqual ( log1 . start ( ) . view ( ) , log2 . start ( ) . view ( ) ) ) . toBe ( true ) ;
166184 expect ( log1 . start ( ) . clock . sid ) . toEqual ( log2 . start ( ) . clock . sid ) ;
167185 expect ( log1 . start ( ) . clock . time ) . toEqual ( log2 . start ( ) . clock . time ) ;
168186 } ) ;
169187
170188 test ( 'end model has the same view and clock' , ( ) => {
171- const { log1, log2} = setup ( ) ;
189+ const { log1, log2} = setupTwoLogs ( ) ;
172190 expect ( log1 . end ) . not . toBe ( log2 . end ) ;
173191 expect ( deepEqual ( log1 . end . view ( ) , log2 . end . view ( ) ) ) . toBe ( true ) ;
174192 expect ( log1 . end . clock . sid ) . toEqual ( log2 . end . clock . sid ) ;
175193 expect ( log1 . end . clock . time ) . toEqual ( log2 . end . clock . time ) ;
176194 } ) ;
177195
178196 test ( 'metadata is the same but has different identity' , ( ) => {
179- const { log1, log2} = setup ( ) ;
197+ const { log1, log2} = setupTwoLogs ( ) ;
180198 expect ( log1 . metadata ) . not . toBe ( log2 . metadata ) ;
181199 expect ( deepEqual ( log1 . metadata , log2 . metadata ) ) . toBe ( true ) ;
182200 } ) ;
183201
184202 test ( 'patch log is the same' , ( ) => {
185- const { log1, log2} = setup ( ) ;
203+ const { log1, log2} = setupTwoLogs ( ) ;
186204 expect ( log1 . patches . size ( ) ) . toBe ( log2 . patches . size ( ) ) ;
187205 expect ( log1 . patches . min ! . v . toBinary ( ) ) . toEqual ( log2 . patches . min ! . v . toBinary ( ) ) ;
188206 expect ( log1 . patches . max ! . v . toBinary ( ) ) . toEqual ( log2 . patches . max ! . v . toBinary ( ) ) ;
@@ -191,7 +209,8 @@ describe('.clone()', () => {
191209 } ) ;
192210
193211 test ( 'can evolve logs independently' , ( ) => {
194- const { log1, log2} = setup ( ) ;
212+ const { log1, log2} = setupTwoLogs ( ) ;
213+ assertLogsEqual ( log1 , log2 ) ;
195214 log1 . end . api . obj ( [ ] ) . set ( { a : 1 } ) ;
196215 log1 . end . api . flush ( ) ;
197216 expect ( log1 . end . view ( ) ) . toEqual ( { foo : 'baz' , x : 1 , y : 2 , a : 1 } ) ;
@@ -203,27 +222,79 @@ describe('.clone()', () => {
203222 } ) ;
204223} ) ;
205224
206- describe ( '.rebase()' , ( ) => {
207- test ( 'can advance the log from start' , ( ) => {
208- const model = Model . create ( ) ;
209- const sid0 = model . clock . sid ;
210- const sid1 = Model . sid ( ) ;
211- model . api . set ( { foo : 'bar' } ) ;
212- const log = Log . fromNewModel ( model ) ;
213- log . end . api . obj ( [ ] ) . set ( { x : 1 } ) ;
214- const patch1 = log . end . api . flush ( ) ;
215- log . end . setSid ( sid1 ) ;
216- log . end . api . obj ( [ ] ) . set ( { y : 2 } ) ;
217- const patch2 = log . end . api . flush ( ) ;
218- log . end . setSid ( sid0 ) ;
219- log . end . api . obj ( [ ] ) . set ( { foo : 'baz' } ) ;
220- const patch3 = log . end . api . flush ( ) ;
221- const found0 = log . findMax ( sid0 ) ;
222- const found1 = log . findMax ( sid1 ) ;
223- const found2 = log . findMax ( 12345 ) ;
224- expect ( found0 ) . toBe ( patch3 ) ;
225- expect ( found1 ) . toBe ( patch2 ) ;
226- expect ( found2 ) . toBe ( void 0 ) ;
225+ describe ( '.rebaseBatch()' , ( ) => {
226+ test ( 'can rebase a concurrent batch onto another log' , ( ) => {
227+ const { log1, log2} = setupTwoLogs ( ) ;
228+ log1 . end . api . obj ( [ ] ) . set ( { a : 1 } ) ;
229+ log2 . end . api . obj ( [ ] ) . set ( { b : 2 } ) ;
230+ const patch1 = log1 . end . api . flush ( ) ;
231+ const patch2 = log2 . end . api . flush ( ) ;
232+ expect ( patch1 . toBinary ( ) ) . not . toEqual ( patch2 . toBinary ( ) ) ;
233+ expect ( patch1 . getId ( ) ?. sid ) . toBe ( patch2 . getId ( ) ?. sid ) ;
234+ expect ( patch1 . getId ( ) ?. time ) . toBe ( patch2 . getId ( ) ?. time ) ;
235+ expect ( patch1 . span ( ) ) . toEqual ( patch2 . span ( ) ) ;
236+ const [ patch3 ] = log1 . rebaseBatch ( [ patch2 ] ) ;
237+ expect ( patch1 . toBinary ( ) ) . not . toEqual ( patch3 . toBinary ( ) ) ;
238+ expect ( patch1 . getId ( ) ?. sid ) . toBe ( patch3 . getId ( ) ?. sid ) ;
239+ expect ( patch1 . getId ( ) ! . time + patch1 . span ( ) ) . toBe ( patch3 . getId ( ) ?. time ) ;
240+ log1 . end . applyPatch ( patch3 ) ;
241+ expect ( log1 . end . view ( ) ) . toEqual ( { foo : 'baz' , x : 1 , y : 2 , a : 1 , b : 2 } ) ;
242+ expect ( log2 . end . view ( ) ) . toEqual ( { foo : 'baz' , x : 1 , y : 2 , b : 2 } ) ;
243+ expect ( ( ) => assertLogsEqual ( log1 , log2 ) ) . toThrow ( ) ;
244+ log2 . reset ( log1 . clone ( ) ) ;
245+ assertLogsEqual ( log1 , log2 ) ;
246+ } ) ;
247+
248+ test ( 'can rebase a concurrent batch onto another log (multiple patches)' , ( ) => {
249+ const { log1, log2} = setupTwoLogs ( ) ;
250+ log1 . end . api . obj ( [ ] ) . set ( { a : 1 } ) ;
251+ log2 . end . api . obj ( [ ] ) . set ( { b : 2 } ) ;
252+ log1 . end . api . flush ( ) ;
253+ const patch2 = log2 . end . api . flush ( ) ;
254+ log1 . end . api . obj ( [ ] ) . set ( { a : 2 } ) ;
255+ log2 . end . api . obj ( [ ] ) . set ( { b : 3 } ) ;
256+ log1 . end . api . flush ( ) ;
257+ const patch4 = log2 . end . api . flush ( ) ;
258+ log2 . end . api . obj ( [ ] ) . set ( { b : 3 } ) ;
259+ const patch5 = log2 . end . api . flush ( ) ;
260+ const batch2 = [ patch2 , patch4 , patch5 ] ;
261+ expect ( log1 . end . view ( ) ) . toEqual ( { foo : 'baz' , x : 1 , y : 2 , a : 2 } ) ;
262+ expect ( log2 . end . view ( ) ) . toEqual ( { foo : 'baz' , x : 1 , y : 2 , b : 3 } ) ;
263+ const batch3 = log1 . rebaseBatch ( batch2 ) ;
264+ expect ( batch3 [ 0 ] . getId ( ) ! . time ) . toBe ( log1 . end . clock . time ) ;
265+ log1 . end . applyBatch ( batch3 ) ;
266+ expect ( log1 . end . view ( ) ) . toEqual ( { foo : 'baz' , x : 1 , y : 2 , a : 2 , b : 3 } ) ;
267+ expect ( log2 . end . view ( ) ) . toEqual ( { foo : 'baz' , x : 1 , y : 2 , b : 3 } ) ;
268+ expect ( ( ) => assertLogsEqual ( log1 , log2 ) ) . toThrow ( ) ;
269+ log2 . reset ( log1 . clone ( ) ) ;
270+ assertLogsEqual ( log1 , log2 ) ;
271+ } ) ;
272+
273+ test ( 'can specify rebase sid' , ( ) => {
274+ const { log1, log2} = setupTwoLogs ( ) ;
275+ expect ( log1 . end . clock . sid ) . toBe ( log2 . end . clock . sid ) ;
276+ log1 . end . api . obj ( [ ] ) . set ( { a : 1 } ) ;
277+ log2 . end . api . obj ( [ ] ) . set ( { b : 2 } ) ;
278+ log1 . end . api . flush ( ) ;
279+ const patch2 = log2 . end . api . flush ( ) ;
280+ log1 . end . setSid ( 12345 ) ;
281+ log1 . end . api . obj ( [ ] ) . set ( { a : 2 } ) ;
282+ log2 . end . api . obj ( [ ] ) . set ( { b : 3 } ) ;
283+ log1 . end . api . flush ( ) ;
284+ const patch4 = log2 . end . api . flush ( ) ;
285+ log2 . end . api . obj ( [ ] ) . set ( { b : 3 } ) ;
286+ const patch5 = log2 . end . api . flush ( ) ;
287+ const batch2 = [ patch2 , patch4 , patch5 ] ;
288+ expect ( log1 . end . view ( ) ) . toEqual ( { foo : 'baz' , x : 1 , y : 2 , a : 2 } ) ;
289+ expect ( log2 . end . view ( ) ) . toEqual ( { foo : 'baz' , x : 1 , y : 2 , b : 3 } ) ;
290+ const batch3 = log1 . rebaseBatch ( batch2 , log2 . end . clock . sid ) ;
291+ expect ( batch3 [ 0 ] . getId ( ) ! . time ) . not . toBe ( log1 . end . clock . time ) ;
292+ log1 . end . applyBatch ( batch3 ) ;
293+ expect ( log1 . end . view ( ) ) . toEqual ( { foo : 'baz' , x : 1 , y : 2 , a : 2 , b : 3 } ) ;
294+ expect ( log2 . end . view ( ) ) . toEqual ( { foo : 'baz' , x : 1 , y : 2 , b : 3 } ) ;
295+ expect ( ( ) => assertLogsEqual ( log1 , log2 ) ) . toThrow ( ) ;
296+ log2 . reset ( log1 . clone ( ) ) ;
297+ assertLogsEqual ( log1 , log2 ) ;
227298 } ) ;
228299} ) ;
229300
0 commit comments