From 46fd1d3f8fee92fc1f392b3a887005b4710b161e Mon Sep 17 00:00:00 2001 From: Alex Giurgiu Date: Tue, 14 Nov 2023 12:52:11 +0200 Subject: [PATCH] added tests for the concurrent map --- .../utils/concurrentmap/concurrentmap_test.go | 134 ++++++++++++++++++ 1 file changed, 134 insertions(+) create mode 100644 go/libraries/utils/concurrentmap/concurrentmap_test.go diff --git a/go/libraries/utils/concurrentmap/concurrentmap_test.go b/go/libraries/utils/concurrentmap/concurrentmap_test.go new file mode 100644 index 0000000000..779b594c04 --- /dev/null +++ b/go/libraries/utils/concurrentmap/concurrentmap_test.go @@ -0,0 +1,134 @@ +// Copyright 2021 Dolthub, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package concurrentmap + +import ( + "sync" + "testing" +) + +func TestConcurrentMapConstructor(t *testing.T) { + m := New[int, string]() + if m == nil { + t.Fatal("New concurrent map is nil") + } + if m.m == nil { + t.Error("New concurrent map's underlying map is nil") + } + if len(m.m) != 0 { + t.Error("New concurrent map's underlying map is not empty") + } +} + +func TestConcurrentMapSetAndGet(t *testing.T) { + m := New[int, string]() + m.Set(1, "a") + + // Test that the value is set + if val, found := m.Get(1); !found || val != "a" { + t.Errorf("Got %s, want %s", val, "a") + } + // Test that the value is not set for a different key + if val, found := m.Get(2); found || val != "" { + t.Errorf("Got %s, want an empty value and a not found", val) + } +} + +func TestConcurrentMapDelete(t *testing.T) { + m := New[int, string]() + m.Set(1, "a") + m.Delete(1) + + // Test that the value is deleted + if _, found := m.Get(1); found { + t.Errorf("Expected key 1 to be deleted") + } +} + +func TestConcurrentMapLen(t *testing.T) { + m := New[int, string]() + m.Set(1, "a") + m.Set(2, "b") + m.Set(3, "b") + + // Test that the length is correct + if m.Len() != 3 { + t.Errorf("Expected length 3, got %d", m.Len()) + } +} + +func TestConcurrentMapDeepCopy(t *testing.T) { + m := New[int, string]() + m.Set(1, "a") + copy := m.DeepCopy() + m.Set(1, "b") + + // Test that the copy is not affected by the original + if val, _ := copy.Get(1); val != "a" { + t.Errorf("DeepCopy failed, expected 'a', got '%s'", val) + } +} + +func TestConcurrentMapIter(t *testing.T) { + m := New[int, string]() + m.Set(1, "a") + m.Set(2, "b") + m.Set(3, "c") + + counter := 0 + elements := make(map[int]string) + m.Iter(func(key int, value string) bool { + counter++ + elements[key] = value + return true + }) + + // Test that the iterator iterates over all elements + if counter != 3 { + t.Errorf("Iter failed, expected to iterate 3 times, iterated %d times", counter) + } + + // Test that iteration yeilds all elements + if len(elements) != 3 { + t.Errorf("Iter failed, there should be 3 elements in the map, got %d", len(elements)) + } + if elements[1] != "a" || elements[2] != "b" || elements[3] != "c" { + t.Errorf("Iter failed, expected to have 3 elements in the map, with correct values: %v", elements) + } +} + +func TestConcurrentMapSetAndGetWithConcurrency(t *testing.T) { + m := New[int, int]() + var wg sync.WaitGroup + + // Set 100 elements concurrently + for i := 0; i < 100; i++ { + wg.Add(1) + go func(i int) { + defer wg.Done() + m.Set(i, i) + }(i) + } + + // Wait for al goroutines to finish + wg.Wait() + + // Test that all elements are set + for i := 0; i < 100; i++ { + if val, found := m.Get(i); !found || val != i { + t.Errorf("Got %d, want %d", val, i) + } + } +}