github.com/MetalBlockchain/metalgo@v1.11.9/utils/bimap/bimap_test.go (about)

     1  // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved.
     2  // See the file LICENSE for licensing terms.
     3  
     4  package bimap
     5  
     6  import (
     7  	"encoding/json"
     8  	"testing"
     9  
    10  	"github.com/stretchr/testify/require"
    11  )
    12  
    13  func TestBiMapPut(t *testing.T) {
    14  	tests := []struct {
    15  		name            string
    16  		state           *BiMap[int, int]
    17  		key             int
    18  		value           int
    19  		expectedRemoved []Entry[int, int]
    20  		expectedState   *BiMap[int, int]
    21  	}{
    22  		{
    23  			name:            "none removed",
    24  			state:           New[int, int](),
    25  			key:             1,
    26  			value:           2,
    27  			expectedRemoved: nil,
    28  			expectedState: &BiMap[int, int]{
    29  				keyToValue: map[int]int{
    30  					1: 2,
    31  				},
    32  				valueToKey: map[int]int{
    33  					2: 1,
    34  				},
    35  			},
    36  		},
    37  		{
    38  			name: "key removed",
    39  			state: &BiMap[int, int]{
    40  				keyToValue: map[int]int{
    41  					1: 2,
    42  				},
    43  				valueToKey: map[int]int{
    44  					2: 1,
    45  				},
    46  			},
    47  			key:   1,
    48  			value: 3,
    49  			expectedRemoved: []Entry[int, int]{
    50  				{
    51  					Key:   1,
    52  					Value: 2,
    53  				},
    54  			},
    55  			expectedState: &BiMap[int, int]{
    56  				keyToValue: map[int]int{
    57  					1: 3,
    58  				},
    59  				valueToKey: map[int]int{
    60  					3: 1,
    61  				},
    62  			},
    63  		},
    64  		{
    65  			name: "value removed",
    66  			state: &BiMap[int, int]{
    67  				keyToValue: map[int]int{
    68  					1: 2,
    69  				},
    70  				valueToKey: map[int]int{
    71  					2: 1,
    72  				},
    73  			},
    74  			key:   3,
    75  			value: 2,
    76  			expectedRemoved: []Entry[int, int]{
    77  				{
    78  					Key:   1,
    79  					Value: 2,
    80  				},
    81  			},
    82  			expectedState: &BiMap[int, int]{
    83  				keyToValue: map[int]int{
    84  					3: 2,
    85  				},
    86  				valueToKey: map[int]int{
    87  					2: 3,
    88  				},
    89  			},
    90  		},
    91  		{
    92  			name: "key and value removed",
    93  			state: &BiMap[int, int]{
    94  				keyToValue: map[int]int{
    95  					1: 2,
    96  					3: 4,
    97  				},
    98  				valueToKey: map[int]int{
    99  					2: 1,
   100  					4: 3,
   101  				},
   102  			},
   103  			key:   1,
   104  			value: 4,
   105  			expectedRemoved: []Entry[int, int]{
   106  				{
   107  					Key:   1,
   108  					Value: 2,
   109  				},
   110  				{
   111  					Key:   3,
   112  					Value: 4,
   113  				},
   114  			},
   115  			expectedState: &BiMap[int, int]{
   116  				keyToValue: map[int]int{
   117  					1: 4,
   118  				},
   119  				valueToKey: map[int]int{
   120  					4: 1,
   121  				},
   122  			},
   123  		},
   124  	}
   125  	for _, test := range tests {
   126  		t.Run(test.name, func(t *testing.T) {
   127  			require := require.New(t)
   128  
   129  			removed := test.state.Put(test.key, test.value)
   130  			require.Equal(test.expectedRemoved, removed)
   131  			require.Equal(test.expectedState, test.state)
   132  		})
   133  	}
   134  }
   135  
   136  func TestBiMapHasValueAndGetKey(t *testing.T) {
   137  	m := New[int, int]()
   138  	require.Empty(t, m.Put(1, 2))
   139  
   140  	tests := []struct {
   141  		name           string
   142  		value          int
   143  		expectedKey    int
   144  		expectedExists bool
   145  	}{
   146  		{
   147  			name:           "fetch unknown",
   148  			value:          3,
   149  			expectedKey:    0,
   150  			expectedExists: false,
   151  		},
   152  		{
   153  			name:           "fetch known value",
   154  			value:          2,
   155  			expectedKey:    1,
   156  			expectedExists: true,
   157  		},
   158  		{
   159  			name:           "fetch known key",
   160  			value:          1,
   161  			expectedKey:    0,
   162  			expectedExists: false,
   163  		},
   164  	}
   165  	for _, test := range tests {
   166  		t.Run(test.name, func(t *testing.T) {
   167  			require := require.New(t)
   168  
   169  			exists := m.HasValue(test.value)
   170  			require.Equal(test.expectedExists, exists)
   171  
   172  			key, exists := m.GetKey(test.value)
   173  			require.Equal(test.expectedKey, key)
   174  			require.Equal(test.expectedExists, exists)
   175  		})
   176  	}
   177  }
   178  
   179  func TestBiMapHasKeyAndGetValue(t *testing.T) {
   180  	m := New[int, int]()
   181  	require.Empty(t, m.Put(1, 2))
   182  
   183  	tests := []struct {
   184  		name           string
   185  		key            int
   186  		expectedValue  int
   187  		expectedExists bool
   188  	}{
   189  		{
   190  			name:           "fetch unknown",
   191  			key:            3,
   192  			expectedValue:  0,
   193  			expectedExists: false,
   194  		},
   195  		{
   196  			name:           "fetch known key",
   197  			key:            1,
   198  			expectedValue:  2,
   199  			expectedExists: true,
   200  		},
   201  		{
   202  			name:           "fetch known value",
   203  			key:            2,
   204  			expectedValue:  0,
   205  			expectedExists: false,
   206  		},
   207  	}
   208  	for _, test := range tests {
   209  		t.Run(test.name, func(t *testing.T) {
   210  			require := require.New(t)
   211  
   212  			exists := m.HasKey(test.key)
   213  			require.Equal(test.expectedExists, exists)
   214  
   215  			value, exists := m.GetValue(test.key)
   216  			require.Equal(test.expectedValue, value)
   217  			require.Equal(test.expectedExists, exists)
   218  		})
   219  	}
   220  }
   221  
   222  func TestBiMapDeleteKey(t *testing.T) {
   223  	tests := []struct {
   224  		name            string
   225  		state           *BiMap[int, int]
   226  		key             int
   227  		expectedValue   int
   228  		expectedRemoved bool
   229  		expectedState   *BiMap[int, int]
   230  	}{
   231  		{
   232  			name:            "none removed",
   233  			state:           New[int, int](),
   234  			key:             1,
   235  			expectedValue:   0,
   236  			expectedRemoved: false,
   237  			expectedState:   New[int, int](),
   238  		},
   239  		{
   240  			name: "key removed",
   241  			state: &BiMap[int, int]{
   242  				keyToValue: map[int]int{
   243  					1: 2,
   244  				},
   245  				valueToKey: map[int]int{
   246  					2: 1,
   247  				},
   248  			},
   249  			key:             1,
   250  			expectedValue:   2,
   251  			expectedRemoved: true,
   252  			expectedState:   New[int, int](),
   253  		},
   254  	}
   255  	for _, test := range tests {
   256  		t.Run(test.name, func(t *testing.T) {
   257  			require := require.New(t)
   258  
   259  			value, removed := test.state.DeleteKey(test.key)
   260  			require.Equal(test.expectedValue, value)
   261  			require.Equal(test.expectedRemoved, removed)
   262  			require.Equal(test.expectedState, test.state)
   263  		})
   264  	}
   265  }
   266  
   267  func TestBiMapDeleteValue(t *testing.T) {
   268  	tests := []struct {
   269  		name            string
   270  		state           *BiMap[int, int]
   271  		value           int
   272  		expectedKey     int
   273  		expectedRemoved bool
   274  		expectedState   *BiMap[int, int]
   275  	}{
   276  		{
   277  			name:            "none removed",
   278  			state:           New[int, int](),
   279  			value:           1,
   280  			expectedKey:     0,
   281  			expectedRemoved: false,
   282  			expectedState:   New[int, int](),
   283  		},
   284  		{
   285  			name: "key removed",
   286  			state: &BiMap[int, int]{
   287  				keyToValue: map[int]int{
   288  					1: 2,
   289  				},
   290  				valueToKey: map[int]int{
   291  					2: 1,
   292  				},
   293  			},
   294  			value:           2,
   295  			expectedKey:     1,
   296  			expectedRemoved: true,
   297  			expectedState:   New[int, int](),
   298  		},
   299  	}
   300  	for _, test := range tests {
   301  		t.Run(test.name, func(t *testing.T) {
   302  			require := require.New(t)
   303  
   304  			key, removed := test.state.DeleteValue(test.value)
   305  			require.Equal(test.expectedKey, key)
   306  			require.Equal(test.expectedRemoved, removed)
   307  			require.Equal(test.expectedState, test.state)
   308  		})
   309  	}
   310  }
   311  
   312  func TestBiMapLenAndLists(t *testing.T) {
   313  	require := require.New(t)
   314  
   315  	m := New[int, int]()
   316  	require.Zero(m.Len())
   317  	require.Empty(m.Keys())
   318  	require.Empty(m.Values())
   319  
   320  	m.Put(1, 2)
   321  	require.Equal(1, m.Len())
   322  	require.ElementsMatch([]int{1}, m.Keys())
   323  	require.ElementsMatch([]int{2}, m.Values())
   324  
   325  	m.Put(2, 3)
   326  	require.Equal(2, m.Len())
   327  	require.ElementsMatch([]int{1, 2}, m.Keys())
   328  	require.ElementsMatch([]int{2, 3}, m.Values())
   329  
   330  	m.Put(1, 3)
   331  	require.Equal(1, m.Len())
   332  	require.ElementsMatch([]int{1}, m.Keys())
   333  	require.ElementsMatch([]int{3}, m.Values())
   334  
   335  	m.DeleteKey(1)
   336  	require.Zero(m.Len())
   337  	require.Empty(m.Keys())
   338  	require.Empty(m.Values())
   339  }
   340  
   341  func TestBiMapJSON(t *testing.T) {
   342  	require := require.New(t)
   343  
   344  	expectedMap := New[int, int]()
   345  	expectedMap.Put(1, 2)
   346  	expectedMap.Put(2, 3)
   347  
   348  	jsonBytes, err := json.Marshal(expectedMap)
   349  	require.NoError(err)
   350  
   351  	expectedJSONBytes := []byte(`{"1":2,"2":3}`)
   352  	require.Equal(expectedJSONBytes, jsonBytes)
   353  
   354  	var unmarshalledMap BiMap[int, int]
   355  	require.NoError(json.Unmarshal(jsonBytes, &unmarshalledMap))
   356  	require.Equal(expectedMap, &unmarshalledMap)
   357  }
   358  
   359  func TestBiMapInvalidJSON(t *testing.T) {
   360  	require := require.New(t)
   361  
   362  	invalidJSONBytes := []byte(`{"1":2,"2":2}`)
   363  	var unmarshalledMap BiMap[int, int]
   364  	err := json.Unmarshal(invalidJSONBytes, &unmarshalledMap)
   365  	require.ErrorIs(err, errNotBijective)
   366  }