refactor: repositories (#28)

* cleanup unnecessary mocks

* refactor document storage location

* remove unused function

* move ownership to document types to repo package

* move types and mappers to repo package

* refactor sets to own package
This commit is contained in:
Hayden 2022-09-27 15:52:13 -08:00 committed by GitHub
parent 2e82398e5c
commit 343290a55a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
79 changed files with 3169 additions and 3160 deletions

101
backend/pkgs/set/funcs.go Normal file
View file

@ -0,0 +1,101 @@
package set
// Diff returns the difference between two sets
func Diff[T key](a, b Set[T]) Set[T] {
s := New[T]()
for k := range a.mp {
if !b.Contains(k) {
s.Insert(k)
}
}
return s
}
// Intersect returns the intersection between two sets
func Intersect[T key](a, b Set[T]) Set[T] {
s := New[T]()
for k := range a.mp {
if b.Contains(k) {
s.Insert(k)
}
}
return s
}
// Union returns the union between two sets
func Union[T key](a, b Set[T]) Set[T] {
s := New[T]()
for k := range a.mp {
s.Insert(k)
}
for k := range b.mp {
s.Insert(k)
}
return s
}
// Xor returns the symmetric difference between two sets
func Xor[T key](a, b Set[T]) Set[T] {
s := New[T]()
for k := range a.mp {
if !b.Contains(k) {
s.Insert(k)
}
}
for k := range b.mp {
if !a.Contains(k) {
s.Insert(k)
}
}
return s
}
// Equal returns true if two sets are equal
func Equal[T key](a, b Set[T]) bool {
if a.Len() != b.Len() {
return false
}
for k := range a.mp {
if !b.Contains(k) {
return false
}
}
return true
}
// Subset returns true if a is a subset of b
func Subset[T key](a, b Set[T]) bool {
if a.Len() > b.Len() {
return false
}
for k := range a.mp {
if !b.Contains(k) {
return false
}
}
return true
}
// Superset returns true if a is a superset of b
func Superset[T key](a, b Set[T]) bool {
if a.Len() < b.Len() {
return false
}
for k := range b.mp {
if !a.Contains(k) {
return false
}
}
return true
}
// Disjoint returns true if two sets are disjoint
func Disjoint[T key](a, b Set[T]) bool {
for k := range a.mp {
if b.Contains(k) {
return false
}
}
return true
}

View file

@ -0,0 +1,287 @@
package set
import (
"reflect"
"testing"
)
type args struct {
a Set[string]
b Set[string]
}
var (
argsBasic = args{
a: New("a", "b", "c"),
b: New("b", "c", "d"),
}
argsNoOverlap = args{
a: New("a", "b", "c"),
b: New("d", "e", "f"),
}
argsIdentical = args{
a: New("a", "b", "c"),
b: New("a", "b", "c"),
}
)
func TestDiff(t *testing.T) {
tests := []struct {
name string
args args
want Set[string]
}{
{
name: "diff basic",
args: argsBasic,
want: New("a"),
},
{
name: "diff empty",
args: argsIdentical,
want: New[string](),
},
{
name: "diff no overlap",
args: argsNoOverlap,
want: New("a", "b", "c"),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := Diff(tt.args.a, tt.args.b); !reflect.DeepEqual(got, tt.want) {
t.Errorf("Diff() = %v, want %v", got, tt.want)
}
})
}
}
func TestIntersect(t *testing.T) {
tests := []struct {
name string
args args
want Set[string]
}{
{
name: "intersect basic",
args: argsBasic,
want: New("b", "c"),
},
{
name: "identical sets",
args: argsIdentical,
want: New("a", "b", "c"),
},
{
name: "no overlap",
args: argsNoOverlap,
want: New[string](),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := Intersect(tt.args.a, tt.args.b); !reflect.DeepEqual(got, tt.want) {
t.Errorf("Intersect() = %v, want %v", got, tt.want)
}
})
}
}
func TestUnion(t *testing.T) {
tests := []struct {
name string
args args
want Set[string]
}{
{
name: "intersect basic",
args: argsBasic,
want: New("a", "b", "c", "d"),
},
{
name: "identical sets",
args: argsIdentical,
want: New("a", "b", "c"),
},
{
name: "no overlap",
args: argsNoOverlap,
want: New("a", "b", "c", "d", "e", "f"),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := Union(tt.args.a, tt.args.b); !reflect.DeepEqual(got, tt.want) {
t.Errorf("Union() = %v, want %v", got, tt.want)
}
})
}
}
func TestXor(t *testing.T) {
tests := []struct {
name string
args args
want Set[string]
}{
{
name: "xor basic",
args: argsBasic,
want: New("a", "d"),
},
{
name: "identical sets",
args: argsIdentical,
want: New[string](),
},
{
name: "no overlap",
args: argsNoOverlap,
want: New("a", "b", "c", "d", "e", "f"),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := Xor(tt.args.a, tt.args.b); !reflect.DeepEqual(got, tt.want) {
t.Errorf("Xor() = %v, want %v", got, tt.want)
}
})
}
}
func TestEqual(t *testing.T) {
tests := []struct {
name string
args args
want bool
}{
{
name: "equal basic",
args: argsBasic,
want: false,
},
{
name: "identical sets",
args: argsIdentical,
want: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := Equal(tt.args.a, tt.args.b); got != tt.want {
t.Errorf("Equal() = %v, want %v", got, tt.want)
}
})
}
}
func TestSubset(t *testing.T) {
type args struct {
a Set[string]
b Set[string]
}
tests := []struct {
name string
args args
want bool
}{
{
name: "subset basic",
args: args{
a: New("a", "b"),
b: New("a", "b", "c"),
},
want: true,
},
{
name: "subset basic false",
args: args{
a: New("a", "b", "d"),
b: New("a", "b", "c"),
},
want: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := Subset(tt.args.a, tt.args.b); got != tt.want {
t.Errorf("Subset() = %v, want %v", got, tt.want)
}
})
}
}
func TestSuperset(t *testing.T) {
type args struct {
a Set[string]
b Set[string]
}
tests := []struct {
name string
args args
want bool
}{
{
name: "superset basic",
args: args{
a: New("a", "b", "c"),
b: New("a", "b"),
},
want: true,
},
{
name: "superset basic false",
args: args{
a: New("a", "b", "c"),
b: New("a", "b", "d"),
},
want: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := Superset(tt.args.a, tt.args.b); got != tt.want {
t.Errorf("Superset() = %v, want %v", got, tt.want)
}
})
}
}
func TestDisjoint(t *testing.T) {
type args struct {
a Set[string]
b Set[string]
}
tests := []struct {
name string
args args
want bool
}{
{
name: "disjoint basic",
args: args{
a: New("a", "b"),
b: New("c", "d"),
},
want: true,
},
{
name: "disjoint basic false",
args: args{
a: New("a", "b"),
b: New("b", "c"),
},
want: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := Disjoint(tt.args.a, tt.args.b); got != tt.want {
t.Errorf("Disjoint() = %v, want %v", got, tt.want)
}
})
}
}

56
backend/pkgs/set/set.go Normal file
View file

@ -0,0 +1,56 @@
package set
type key interface {
comparable
}
type Set[T key] struct {
mp map[T]struct{}
}
func New[T key](v ...T) Set[T] {
mp := make(map[T]struct{}, len(v))
s := Set[T]{mp}
s.Insert(v...)
return s
}
func (s Set[T]) Insert(v ...T) {
for _, e := range v {
s.mp[e] = struct{}{}
}
}
func (s Set[T]) Remove(v ...T) {
for _, e := range v {
delete(s.mp, e)
}
}
func (s Set[T]) Contains(v T) bool {
_, ok := s.mp[v]
return ok
}
func (s Set[T]) ContainsAll(v ...T) bool {
for _, e := range v {
if !s.Contains(e) {
return false
}
}
return true
}
func (s Set[T]) Slice() []T {
slice := make([]T, 0, len(s.mp))
for k := range s.mp {
slice = append(slice, k)
}
return slice
}
func (s Set[T]) Len() int {
return len(s.mp)
}

View file

@ -0,0 +1,255 @@
package set
import (
"reflect"
"testing"
)
func TestNew(t *testing.T) {
type args struct {
v []string
}
tests := []struct {
name string
args args
want Set[string]
}{
{
name: "new",
args: args{
v: []string{"a", "b", "c"},
},
want: Set[string]{
mp: map[string]struct{}{
"a": {},
"b": {},
"c": {},
},
},
},
{
name: "new empty",
args: args{
v: []string{},
},
want: Set[string]{
mp: map[string]struct{}{},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := New(tt.args.v...); !reflect.DeepEqual(got, tt.want) {
t.Errorf("New() = %v, want %v", got, tt.want)
}
})
}
}
func TestSet_Insert(t *testing.T) {
type args struct {
v []string
}
tests := []struct {
name string
s Set[string]
args args
want Set[string]
}{
{
name: "insert",
s: Set[string]{
mp: map[string]struct{}{
"a": {},
"b": {},
"c": {},
},
},
args: args{
v: []string{"d", "e", "f"},
},
want: Set[string]{
mp: map[string]struct{}{
"a": {},
"b": {},
"c": {},
"d": {},
"e": {},
"f": {},
},
},
},
{
name: "insert empty",
s: Set[string]{
mp: map[string]struct{}{},
},
args: args{
v: []string{"a", "b", "c"},
},
want: Set[string]{
mp: map[string]struct{}{
"a": {},
"b": {},
"c": {},
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
tt.s.Insert(tt.args.v...)
if !reflect.DeepEqual(tt.s, tt.want) {
t.Errorf("Set.Insert() = %v, want %v", tt.s, tt.want)
}
})
}
}
func TestSet_Delete(t *testing.T) {
type args struct {
v []string
}
tests := []struct {
name string
s Set[string]
args args
want Set[string]
}{
{
name: "insert",
s: Set[string]{
mp: map[string]struct{}{
"a": {},
"b": {},
"c": {},
"d": {},
"e": {},
"f": {},
},
},
args: args{
v: []string{"d", "e", "f"},
},
want: Set[string]{
mp: map[string]struct{}{
"a": {},
"b": {},
"c": {},
},
},
},
{
name: "delete empty",
s: Set[string]{
mp: map[string]struct{}{},
},
args: args{
v: []string{},
},
want: Set[string]{
mp: map[string]struct{}{},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
tt.s.Remove(tt.args.v...)
if !reflect.DeepEqual(tt.s, tt.want) {
t.Errorf("Set.Delete() = %v, want %v", tt.s, tt.want)
}
})
}
}
func TestSet_ContainsAll(t *testing.T) {
type args struct {
v []string
}
tests := []struct {
name string
s Set[string]
args args
want bool
}{
{
name: "contains",
s: Set[string]{
mp: map[string]struct{}{
"a": {},
"b": {},
"c": {},
},
},
args: args{
v: []string{"a", "b", "c"},
},
want: true,
},
{
name: "contains empty",
s: Set[string]{
mp: map[string]struct{}{},
},
args: args{
v: []string{},
},
want: true,
},
{
name: "not contains",
s: Set[string]{
mp: map[string]struct{}{
"a": {},
"b": {},
"c": {},
},
},
args: args{
v: []string{"d", "e", "f"},
},
want: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := tt.s.ContainsAll(tt.args.v...); got != tt.want {
t.Errorf("Set.ContainsAll() = %v, want %v", got, tt.want)
}
})
}
}
func TestSet_Slice(t *testing.T) {
tests := []struct {
name string
s Set[string]
want []string
}{
{
name: "slice",
s: Set[string]{
mp: map[string]struct{}{
"a": {},
"b": {},
"c": {},
},
},
want: []string{"a", "b", "c"},
},
{
name: "slice empty",
s: Set[string]{
mp: map[string]struct{}{},
},
want: []string{},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := tt.s.Slice(); !reflect.DeepEqual(got, tt.want) {
t.Errorf("Set.Slice() = %v, want %v", got, tt.want)
}
})
}
}