update exceptions

This commit is contained in:
tursom 2022-03-28 18:19:05 +08:00
parent 3057483900
commit 150fa1f04e
22 changed files with 652 additions and 45 deletions

View File

@ -1,6 +1,84 @@
package collections package collections
import "github.com/tursom/GoCollections/lang" import (
"github.com/tursom/GoCollections/exceptions"
"github.com/tursom/GoCollections/lang"
)
type GoMap[K lang.Object, V any] struct { type (
GoMap[K lang.Object, V any] struct {
NodeMap[K, V]
m map[int32]*SimpleMapNode[K, V]
}
//goMapNode[K lang.Object, V any] struct {
// key K
// value V
// next *goMapNode[K, V]
//}
)
func NewGoMap[K lang.Object, V any]() *GoMap[K, V] {
m := &GoMap[K, V]{m: make(map[int32]*SimpleMapNode[K, V])}
m.NodeMap.MapNodeFinder = NewMapNodeFinderBySlot[K, V](m)
return m
}
func (g *GoMap[K, V]) ToString() lang.String {
return MapToString[K, V](g)
}
func (g *GoMap[K, V]) String() string {
return g.ToString().GoString()
}
func (g *GoMap[K, V]) findSlot(k K) MapNode[K, V] {
hashCode := lang.HashCode(k)
root := g.m[hashCode]
if root == nil {
root = &SimpleMapNode[K, V]{}
g.m[hashCode] = root
}
return root
}
//func (g *GoMap[K, V]) Put(k K, v V) (bool, exceptions.Exception) {
// node, _ := g.findNode(k, true)
// node.value = v
// return true, nil
//}
//
//func (g *GoMap[K, V]) Get(k K) (V, bool, exceptions.Exception) {
// node, _ := g.findNode(k, false)
// if node == nil {
// return g.nil()
// } else {
// return node.value, true, nil
// }
//}
//
//func (g *GoMap[K, V]) Remove(k K) (V, bool, exceptions.Exception) {
// node, prev := g.findNode(k, false)
// if node == nil {
// return g.nil()
// } else {
// prev.next = node.next
// return node.value, true, nil
// }
//}
func (g *GoMap[K, V]) Loop(f func(K, V) exceptions.Exception) (err exceptions.Exception) {
for _, node := range g.m {
for node.next != nil {
node = node.next
err = f(node.key, node.value)
if err != nil {
return
}
}
}
return
}
func (g *GoMap[K, V]) nil() (V, bool, exceptions.Exception) {
return lang.Nil[V](), false, nil
} }

16
collections/GoMap_test.go Normal file
View File

@ -0,0 +1,16 @@
package collections
import (
"fmt"
"github.com/tursom/GoCollections/lang"
"testing"
)
func TestGoMap_get(t *testing.T) {
m := NewGoMap[lang.Int, int]()
for i := 0; i < 10; i++ {
m.Put(lang.Int(i), i+1)
fmt.Println(m.ToString().String())
fmt.Println(m)
}
}

65
collections/GoSyncMap.go Normal file
View File

@ -0,0 +1,65 @@
package collections
import (
"github.com/tursom/GoCollections/concurrent"
"github.com/tursom/GoCollections/exceptions"
"github.com/tursom/GoCollections/lang"
"sync"
)
type (
GoSyncMap[K lang.Object, V any] struct {
NodeMap[K, V]
m sync.Map
lock concurrent.RWLock
}
)
func NewGoSyncMap[K lang.Object, V any]() *GoSyncMap[K, V] {
m := &GoSyncMap[K, V]{lock: &sync.RWMutex{}}
m.MapNodeFinder = NewMapNodeFinderBySlot[K, V](m)
return m
}
func (g *GoSyncMap[K, V]) ToString() lang.String {
return MapToString[K, V](g)
}
func (g *GoSyncMap[K, V]) findSlot(k K) MapNode[K, V] {
hashCode := lang.HashCode(k)
p, _ := g.m.Load(hashCode)
root := lang.Cast[*SimpleMapNode[K, V]](p)
if root == nil {
root = &SimpleMapNode[K, V]{}
g.m.Store(hashCode, root)
}
return root
}
func (g *GoSyncMap[K, V]) Put(k K, v V) (bool, exceptions.Exception) {
g.lock.Lock()
defer g.lock.Unlock()
return g.NodeMap.Put(k, v)
}
func (g *GoSyncMap[K, V]) Get(k K) (V, bool, exceptions.Exception) {
g.lock.RLock()
defer g.lock.RUnlock()
return g.NodeMap.Get(k)
}
func (g *GoSyncMap[K, V]) Remove(k K) (V, bool, exceptions.Exception) {
g.lock.Lock()
defer g.lock.Unlock()
return g.NodeMap.Remove(k)
}
func (g *GoSyncMap[K, V]) Loop(f func(K, V) exceptions.Exception) (err exceptions.Exception) {
g.lock.RLock()
defer g.lock.RUnlock()
g.m.Range(func(key, value any) bool {
err = f(lang.Cast[K](key), lang.Cast[V](value))
return err == nil
})
return
}

147
collections/HashMap.go Normal file
View File

@ -0,0 +1,147 @@
package collections
import (
"fmt"
"github.com/tursom/GoCollections/exceptions"
"github.com/tursom/GoCollections/lang"
)
type (
//HashMap
//TODO impl
HashMap[K lang.Object, V any] struct {
NodeMap[K, V]
slot []*hashMapNode[K, V]
loadFactor float32
}
hashMapNode[K lang.Object, V any] struct {
lang.BaseObject
m *HashMap[K, V]
key K
value V
next *hashMapNode[K, V]
hash int32
}
emptyHashMapSlot[K lang.Object, V any] struct {
lang.BaseObject
m *HashMap[K, V]
hashCode int32
index int
}
)
func NewHashMap[K lang.Object, V any]() *HashMap[K, V] {
return NewHashMapInitCap[K, V](16, 0.75)
}
func NewHashMapInitCap[K lang.Object, V any](initialCapacity int, loadFactor float32) *HashMap[K, V] {
m := &HashMap[K, V]{
slot: make([]*hashMapNode[K, V], initialCapacity),
loadFactor: loadFactor,
}
m.MapNodeFinder = NewMapNodeFinderBySlot[K, V](m)
return m
}
func (h *HashMap[K, V]) String() string {
return MapToString[K, V](h).String()
}
func (h *HashMap[K, V]) findSlot(k K) MapNode[K, V] {
hashCode := lang.HashCode(k)
hashCode ^= hashCode >> 16
index := int(hashCode) % len(h.slot)
root := h.slot[index]
if root == nil {
return &emptyHashMapSlot[K, V]{m: h, hashCode: hashCode, index: index}
}
return root
}
func (h *HashMap[K, V]) Loop(f func(K, V) exceptions.Exception) (err exceptions.Exception) {
for _, node := range h.slot {
for node != nil {
err = f(node.GetKey(), node.GetValue())
if err != nil {
return
}
node = node.next
}
}
return
}
func (e *emptyHashMapSlot[K, V]) GetKey() K {
//TODO implement me
panic("implement me")
}
func (e *emptyHashMapSlot[K, V]) GetValue() V {
//TODO implement me
panic("implement me")
}
func (e *emptyHashMapSlot[K, V]) SetValue(value V) {
//TODO implement me
panic("implement me")
}
func (e *emptyHashMapSlot[K, V]) CreateNext(key K) MapNode[K, V] {
node := &hashMapNode[K, V]{
key: key,
hash: lang.HashCode(key),
}
e.m.slot[e.index] = node
return node
}
func (e *emptyHashMapSlot[K, V]) GetNext() MapNode[K, V] {
node := e.m.slot[e.index]
if node == nil {
return nil
}
return node
}
func (e *emptyHashMapSlot[K, V]) RemoveNext() {
node := e.m.slot[e.index]
if node != nil {
e.m.slot[e.index] = node.next
}
}
func (s *hashMapNode[K, V]) String() string {
return "hashMapNode{key: " + s.key.String() + ", value: " + fmt.Sprint(s.value) + "}"
}
func (s *hashMapNode[K, V]) GetKey() K {
return s.key
}
func (s *hashMapNode[K, V]) GetValue() V {
return s.value
}
func (s *hashMapNode[K, V]) SetValue(value V) {
s.value = value
}
func (s *hashMapNode[K, V]) CreateNext(key K) MapNode[K, V] {
s.next = &hashMapNode[K, V]{key: key, next: s.next, hash: lang.HashCode(key)}
return s.next
}
func (s *hashMapNode[K, V]) GetNext() MapNode[K, V] {
if s.next == nil {
return nil
}
return s.next
}
func (s *hashMapNode[K, V]) RemoveNext() {
if s.next != nil {
s.next = s.next.next
}
}

View File

@ -0,0 +1,16 @@
package collections
import (
"fmt"
"github.com/tursom/GoCollections/lang"
"testing"
)
func TestHashMap_put(t *testing.T) {
m := NewHashMap[lang.Int, int]()
for i := 0; i < 100; i++ {
fmt.Println(m)
m.Put(lang.Int(i), i+1)
}
fmt.Println(m)
}

View File

@ -1,11 +1,166 @@
package collections package collections
import ( import (
"fmt"
"github.com/tursom/GoCollections/exceptions" "github.com/tursom/GoCollections/exceptions"
"github.com/tursom/GoCollections/lang" "github.com/tursom/GoCollections/lang"
"strings"
) )
type Map[K lang.Object, V any] interface { type (
Put(k K, v V) (bool, exceptions.Exception) MapLooper[K lang.Object, V any] interface {
Get(k K) (V, exceptions.Exception) Loop(func(K, V) exceptions.Exception) exceptions.Exception
}
Map[K lang.Object, V any] interface {
MapLooper[K, V]
Put(k K, v V) (bool, exceptions.Exception)
Get(k K) (V, bool, exceptions.Exception)
Remove(k K) (V, bool, exceptions.Exception)
}
MapNodeFinder[K lang.Object, V any] interface {
findNode(k K, createIfNotExist bool) (node, prev MapNode[K, V])
}
MapSlotFinder[K lang.Object, V any] interface {
findSlot(k K) (root MapNode[K, V])
}
MapNode[K lang.Object, V any] interface {
GetKey() K
GetValue() V
SetValue(value V)
CreateNext(key K) MapNode[K, V]
GetNext() MapNode[K, V]
RemoveNext()
}
SimpleMapNode[K lang.Object, V any] struct {
lang.BaseObject
key K
value V
next *SimpleMapNode[K, V]
}
NodeMap[K lang.Object, V any] struct {
lang.BaseObject
MapNodeFinder MapNodeFinder[K, V]
}
MapNodeFinderBySlot[K lang.Object, V any] struct {
lang.BaseObject
slotFinder MapSlotFinder[K, V]
}
)
func NewMapNodeFinderBySlot[K lang.Object, V any](slotFinder MapSlotFinder[K, V]) MapNodeFinder[K, V] {
return &MapNodeFinderBySlot[K, V]{slotFinder: slotFinder}
}
func MapToString[K lang.Object, V any](m MapLooper[K, V]) lang.String {
builder := strings.Builder{}
builder.WriteString("{")
_ = m.Loop(func(k K, v V) exceptions.Exception {
if builder.Len() != 1 {
builder.WriteString(", ")
}
builder.WriteString(k.String())
builder.WriteString(": ")
if ov, ok := lang.TryCast[lang.Object](v); ok {
builder.WriteString(ov.String())
} else {
builder.WriteString(fmt.Sprint(v))
}
return nil
})
builder.WriteString("}")
return lang.NewString(builder.String())
}
func (g *NodeMap[K, V]) findNode(k K, createIfNotExist bool) (node, prev MapNode[K, V]) {
return g.MapNodeFinder.findNode(k, createIfNotExist)
}
func (g *NodeMap[K, V]) Put(k K, v V) (bool, exceptions.Exception) {
node, _ := g.findNode(k, true)
node.SetValue(v)
return true, nil
}
func (g *NodeMap[K, V]) Get(k K) (V, bool, exceptions.Exception) {
node, _ := g.findNode(k, false)
if node == nil {
return g.nil()
} else {
return node.GetValue(), true, nil
}
}
func (g *NodeMap[K, V]) Remove(k K) (V, bool, exceptions.Exception) {
node, prev := g.findNode(k, false)
if node == nil {
return g.nil()
} else {
if prev != nil {
prev.RemoveNext()
}
return node.GetValue(), true, nil
}
}
func (g *NodeMap[K, V]) nil() (V, bool, exceptions.Exception) {
return lang.Nil[V](), false, nil
}
func (m *MapNodeFinderBySlot[K, V]) findNode(k K, createIfNotExist bool) (node, prev MapNode[K, V]) {
prev = m.slotFinder.findSlot(k)
if prev != nil {
node = prev.GetNext()
for node != nil {
if node.GetKey().Equals(k) {
return
}
prev = node
node = node.GetNext()
}
}
if createIfNotExist {
node = prev.CreateNext(k)
}
return
}
func (s *SimpleMapNode[K, V]) String() string {
return "SimpleMapNode{key: " + s.key.String() + ", value: " + fmt.Sprint(s.value) + "}"
}
func (s *SimpleMapNode[K, V]) GetKey() K {
return s.key
}
func (s *SimpleMapNode[K, V]) GetValue() V {
return s.value
}
func (s *SimpleMapNode[K, V]) SetValue(value V) {
s.value = value
}
func (s *SimpleMapNode[K, V]) CreateNext(key K) MapNode[K, V] {
s.next = &SimpleMapNode[K, V]{key: key, next: s.next}
return s.next
}
func (s *SimpleMapNode[K, V]) GetNext() MapNode[K, V] {
if s.next == nil {
return nil
}
return s.next
}
func (s *SimpleMapNode[K, V]) RemoveNext() {
if s.next != nil {
s.next = s.next.next
}
} }

View File

@ -5,12 +5,11 @@ type ElementNotFoundException struct {
} }
func NewElementNotFoundException(message any, config *ExceptionConfig) *ElementNotFoundException { func NewElementNotFoundException(message any, config *ExceptionConfig) *ElementNotFoundException {
config.AddSkipStack(1)
return &ElementNotFoundException{ return &ElementNotFoundException{
NewRuntimeException( NewRuntimeException(
message, message,
"exception caused ElementNotFoundException:", "exception caused ElementNotFoundException:",
config, config.AddSkipStack(1),
), ),
} }
} }

View File

@ -0,0 +1,15 @@
package exceptions
type IllegalParameterException struct {
RuntimeException
}
func NewIllegalParameterException(message any, config *ExceptionConfig) *IllegalParameterException {
return &IllegalParameterException{
NewRuntimeException(
message,
"exception caused ElementNotFoundException:",
config.AddSkipStack(1),
),
}
}

View File

@ -5,12 +5,11 @@ type IndexOutOfBound struct {
} }
func NewIndexOutOfBound(message any, config *ExceptionConfig) *IndexOutOfBound { func NewIndexOutOfBound(message any, config *ExceptionConfig) *IndexOutOfBound {
config.AddSkipStack(1)
return &IndexOutOfBound{ return &IndexOutOfBound{
NewRuntimeException( NewRuntimeException(
message, message,
"exception caused IndexOutOfBound:", "exception caused IndexOutOfBound:",
config, config.AddSkipStack(1),
), ),
} }
} }

View File

@ -1,16 +1,27 @@
package exceptions package exceptions
import (
"github.com/tursom/GoCollections/lang"
"reflect"
)
type NPE struct { type NPE struct {
RuntimeException RuntimeException
} }
func NewNPE(message any, config *ExceptionConfig) *NPE { func NewNPE(message any, config *ExceptionConfig) *NPE {
config.AddSkipStack(1)
return &NPE{ return &NPE{
NewRuntimeException( NewRuntimeException(
message, message,
"exception caused NullPointerException:", "exception caused NullPointerException:",
config, config.AddSkipStack(1),
), ),
} }
} }
func CheckNil[T any](p *T) {
t := reflect.TypeOf(lang.Nil[T]())
if p == nil {
panic(NewNPE(t.Name()+" is null", DefaultExceptionConfig().AddSkipStack(1)))
}
}

View File

@ -5,12 +5,11 @@ type OperationNotSupportedException struct {
} }
func NewOperationNotSupportedException(message any, config *ExceptionConfig) *OperationNotSupportedException { func NewOperationNotSupportedException(message any, config *ExceptionConfig) *OperationNotSupportedException {
config.AddSkipStack(1)
return &OperationNotSupportedException{ return &OperationNotSupportedException{
NewRuntimeException( NewRuntimeException(
message, message,
"exception caused OperationNotSupportedException:", "exception caused OperationNotSupportedException:",
config, config.AddSkipStack(1),
), ),
} }
} }

View File

@ -6,9 +6,8 @@ type PackageException struct {
} }
func NewPackageException(err any, exceptionMessage string, config *ExceptionConfig) *PackageException { func NewPackageException(err any, exceptionMessage string, config *ExceptionConfig) *PackageException {
config.AddSkipStack(1)
return &PackageException{ return &PackageException{
RuntimeException: NewRuntimeException(err, exceptionMessage, config), RuntimeException: NewRuntimeException(err, exceptionMessage, config.AddSkipStack(1)),
err: err, err: err,
} }
} }

View File

@ -55,11 +55,9 @@ func (o RuntimeException) Cause() Exception {
} }
func (o RuntimeException) Error() string { func (o RuntimeException) Error() string {
if len(o.message) == 0 { builder := strings.Builder{}
return "index out of bound" o.BuildPrintStackTrace(&builder)
} else { return builder.String()
return o.message
}
} }
func (o RuntimeException) StackTrace() []StackTrace { func (o RuntimeException) StackTrace() []StackTrace {
@ -71,9 +69,7 @@ func (o RuntimeException) PrintStackTrace() {
} }
func (o RuntimeException) PrintStackTraceTo(writer io.Writer) { func (o RuntimeException) PrintStackTraceTo(writer io.Writer) {
builder := strings.Builder{} bytes := []byte(o.Error())
o.BuildPrintStackTrace(&builder)
bytes := []byte(builder.String())
writeBytes := 0 writeBytes := 0
for writeBytes < len(bytes) { for writeBytes < len(bytes) {
write, err := writer.Write(bytes[writeBytes:]) write, err := writer.Write(bytes[writeBytes:])

View File

@ -0,0 +1,28 @@
package exceptions
import (
"fmt"
"github.com/tursom/GoCollections/lang"
"reflect"
)
type TypeCastException struct {
RuntimeException
}
func NewTypeCastException(message any, config *ExceptionConfig) *TypeCastException {
return &TypeCastException{
NewRuntimeException(
message,
"exception caused ElementNotFoundException:",
config.AddSkipStack(1),
),
}
}
func NewTypeCastExceptionByType[T any](obj any, config *ExceptionConfig) *TypeCastException {
return NewTypeCastException(
fmt.Sprintf("object %s cannot cast to %s", obj, reflect.TypeOf(lang.Nil[T]()).Name()),
config,
)
}

View File

@ -6,6 +6,6 @@ type WrongCallHostException struct {
func NewWrongCallHostException(message string) WrongCallHostException { func NewWrongCallHostException(message string) WrongCallHostException {
return WrongCallHostException{ return WrongCallHostException{
NewRuntimeException(nil, message, nil), NewRuntimeException(nil, message, DefaultExceptionConfig().AddSkipStack(1)),
} }
} }

29
lang/Class.go Normal file
View File

@ -0,0 +1,29 @@
package lang
import "reflect"
type (
Class struct {
t reflect.Type
methods map[string]Method
fields map[string]Field
}
Method struct {
}
Field struct {
}
)
func (c Class) GetType() reflect.Type {
return c.t
}
func (c Class) GetName() String {
return NewString(c.t.Name())
}
func GenerateClass(t reflect.Type) *Class {
//TODO impl
//t.Method(1).Func.Call()
return nil
}

View File

@ -29,7 +29,7 @@ func Hash32[T any](p *T) int32 {
func Hash64[T any](p *T) int32 { func Hash64[T any](p *T) int32 {
i := *(*int64)(unsafe.Pointer(p)) i := *(*int64)(unsafe.Pointer(p))
return int32(i)*31 ^ int32(i>>32) return int32(i) ^ int32(i>>32)
} }
func HashString(str string) int32 { func HashString(str string) int32 {

View File

@ -1,5 +1,7 @@
package lang package lang
import "unsafe"
func Nil[T any]() T { func Nil[T any]() T {
var n T var n T
return n return n
@ -12,3 +14,28 @@ func Len[T any](array []T) int {
func Append[T any](slice []T, elems ...T) []T { func Append[T any](slice []T, elems ...T) []T {
return append(slice, elems...) return append(slice, elems...)
} }
func TryCast[T any](v any) (T, bool) {
if v == nil {
return Nil[T](), true
} else {
t, ok := v.(T)
return t, ok
}
}
func Cast[T any](v any) T {
if v == nil {
return Nil[T]()
} else {
return v.(T)
}
}
func ForceCast[T any](v *any) T {
if v == nil {
return Nil[T]()
} else {
return Cast[T](unsafe.Pointer(v))
}
}

11
lang/Lang_test.go Normal file
View File

@ -0,0 +1,11 @@
package lang
import (
"fmt"
"testing"
)
func TestCast(t *testing.T) {
fmt.Println(Cast[int](1))
fmt.Println(Cast[int](nil))
}

View File

@ -15,9 +15,9 @@ type (
} }
Object interface { Object interface {
AsObject() Object fmt.Stringer
Equals(o Object) bool AsObject
ToString() String Equable
HashCode() int32 HashCode() int32
} }
@ -27,6 +27,10 @@ type (
} }
) )
func ToString(obj Object) String {
return NewString(obj.String())
}
func Equals(e Object, t Object) bool { func Equals(e Object, t Object) bool {
if e == nil { if e == nil {
return t == nil return t == nil
@ -34,6 +38,14 @@ func Equals(e Object, t Object) bool {
return e.Equals(t) return e.Equals(t)
} }
func HashCode(obj Object) int32 {
if obj == nil {
return 0
} else {
return obj.HashCode()
}
}
func NewBaseObject() BaseObject { func NewBaseObject() BaseObject {
return BaseObject{} return BaseObject{}
} }
@ -46,8 +58,16 @@ func (b *BaseObject) Equals(o Object) bool {
return b == o return b == o
} }
func (b *BaseObject) GoString() string {
return b.String()
}
func (b *BaseObject) String() string {
return fmt.Sprintf("BaseObject@%p", unsafe.Pointer(b))
}
func (b *BaseObject) ToString() String { func (b *BaseObject) ToString() String {
return NewString(fmt.Sprint(unsafe.Pointer(b))) return NewString(b.String())
} }
func (b *BaseObject) HashCode() int32 { func (b *BaseObject) HashCode() int32 {

View File

@ -13,6 +13,10 @@ func (i String) AsString() string {
return i.string return i.string
} }
func (i String) GoString() string {
return i.string
}
func (i String) String() string { func (i String) String() string {
return i.string return i.string
} }

View File

@ -1,33 +1,26 @@
package lang package util
import ( import (
"fmt" "github.com/tursom/GoCollections/lang"
"github.com/tursom/GoCollections/util"
"reflect" "reflect"
"testing" "testing"
) )
func TestStrongReference_ToString(t *testing.T) {
reference := util.NewStrongReference[Int](1)
fmt.Println(reference.ToString())
fmt.Println(reference)
}
func TestStrongReference_GetReference(t *testing.T) { func TestStrongReference_GetReference(t *testing.T) {
type fields struct { type fields struct {
reference Int reference lang.Int
} }
tests := []struct { tests := []struct {
name string name string
fields fields fields fields
want Int want lang.Int
}{ }{
{"1", fields{reference: 1}, 1}, {"1", fields{reference: 1}, 1},
{"2", fields{reference: 2}, 2}, {"2", fields{reference: 2}, 2},
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
r := util.NewStrongReference(tt.fields.reference) r := NewStrongReference(tt.fields.reference)
if got := r.GetReference(); !reflect.DeepEqual(got, tt.want) { if got := r.GetReference(); !reflect.DeepEqual(got, tt.want) {
t.Errorf("GetReference() = %v, want %v", got, tt.want) t.Errorf("GetReference() = %v, want %v", got, tt.want)
} }
@ -37,23 +30,23 @@ func TestStrongReference_GetReference(t *testing.T) {
func TestStrongReference_SetReference(t *testing.T) { func TestStrongReference_SetReference(t *testing.T) {
type fields struct { type fields struct {
reference Int reference lang.Int
} }
type args struct { type args struct {
reference Int reference lang.Int
} }
tests := []struct { tests := []struct {
name string name string
fields fields fields fields
args args args args
want Int want lang.Int
}{ }{
{"1", fields{reference: 1}, args{2}, 2}, {"1", fields{reference: 1}, args{2}, 2},
{"2", fields{reference: 2}, args{3}, 3}, {"2", fields{reference: 2}, args{3}, 3},
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
r := util.NewStrongReference(tt.fields.reference) r := NewStrongReference(tt.fields.reference)
r.SetReference(tt.args.reference) r.SetReference(tt.args.reference)
if got := r.GetReference(); !reflect.DeepEqual(got, tt.want) { if got := r.GetReference(); !reflect.DeepEqual(got, tt.want) {
t.Errorf("GetReference() = %v, want %v", got, tt.want) t.Errorf("GetReference() = %v, want %v", got, tt.want)