Some checks failed
Server CI / Postgres (shard 0) (push) Has been skipped
Server CI / Postgres (shard 3) (push) Has been skipped
BuildEnv Docker Image / build-image (push) Failing after 4s
BuildEnv Docker Image / build-image-fips (push) Failing after 4s
Migration Review & Release Notes / Generate migration review & release notes (push) Failing after 3s
Server CI / Build Environment (push) Failing after 3s
Server CI / Postgres (shard 1) (push) Has been skipped
Tools CI / check-style (mattermost-govet) (push) Failing after 4s
Server CI / Postgres (shard 2) (push) Has been skipped
Tools CI / check-style (mmgotool) (push) Failing after 3s
Server CI / Elasticsearch v8 Compatibility (push) Has been skipped
Server CI / OpenSearch v2 Compatibility (push) Has been skipped
Server CI / Postgres FIPS (shard 0) (push) Has been skipped
Tools CI / Test (mattermost-govet) (push) Failing after 3s
Server CI / Postgres FIPS (shard 1) (push) Has been skipped
Server CI / Postgres FIPS (shard 2) (push) Has been skipped
Tools CI / Test (mmgotool) (push) Failing after 3s
Server CI / Postgres FIPS (shard 3) (push) Has been skipped
Server CI / Run mmctl tests (push) Has been skipped
Server CI / Run mmctl tests (FIPS) (push) Has been skipped
Server CI / Merge Postgres Test Results (push) Has been skipped
Server CI / Merge Postgres FIPS Test Results (push) Has been skipped
Server CI / Check backport migrations (push) Has been skipped
Server CI / Check generated files (push) Has been skipped
Server CI / check-style (push) Has been skipped
Server CI / Vet API (push) Has been skipped
Server CI / Build mattermost server app (push) Has been skipped
Server CI / Server CI Complete (push) Failing after 2s
Server CI / Server CI Artifacts (push) Has been skipped
Server CI / Sentry Upload (push) Has been skipped
Server CI / Server CI Report (push) Failing after 5m1s
Server CI Nightly Race / Race Detector (push) Has been skipped
CodeQL / Analyze (go) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Webapp CI Cache Warm / Warm Webapp node_modules Cache (push) Has been cancelled
E2E CI Cache Warm / Warm E2E npm Registry Cache (push) Has been cancelled
API / build (push) Has been cancelled
Web App CI / check-types (push) Has been cancelled
Web App CI / check-lint (push) Has been cancelled
Web App CI / check-i18n (push) Has been cancelled
Web App CI / check-external-links (push) Has been cancelled
Web App CI / test (platform) (push) Has been cancelled
Web App CI / test (mattermost-redux) (push) Has been cancelled
Web App CI / test (channels shard 1/4) (push) Has been cancelled
Web App CI / test (channels shard 2/4) (push) Has been cancelled
Web App CI / test (channels shard 3/4) (push) Has been cancelled
Web App CI / test (channels shard 4/4) (push) Has been cancelled
Web App CI / upload-coverage (push) Has been cancelled
Web App CI / build (push) Has been cancelled
YAML Lint / yamllint (push) Has been cancelled
Push mirrored docker images / cd/Push mirrored docker images (push) Has been cancelled
docs-cd / Build and deploy docs (push) Has been cancelled
Docs CI / build (push) Has been cancelled
E2E Cache Warm: Cypress deps / Warm Cypress deps cache (push) Has been cancelled
Scorecards supply-chain security / Scorecard analysis (push) Has been cancelled
Server CI Weekly / Postgres FIPS (push) Has been skipped
Server CI Weekly / Run mmctl tests (FIPS) (push) Has been skipped
Server CI Weekly / Postgres with binary parameters (push) Has been skipped
Server CI Weekly / Build Environment (push) Failing after 1s
Server CI Cache Warm / Warm Go Module and Build Cache (push) Failing after 2s
Server CI Nightly Race / Build Environment (push) Failing after 1s
500 lines
15 KiB
Go
500 lines
15 KiB
Go
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
// See LICENSE.txt for license information.
|
|
|
|
package utils
|
|
|
|
import (
|
|
"reflect"
|
|
"slices"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestDedup(t *testing.T) {
|
|
t.Run("strings", func(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
input []string
|
|
expected []string
|
|
}{
|
|
{name: "nil stays nil", input: nil, expected: nil},
|
|
{name: "empty stays empty", input: []string{}, expected: []string{}},
|
|
{name: "no duplicates is unchanged", input: []string{"a", "b", "c"}, expected: []string{"a", "b", "c"}},
|
|
{name: "adjacent duplicates", input: []string{"a", "a", "b"}, expected: []string{"a", "b"}},
|
|
{name: "non-adjacent duplicates keep first occurrence order", input: []string{"b", "a", "b", "c", "a"}, expected: []string{"b", "a", "c"}},
|
|
{name: "all duplicates", input: []string{"a", "a", "a"}, expected: []string{"a"}},
|
|
{name: "empty string is a value like any other", input: []string{"", "a", ""}, expected: []string{"", "a"}},
|
|
}
|
|
|
|
for _, tc := range tests {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
result := Dedup(tc.input)
|
|
if !reflect.DeepEqual(result, tc.expected) {
|
|
t.Errorf("Dedup(%v) = %v, want %v", tc.input, result, tc.expected)
|
|
}
|
|
if tc.input == nil && result != nil {
|
|
t.Errorf("Dedup(nil) should stay nil, got %v", result)
|
|
}
|
|
})
|
|
}
|
|
})
|
|
|
|
t.Run("integers", func(t *testing.T) {
|
|
result := Dedup([]int{3, 1, 3, 2, 1})
|
|
expected := []int{3, 1, 2}
|
|
if !reflect.DeepEqual(result, expected) {
|
|
t.Errorf("Dedup() = %v, want %v", result, expected)
|
|
}
|
|
})
|
|
|
|
t.Run("structs", func(t *testing.T) {
|
|
type key struct {
|
|
Group string
|
|
ID int
|
|
}
|
|
|
|
result := Dedup([]key{{"a", 1}, {"a", 1}, {"a", 2}, {"b", 1}})
|
|
expected := []key{{"a", 1}, {"a", 2}, {"b", 1}}
|
|
if !reflect.DeepEqual(result, expected) {
|
|
t.Errorf("Dedup() = %v, want %v", result, expected)
|
|
}
|
|
})
|
|
|
|
t.Run("does not modify the input", func(t *testing.T) {
|
|
input := []string{"a", "b", "a"}
|
|
Dedup(input)
|
|
|
|
if !reflect.DeepEqual(input, []string{"a", "b", "a"}) {
|
|
t.Errorf("Dedup mutated its input: %v", input)
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestFindExclusives(t *testing.T) {
|
|
t.Run("integers", func(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
arr1, arr2 []int
|
|
expectedExclusive1 []int
|
|
expectedExclusive2 []int
|
|
expectedCommon []int
|
|
}{
|
|
// Basic test with non-overlapping elements
|
|
{
|
|
name: "No overlap",
|
|
arr1: []int{1, 2, 3},
|
|
arr2: []int{4, 5, 6},
|
|
expectedExclusive1: []int{1, 2, 3},
|
|
expectedExclusive2: []int{4, 5, 6},
|
|
expectedCommon: nil,
|
|
},
|
|
// Fully overlapping arrays
|
|
{
|
|
name: "Full overlap",
|
|
arr1: []int{1, 2, 3},
|
|
arr2: []int{1, 2, 3},
|
|
expectedExclusive1: nil,
|
|
expectedExclusive2: nil,
|
|
expectedCommon: []int{1, 2, 3},
|
|
},
|
|
// Partial overlap
|
|
{
|
|
name: "Partial overlap",
|
|
arr1: []int{1, 2, 3, 4},
|
|
arr2: []int{3, 4, 5, 6},
|
|
expectedExclusive1: []int{1, 2},
|
|
expectedExclusive2: []int{5, 6},
|
|
expectedCommon: []int{3, 4},
|
|
},
|
|
// Duplicates within arrays
|
|
{
|
|
name: "Duplicates in arr1",
|
|
arr1: []int{1, 2, 2, 3},
|
|
arr2: []int{2, 4, 4},
|
|
expectedExclusive1: []int{1, 3},
|
|
expectedExclusive2: []int{4},
|
|
expectedCommon: []int{2},
|
|
},
|
|
{
|
|
name: "Duplicates in arr2",
|
|
arr1: []int{1, 2, 3},
|
|
arr2: []int{2, 2, 3, 3},
|
|
expectedExclusive1: []int{1},
|
|
expectedExclusive2: nil,
|
|
expectedCommon: []int{2, 3},
|
|
},
|
|
// Edge cases
|
|
{
|
|
name: "Both arrays nil",
|
|
arr1: nil,
|
|
arr2: nil,
|
|
expectedExclusive1: nil,
|
|
expectedExclusive2: nil,
|
|
expectedCommon: nil,
|
|
},
|
|
{
|
|
name: "Both arrays empty",
|
|
arr1: []int{},
|
|
arr2: []int{},
|
|
expectedExclusive1: nil,
|
|
expectedExclusive2: nil,
|
|
expectedCommon: nil,
|
|
},
|
|
{
|
|
name: "One empty array",
|
|
arr1: []int{1, 2, 3},
|
|
arr2: nil,
|
|
expectedExclusive1: []int{1, 2, 3},
|
|
expectedExclusive2: nil,
|
|
expectedCommon: nil,
|
|
},
|
|
{
|
|
name: "One element in each array",
|
|
arr1: []int{1},
|
|
arr2: []int{2},
|
|
expectedExclusive1: []int{1},
|
|
expectedExclusive2: []int{2},
|
|
expectedCommon: nil,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
exclusive1, exclusive2, common := FindExclusives(tt.arr1, tt.arr2)
|
|
|
|
slices.Sort(exclusive1)
|
|
slices.Sort(exclusive2)
|
|
slices.Sort(common)
|
|
slices.Sort(tt.expectedExclusive1)
|
|
slices.Sort(tt.expectedExclusive2)
|
|
slices.Sort(tt.expectedCommon)
|
|
|
|
if !reflect.DeepEqual(exclusive1, tt.expectedExclusive1) {
|
|
t.Errorf("Exclusive to arr1: expected %v, got %v", tt.expectedExclusive1, exclusive1)
|
|
}
|
|
if !reflect.DeepEqual(exclusive2, tt.expectedExclusive2) {
|
|
t.Errorf("Exclusive to arr2: expected %v, got %v", tt.expectedExclusive2, exclusive2)
|
|
}
|
|
if !reflect.DeepEqual(common, tt.expectedCommon) {
|
|
t.Errorf("Common elements: expected %v, got %v", tt.expectedCommon, common)
|
|
}
|
|
})
|
|
}
|
|
})
|
|
|
|
t.Run("strings", func(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
arr1, arr2 []string
|
|
expectedExclusive1 []string
|
|
expectedExclusive2 []string
|
|
expectedCommon []string
|
|
}{
|
|
// Basic test with non-overlapping elements
|
|
{
|
|
name: "No overlap",
|
|
arr1: []string{"a", "b", "c"},
|
|
arr2: []string{"d", "e", "f"},
|
|
expectedExclusive1: []string{"a", "b", "c"},
|
|
expectedExclusive2: []string{"d", "e", "f"},
|
|
expectedCommon: nil,
|
|
},
|
|
// Fully overlapping arrays
|
|
{
|
|
name: "Full overlap",
|
|
arr1: []string{"a", "b", "c"},
|
|
arr2: []string{"a", "b", "c"},
|
|
expectedExclusive1: nil,
|
|
expectedExclusive2: nil,
|
|
expectedCommon: []string{"a", "b", "c"},
|
|
},
|
|
// Partial overlap
|
|
{
|
|
name: "Partial overlap",
|
|
arr1: []string{"a", "b", "c", "d"},
|
|
arr2: []string{"c", "d", "e", "f"},
|
|
expectedExclusive1: []string{"a", "b"},
|
|
expectedExclusive2: []string{"e", "f"},
|
|
expectedCommon: []string{"c", "d"},
|
|
},
|
|
// Duplicates within arrays
|
|
{
|
|
name: "Duplicates in arr1",
|
|
arr1: []string{"a", "b", "b", "c"},
|
|
arr2: []string{"b", "d", "d"},
|
|
expectedExclusive1: []string{"a", "c"},
|
|
expectedExclusive2: []string{"d"},
|
|
expectedCommon: []string{"b"},
|
|
},
|
|
{
|
|
name: "Duplicates in arr2",
|
|
arr1: []string{"a", "b", "c"},
|
|
arr2: []string{"b", "b", "c", "c"},
|
|
expectedExclusive1: []string{"a"},
|
|
expectedExclusive2: nil,
|
|
expectedCommon: []string{"b", "c"},
|
|
},
|
|
// Edge cases
|
|
{
|
|
name: "Both arrays nil",
|
|
arr1: nil,
|
|
arr2: nil,
|
|
expectedExclusive1: nil,
|
|
expectedExclusive2: nil,
|
|
expectedCommon: nil,
|
|
},
|
|
{
|
|
name: "Both arrays empty",
|
|
arr1: []string{},
|
|
arr2: []string{},
|
|
expectedExclusive1: nil,
|
|
expectedExclusive2: nil,
|
|
expectedCommon: nil,
|
|
},
|
|
{
|
|
name: "One empty array",
|
|
arr1: []string{"a", "b", "c"},
|
|
arr2: nil,
|
|
expectedExclusive1: []string{"a", "b", "c"},
|
|
expectedExclusive2: nil,
|
|
expectedCommon: nil,
|
|
},
|
|
{
|
|
name: "One element in each array",
|
|
arr1: []string{"a"},
|
|
arr2: []string{"b"},
|
|
expectedExclusive1: []string{"a"},
|
|
expectedExclusive2: []string{"b"},
|
|
expectedCommon: nil,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
exclusive1, exclusive2, common := FindExclusives(tt.arr1, tt.arr2)
|
|
|
|
slices.Sort(exclusive1)
|
|
slices.Sort(exclusive2)
|
|
slices.Sort(common)
|
|
slices.Sort(tt.expectedExclusive1)
|
|
slices.Sort(tt.expectedExclusive2)
|
|
slices.Sort(tt.expectedCommon)
|
|
|
|
if !reflect.DeepEqual(exclusive1, tt.expectedExclusive1) {
|
|
t.Errorf("Exclusive to arr1: expected %v, got %v", tt.expectedExclusive1, exclusive1)
|
|
}
|
|
if !reflect.DeepEqual(exclusive2, tt.expectedExclusive2) {
|
|
t.Errorf("Exclusive to arr2: expected %v, got %v", tt.expectedExclusive2, exclusive2)
|
|
}
|
|
if !reflect.DeepEqual(common, tt.expectedCommon) {
|
|
t.Errorf("Common elements: expected %v, got %v", tt.expectedCommon, common)
|
|
}
|
|
})
|
|
}
|
|
})
|
|
|
|
t.Run("dates", func(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
arr1, arr2 []time.Time
|
|
expectedExclusive1 []time.Time
|
|
expectedExclusive2 []time.Time
|
|
expectedCommon []time.Time
|
|
}{
|
|
// Basic test with non-overlapping elements
|
|
{
|
|
name: "No overlap",
|
|
arr1: []time.Time{
|
|
time.Date(2023, 1, 1, 0, 0, 0, 0, time.UTC),
|
|
time.Date(2023, 1, 2, 0, 0, 0, 0, time.UTC),
|
|
time.Date(2023, 1, 3, 0, 0, 0, 0, time.UTC),
|
|
},
|
|
arr2: []time.Time{
|
|
time.Date(2023, 1, 4, 0, 0, 0, 0, time.UTC),
|
|
time.Date(2023, 1, 5, 0, 0, 0, 0, time.UTC),
|
|
time.Date(2023, 1, 6, 0, 0, 0, 0, time.UTC),
|
|
},
|
|
expectedExclusive1: []time.Time{
|
|
time.Date(2023, 1, 1, 0, 0, 0, 0, time.UTC),
|
|
time.Date(2023, 1, 2, 0, 0, 0, 0, time.UTC),
|
|
time.Date(2023, 1, 3, 0, 0, 0, 0, time.UTC),
|
|
},
|
|
expectedExclusive2: []time.Time{
|
|
time.Date(2023, 1, 4, 0, 0, 0, 0, time.UTC),
|
|
time.Date(2023, 1, 5, 0, 0, 0, 0, time.UTC),
|
|
time.Date(2023, 1, 6, 0, 0, 0, 0, time.UTC),
|
|
},
|
|
expectedCommon: nil,
|
|
},
|
|
// Fully overlapping arrays
|
|
{
|
|
name: "Full overlap",
|
|
arr1: []time.Time{
|
|
time.Date(2023, 1, 1, 0, 0, 0, 0, time.UTC),
|
|
time.Date(2023, 1, 2, 0, 0, 0, 0, time.UTC),
|
|
time.Date(2023, 1, 3, 0, 0, 0, 0, time.UTC),
|
|
},
|
|
arr2: []time.Time{
|
|
time.Date(2023, 1, 1, 0, 0, 0, 0, time.UTC),
|
|
time.Date(2023, 1, 2, 0, 0, 0, 0, time.UTC),
|
|
time.Date(2023, 1, 3, 0, 0, 0, 0, time.UTC),
|
|
},
|
|
expectedExclusive1: nil,
|
|
expectedExclusive2: nil,
|
|
expectedCommon: []time.Time{
|
|
time.Date(2023, 1, 1, 0, 0, 0, 0, time.UTC),
|
|
time.Date(2023, 1, 2, 0, 0, 0, 0, time.UTC),
|
|
time.Date(2023, 1, 3, 0, 0, 0, 0, time.UTC),
|
|
},
|
|
},
|
|
// Partial overlap
|
|
{
|
|
name: "Partial overlap",
|
|
arr1: []time.Time{
|
|
time.Date(2023, 1, 1, 0, 0, 0, 0, time.UTC),
|
|
time.Date(2023, 1, 2, 0, 0, 0, 0, time.UTC),
|
|
time.Date(2023, 1, 3, 0, 0, 0, 0, time.UTC),
|
|
time.Date(2023, 1, 4, 0, 0, 0, 0, time.UTC),
|
|
},
|
|
arr2: []time.Time{
|
|
time.Date(2023, 1, 3, 0, 0, 0, 0, time.UTC),
|
|
time.Date(2023, 1, 4, 0, 0, 0, 0, time.UTC),
|
|
time.Date(2023, 1, 5, 0, 0, 0, 0, time.UTC),
|
|
time.Date(2023, 1, 6, 0, 0, 0, 0, time.UTC),
|
|
},
|
|
expectedExclusive1: []time.Time{
|
|
time.Date(2023, 1, 1, 0, 0, 0, 0, time.UTC),
|
|
time.Date(2023, 1, 2, 0, 0, 0, 0, time.UTC),
|
|
},
|
|
expectedExclusive2: []time.Time{
|
|
time.Date(2023, 1, 5, 0, 0, 0, 0, time.UTC),
|
|
time.Date(2023, 1, 6, 0, 0, 0, 0, time.UTC),
|
|
},
|
|
expectedCommon: []time.Time{
|
|
time.Date(2023, 1, 3, 0, 0, 0, 0, time.UTC),
|
|
time.Date(2023, 1, 4, 0, 0, 0, 0, time.UTC),
|
|
},
|
|
},
|
|
// Duplicates within arrays
|
|
{
|
|
name: "Duplicates in arr1",
|
|
arr1: []time.Time{
|
|
time.Date(2023, 1, 1, 0, 0, 0, 0, time.UTC),
|
|
time.Date(2023, 1, 2, 0, 0, 0, 0, time.UTC),
|
|
time.Date(2023, 1, 2, 0, 0, 0, 0, time.UTC),
|
|
time.Date(2023, 1, 3, 0, 0, 0, 0, time.UTC),
|
|
},
|
|
arr2: []time.Time{
|
|
time.Date(2023, 1, 2, 0, 0, 0, 0, time.UTC),
|
|
time.Date(2023, 1, 4, 0, 0, 0, 0, time.UTC),
|
|
time.Date(2023, 1, 4, 0, 0, 0, 0, time.UTC),
|
|
},
|
|
expectedExclusive1: []time.Time{
|
|
time.Date(2023, 1, 1, 0, 0, 0, 0, time.UTC),
|
|
time.Date(2023, 1, 3, 0, 0, 0, 0, time.UTC),
|
|
},
|
|
expectedExclusive2: []time.Time{
|
|
time.Date(2023, 1, 4, 0, 0, 0, 0, time.UTC),
|
|
},
|
|
expectedCommon: []time.Time{
|
|
time.Date(2023, 1, 2, 0, 0, 0, 0, time.UTC),
|
|
},
|
|
},
|
|
{
|
|
name: "Duplicates in arr2",
|
|
arr1: []time.Time{
|
|
time.Date(2023, 1, 1, 0, 0, 0, 0, time.UTC),
|
|
time.Date(2023, 1, 2, 0, 0, 0, 0, time.UTC),
|
|
time.Date(2023, 1, 3, 0, 0, 0, 0, time.UTC),
|
|
},
|
|
arr2: []time.Time{
|
|
time.Date(2023, 1, 2, 0, 0, 0, 0, time.UTC),
|
|
time.Date(2023, 1, 2, 0, 0, 0, 0, time.UTC),
|
|
time.Date(2023, 1, 3, 0, 0, 0, 0, time.UTC),
|
|
time.Date(2023, 1, 3, 0, 0, 0, 0, time.UTC),
|
|
},
|
|
expectedExclusive1: []time.Time{
|
|
time.Date(2023, 1, 1, 0, 0, 0, 0, time.UTC),
|
|
},
|
|
expectedExclusive2: nil,
|
|
expectedCommon: []time.Time{
|
|
time.Date(2023, 1, 2, 0, 0, 0, 0, time.UTC),
|
|
time.Date(2023, 1, 3, 0, 0, 0, 0, time.UTC),
|
|
},
|
|
},
|
|
// Edge cases
|
|
{
|
|
name: "Both arrays nil",
|
|
arr1: nil,
|
|
arr2: nil,
|
|
expectedExclusive1: nil,
|
|
expectedExclusive2: nil,
|
|
expectedCommon: nil,
|
|
},
|
|
{
|
|
name: "Both arrays empty",
|
|
arr1: []time.Time{},
|
|
arr2: []time.Time{},
|
|
expectedExclusive1: nil,
|
|
expectedExclusive2: nil,
|
|
expectedCommon: nil,
|
|
},
|
|
{
|
|
name: "One empty array",
|
|
arr1: []time.Time{
|
|
time.Date(2023, 1, 1, 0, 0, 0, 0, time.UTC),
|
|
time.Date(2023, 1, 2, 0, 0, 0, 0, time.UTC),
|
|
time.Date(2023, 1, 3, 0, 0, 0, 0, time.UTC),
|
|
},
|
|
arr2: nil,
|
|
expectedExclusive1: []time.Time{
|
|
time.Date(2023, 1, 1, 0, 0, 0, 0, time.UTC),
|
|
time.Date(2023, 1, 2, 0, 0, 0, 0, time.UTC),
|
|
time.Date(2023, 1, 3, 0, 0, 0, 0, time.UTC),
|
|
},
|
|
expectedExclusive2: nil,
|
|
expectedCommon: nil,
|
|
},
|
|
{
|
|
name: "One element in each array",
|
|
arr1: []time.Time{
|
|
time.Date(2023, 1, 1, 0, 0, 0, 0, time.UTC),
|
|
},
|
|
arr2: []time.Time{
|
|
time.Date(2023, 1, 2, 0, 0, 0, 0, time.UTC),
|
|
},
|
|
expectedExclusive1: []time.Time{
|
|
time.Date(2023, 1, 1, 0, 0, 0, 0, time.UTC),
|
|
},
|
|
expectedExclusive2: []time.Time{
|
|
time.Date(2023, 1, 2, 0, 0, 0, 0, time.UTC),
|
|
},
|
|
expectedCommon: nil,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
exclusive1, exclusive2, common := FindExclusives(tt.arr1, tt.arr2)
|
|
|
|
slices.SortFunc(exclusive1, func(a, b time.Time) int { return a.Compare(b) })
|
|
slices.SortFunc(exclusive2, func(a, b time.Time) int { return a.Compare(b) })
|
|
slices.SortFunc(common, func(a, b time.Time) int { return a.Compare(b) })
|
|
slices.SortFunc(tt.expectedExclusive1, func(a, b time.Time) int { return a.Compare(b) })
|
|
slices.SortFunc(tt.expectedExclusive2, func(a, b time.Time) int { return a.Compare(b) })
|
|
slices.SortFunc(tt.expectedCommon, func(a, b time.Time) int { return a.Compare(b) })
|
|
|
|
if !reflect.DeepEqual(exclusive1, tt.expectedExclusive1) {
|
|
t.Errorf("Exclusive to arr1: expected %v, got %v", tt.expectedExclusive1, exclusive1)
|
|
}
|
|
if !reflect.DeepEqual(exclusive2, tt.expectedExclusive2) {
|
|
t.Errorf("Exclusive to arr2: expected %v, got %v", tt.expectedExclusive2, exclusive2)
|
|
}
|
|
if !reflect.DeepEqual(common, tt.expectedCommon) {
|
|
t.Errorf("Common elements: expected %v, got %v", tt.expectedCommon, common)
|
|
}
|
|
})
|
|
}
|
|
})
|
|
}
|