github.com/braveheart12/insolar-09-08-19@v0.8.7/ledger/storage/jet/tree_test.go (about)

     1  /*
     2   *    Copyright 2019 Insolar Technologies
     3   *
     4   *    Licensed under the Apache License, Version 2.0 (the "License");
     5   *    you may not use this file except in compliance with the License.
     6   *    You may obtain a copy of the License at
     7   *
     8   *        http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   *    Unless required by applicable law or agreed to in writing, software
    11   *    distributed under the License is distributed on an "AS IS" BASIS,
    12   *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   *    See the License for the specific language governing permissions and
    14   *    limitations under the License.
    15   */
    16  
    17  package jet
    18  
    19  import (
    20  	"strings"
    21  	"testing"
    22  
    23  	"github.com/insolar/insolar/core"
    24  	"github.com/stretchr/testify/assert"
    25  	"github.com/stretchr/testify/require"
    26  )
    27  
    28  func TestTree_Find(t *testing.T) {
    29  	tree := Tree{
    30  		Head: &jet{
    31  			Right: &jet{
    32  				Right: &jet{
    33  					Left: &jet{
    34  						Right: &jet{},
    35  						Left:  &jet{},
    36  					},
    37  					Right: &jet{},
    38  				},
    39  			},
    40  			Left: &jet{},
    41  		},
    42  	}
    43  	lookup := core.NewRecordID(0, []byte{0xD5}) // 11010101
    44  	jetLookup := NewID(15, []byte{1, 2, 3})
    45  	expectedPrefix := make([]byte, core.RecordIDSize-core.PulseNumberSize-1)
    46  	expectedPrefix[0] = 0xD0 // 11010000
    47  
    48  	id, actual := tree.Find(*lookup)
    49  	depth, prefix := Jet(*id)
    50  	assert.Equal(t, depth, uint8(4))
    51  	assert.Equal(t, expectedPrefix, prefix)
    52  	assert.False(t, actual)
    53  
    54  	jetID, actual := tree.Find(*jetLookup)
    55  	assert.Equal(t, jetLookup, jetID)
    56  	assert.True(t, actual)
    57  }
    58  
    59  func TestTree_Update(t *testing.T) {
    60  	tree := Tree{Head: &jet{}}
    61  
    62  	lookup := core.NewRecordID(0, []byte{0xD5}) // 11010101
    63  
    64  	id, actual := tree.Find(*lookup)
    65  	depth, prefix := Jet(*id)
    66  	assert.Equal(t, depth, uint8(0))
    67  	assert.Equal(t, prefix, make([]byte, core.RecordHashSize-1))
    68  	assert.Equal(t, false, actual)
    69  
    70  	tree.Update(*NewID(1, []byte{1 << 7}), false)
    71  	id, actual = tree.Find(*lookup)
    72  	depth, prefix = Jet(*id)
    73  	expectedPrefix := make([]byte, core.RecordHashSize-1)
    74  	expectedPrefix[0] = 0x80
    75  	require.Equal(t, uint8(1), depth)
    76  	assert.Equal(t, expectedPrefix, prefix)
    77  	assert.Equal(t, false, actual)
    78  
    79  	tree.Update(*NewID(8, lookup.Hash()), false)
    80  	id, actual = tree.Find(*lookup)
    81  	depth, prefix = Jet(*id)
    82  	assert.Equal(t, uint8(8), depth)
    83  	assert.Equal(t, lookup.Hash()[:core.RecordHashSize-1], prefix)
    84  	assert.Equal(t, false, actual)
    85  
    86  	tree.Update(*NewID(8, lookup.Hash()), true)
    87  	id, actual = tree.Find(*lookup)
    88  	depth, prefix = Jet(*id)
    89  	assert.Equal(t, uint8(8), depth)
    90  	assert.Equal(t, lookup.Hash()[:core.RecordHashSize-1], prefix)
    91  	assert.Equal(t, true, actual)
    92  }
    93  
    94  func TestTree_Split(t *testing.T) {
    95  	tree := Tree{
    96  		Head: &jet{
    97  			Right: &jet{
    98  				Right: &jet{},
    99  			},
   100  			Left: &jet{},
   101  		},
   102  	}
   103  	tooDeep := NewID(6, []byte{0xD5}) // 11010101
   104  	ok := NewID(2, []byte{0xD5})      // 11010101
   105  
   106  	t.Run("not existing jet returns error", func(t *testing.T) {
   107  		_, _, err := tree.Split(*tooDeep)
   108  		assert.Error(t, err)
   109  	})
   110  
   111  	t.Run("splits jet", func(t *testing.T) {
   112  		okDepth, okPrefix := Jet(*ok)
   113  		lExpectedPrefix := make([]byte, len(okPrefix))
   114  		copy(lExpectedPrefix, okPrefix)
   115  		lExpectedPrefix[0] = 0xC0 // 11000000
   116  		rExpectedPrefix := make([]byte, len(okPrefix))
   117  		copy(rExpectedPrefix, okPrefix)
   118  		rExpectedPrefix[0] = 0xE0 // 11100000
   119  
   120  		left, right, err := tree.Split(*ok)
   121  		require.NoError(t, err)
   122  		lDepth, lPrefix := Jet(*left)
   123  		rDepth, rPrefix := Jet(*right)
   124  		assert.Equal(t, uint8(okDepth+1), lDepth)
   125  		assert.Equal(t, uint8(okDepth+1), rDepth)
   126  		assert.Equal(t, lExpectedPrefix, lPrefix)
   127  		assert.Equal(t, rExpectedPrefix, rPrefix)
   128  	})
   129  }
   130  
   131  func TestTree_String(t *testing.T) {
   132  	tree := Tree{
   133  		Head: &jet{
   134  			Left: &jet{
   135  				Actual: true,
   136  				Right: &jet{
   137  					Actual: true,
   138  					Left:   &jet{Actual: true},
   139  					Right:  &jet{},
   140  				},
   141  			},
   142  			Right: &jet{
   143  				Left:  &jet{},
   144  				Right: &jet{},
   145  			},
   146  		},
   147  	}
   148  	treeOut := strings.Join([]string{
   149  		"root (level=0 actual=false)",
   150  		" 0 (level=1 actual=true)",
   151  		"  01 (level=2 actual=true)",
   152  		"   010 (level=3 actual=true)",
   153  		"   011 (level=3 actual=false)",
   154  		" 1 (level=1 actual=false)",
   155  		"  10 (level=2 actual=false)",
   156  		"  11 (level=2 actual=false)",
   157  	}, "\n") + "\n"
   158  	assert.Equal(t, treeOut, tree.String())
   159  
   160  	emptyTree := Tree{
   161  		Head: &jet{},
   162  	}
   163  	assert.Equal(t, "root (level=0 actual=false)\n", emptyTree.String())
   164  }
   165  
   166  func TestTree_Merge(t *testing.T) {
   167  	t.Run("One level", func(t *testing.T) {
   168  		savedTree := Tree{
   169  			Head: &jet{
   170  				Left: &jet{
   171  					Actual: true,
   172  				},
   173  				Right: &jet{
   174  					Actual: false,
   175  				},
   176  				Actual: true,
   177  			},
   178  		}
   179  
   180  		newTree := Tree{
   181  			Head: &jet{
   182  				Left: &jet{
   183  					Actual: false,
   184  				},
   185  				Right: &jet{
   186  					Actual: true,
   187  				},
   188  				Actual: false,
   189  			},
   190  		}
   191  
   192  		result := savedTree.Merge(&newTree)
   193  
   194  		require.Equal(t,
   195  			Tree{
   196  				Head: &jet{
   197  					Left: &jet{
   198  						Actual: true,
   199  					},
   200  					Right: &jet{
   201  						Actual: true,
   202  					},
   203  					Actual: true,
   204  				},
   205  			}.String(),
   206  			result.String())
   207  	})
   208  
   209  	t.Run("Five levels saved is false active is true", func(t *testing.T) {
   210  		savedTree := Tree{
   211  			Head: &jet{
   212  				Left: &jet{
   213  					Actual: false,
   214  					Left: &jet{
   215  						Actual: false,
   216  					},
   217  					Right: &jet{
   218  						Actual: false,
   219  					},
   220  				},
   221  				Right: &jet{
   222  					Actual: false,
   223  					Left: &jet{
   224  						Actual: false,
   225  						Left: &jet{
   226  							Actual: false,
   227  						},
   228  						Right: &jet{
   229  							Actual: false,
   230  							Left: &jet{
   231  								Actual: false,
   232  							},
   233  							Right: &jet{
   234  								Actual: false,
   235  							},
   236  						},
   237  					},
   238  					Right: &jet{
   239  						Actual: false,
   240  					},
   241  				},
   242  				Actual: false,
   243  			},
   244  		}
   245  
   246  		newTree := Tree{
   247  			Head: &jet{
   248  				Left: &jet{
   249  					Actual: true,
   250  					Left: &jet{
   251  						Actual: true,
   252  					},
   253  					Right: &jet{
   254  						Actual: true,
   255  					},
   256  				},
   257  				Right: &jet{
   258  					Actual: true,
   259  					Left: &jet{
   260  						Actual: true,
   261  						Left: &jet{
   262  							Actual: true,
   263  						},
   264  						Right: &jet{
   265  							Actual: true,
   266  							Left: &jet{
   267  								Actual: true,
   268  							},
   269  							Right: &jet{
   270  								Actual: true,
   271  							},
   272  						},
   273  					},
   274  					Right: &jet{
   275  						Actual: true,
   276  					},
   277  				},
   278  				Actual: true,
   279  			},
   280  		}
   281  
   282  		result := savedTree.Merge(&newTree)
   283  
   284  		require.Equal(t, newTree.String(), result.String())
   285  	})
   286  
   287  	t.Run("Two levels saved is empty", func(t *testing.T) {
   288  		savedTree := Tree{
   289  			Head: &jet{
   290  				Actual: false,
   291  			},
   292  		}
   293  
   294  		newTree := Tree{
   295  			Head: &jet{
   296  				Left: &jet{
   297  					Actual: true,
   298  					Left: &jet{
   299  						Actual: true,
   300  					},
   301  					Right: &jet{
   302  						Actual: true,
   303  					},
   304  				},
   305  				Right: &jet{
   306  					Actual: true,
   307  					Left: &jet{
   308  						Actual: true,
   309  						Left: &jet{
   310  							Actual: true,
   311  						},
   312  						Right: &jet{
   313  							Actual: true,
   314  							Left: &jet{
   315  								Actual: true,
   316  							},
   317  							Right: &jet{
   318  								Actual: true,
   319  							},
   320  						},
   321  					},
   322  					Right: &jet{
   323  						Actual: true,
   324  					},
   325  				},
   326  				Actual: true,
   327  			},
   328  		}
   329  
   330  		result := savedTree.Merge(&newTree)
   331  
   332  		require.Equal(t, newTree.String(), result.String())
   333  	})
   334  
   335  	t.Run("Three levels saved with left and new with right", func(t *testing.T) {
   336  		savedTree := Tree{
   337  			Head: &jet{
   338  				Actual: true,
   339  				Left: &jet{
   340  					Actual: true,
   341  					Left: &jet{
   342  						Actual: true,
   343  						Left: &jet{
   344  							Actual: true,
   345  						},
   346  					},
   347  					Right: &jet{
   348  						Actual: false,
   349  					},
   350  				},
   351  			},
   352  		}
   353  
   354  		newTree := Tree{
   355  			Head: &jet{
   356  				Right: &jet{
   357  					Right: &jet{
   358  						Actual: true,
   359  						Right: &jet{
   360  							Actual: true,
   361  							Right: &jet{
   362  								Actual: false,
   363  							},
   364  						},
   365  					},
   366  				},
   367  				Actual: true,
   368  			},
   369  		}
   370  
   371  		expectedTree := Tree{
   372  			Head: &jet{
   373  				Left: &jet{
   374  					Actual: true,
   375  					Left: &jet{
   376  						Actual: true,
   377  						Left: &jet{
   378  							Actual: true,
   379  						},
   380  					},
   381  					Right: &jet{
   382  						Actual: false,
   383  					},
   384  				},
   385  
   386  				Actual: true,
   387  
   388  				Right: &jet{
   389  					Right: &jet{
   390  						Actual: true,
   391  						Right: &jet{
   392  							Actual: true,
   393  							Right: &jet{
   394  								Actual: false,
   395  							},
   396  						},
   397  					},
   398  				},
   399  			},
   400  		}
   401  
   402  		result := savedTree.Merge(&newTree)
   403  
   404  		require.Equal(t, expectedTree.String(), result.String())
   405  	})
   406  
   407  	t.Run("heads saved false new true", func(t *testing.T) {
   408  		savedTree := Tree{
   409  			Head: &jet{
   410  				Actual: false,
   411  			},
   412  		}
   413  
   414  		newTree := Tree{
   415  			Head: &jet{
   416  				Actual: true,
   417  			},
   418  		}
   419  
   420  		result := savedTree.Merge(&newTree)
   421  
   422  		require.Equal(t, newTree.String(), result.String())
   423  	})
   424  
   425  	t.Run("heads saved false new true", func(t *testing.T) {
   426  		savedTree := Tree{
   427  			Head: &jet{
   428  				Actual: true,
   429  			},
   430  		}
   431  
   432  		newTree := Tree{
   433  			Head: &jet{
   434  				Actual: false,
   435  			},
   436  		}
   437  
   438  		result := savedTree.Merge(&newTree)
   439  
   440  		require.Equal(t, savedTree.String(), result.String())
   441  	})
   442  }
   443  
   444  func TestTree_LeafIDs(t *testing.T) {
   445  	tree := Tree{
   446  		Head: &jet{
   447  			Right: &jet{
   448  				Right: &jet{
   449  					Left: &jet{
   450  						Right: &jet{},
   451  						Left:  &jet{},
   452  					},
   453  					Right: &jet{},
   454  				},
   455  			},
   456  			Left: &jet{},
   457  		},
   458  	}
   459  
   460  	leafIDs := tree.LeafIDs()
   461  
   462  	require.Equal(t, len(leafIDs), 4)
   463  	assert.Equal(t, leafIDs[0], *NewID(1, nil))          // 0000
   464  	assert.Equal(t, leafIDs[1], *NewID(4, []byte{0xC0})) // 1100
   465  	assert.Equal(t, leafIDs[2], *NewID(4, []byte{0xD0})) // 1101
   466  	assert.Equal(t, leafIDs[3], *NewID(3, []byte{0xE0})) // 1110
   467  }