mirror of
https://gitee.com/johng/gf
synced 2026-06-06 02:25:47 +08:00
This pull request standardizes the use of the Go 1.18+ `any` type alias
instead of `interface{}` throughout the codebase. The change improves
code readability and aligns with modern Go best practices. The update
touches many files, including core data structures, code generation
templates, logging utilities, and test data, ensuring consistency across
all usages.
**Type alias migration to `any`:**
* Replaced all instances of `interface{}` with `any` in core data
structures such as `garray` and in generated model structs (e.g.,
`TableUser`, `User1`, `User2`) to modernize type usage.
[[1]](diffhunk://#diff-3a1259e160a4dfa5fe49dfe739fbdb986c0d0a2220a709882ea48d3ae1b8f911L31-R31)
[[2]](diffhunk://#diff-6c19859cb32c7516ea95ddc8f8235460818eb2f24d2204308e0d9e1b19e7d90fL15-R19)
[[3]](diffhunk://#diff-a15ba2f5e830b4833c47b902515a4f9e5a4f83a3707698f3229b307ec3776b41L15-R18)
[[4]](diffhunk://#diff-52e0837e84d49221d1b810d88fdf78221f36cffcd664fb42f8aba49a79b974dcL15-R19)
[[5]](diffhunk://#diff-11c3457d1a23a4ca6ecd00d6b856289774936b6a708384cf03aff164044e7546L15-R19)
[[6]](diffhunk://#diff-2cff9cf8e6a0cc34087326d8c8149c3bbaf74c76fdbdf5a73daed13cc04249e1L15-R19)
* Updated function signatures, method parameters, and return types from
`interface{}` to `any` in various parts of the codebase, including code
generation, service logic, and logging utilities (e.g., `mlog`).
[[1]](diffhunk://#diff-175edfeea54490b8fe4e18ffcbea5835efaf8f0b8acf623359073987cae7eb76L48-R55)
[[2]](diffhunk://#diff-2b1953fb78cf3593d8c2c7d911e95b65fd0b847c30ed0b4d167d16fe6d781235L54-R74)
[[3]](diffhunk://#diff-e001b7a4b63603b9b14f00de78a4d570bb76c5f57d856a24643f071032e12356L66-R73)
[[4]](diffhunk://#diff-5582954e8a9983988dc8854ad82067fb2ac6269b988e07357ad8db1dfec5f1a0L39-R41)
[[5]](diffhunk://#diff-c5d51d56f487779a2b6207c7ad26c7a20bbadcc846ce094fe60ab4cabff58c51L107-R107)
[[6]](diffhunk://#diff-f96e6a9fdb416eb1804ceaba1fe0ac637bff22c43837f8bb849c2366ce72d4a1L116-R121)
[[7]](diffhunk://#diff-f94c83a1b08ae060d9346f4a6031fc4a7b9a0b894e02d9afaa09018b6598eac0L112-R112)
[[8]](diffhunk://#diff-748b11dbe8828dd4c040ec23cae0b8fe57ecf0a2d1b7694ea39102294e633c64L36-R36)
[[9]](diffhunk://#diff-748b11dbe8828dd4c040ec23cae0b8fe57ecf0a2d1b7694ea39102294e633c64L74-R74)
[[10]](diffhunk://#diff-748b11dbe8828dd4c040ec23cae0b8fe57ecf0a2d1b7694ea39102294e633c64L96-R96)
**Generated code and templates:**
* Adjusted generated files and code generation templates to output `any`
instead of `interface{}` for relevant struct fields and function
signatures, ensuring that new code generation aligns with the updated
convention.
[[1]](diffhunk://#diff-6c19859cb32c7516ea95ddc8f8235460818eb2f24d2204308e0d9e1b19e7d90fL15-R19)
[[2]](diffhunk://#diff-a15ba2f5e830b4833c47b902515a4f9e5a4f83a3707698f3229b307ec3776b41L15-R18)
[[3]](diffhunk://#diff-52e0837e84d49221d1b810d88fdf78221f36cffcd664fb42f8aba49a79b974dcL15-R19)
[[4]](diffhunk://#diff-11c3457d1a23a4ca6ecd00d6b856289774936b6a708384cf03aff164044e7546L15-R19)
[[5]](diffhunk://#diff-2cff9cf8e6a0cc34087326d8c8149c3bbaf74c76fdbdf5a73daed13cc04249e1L15-R19)
[[6]](diffhunk://#diff-175edfeea54490b8fe4e18ffcbea5835efaf8f0b8acf623359073987cae7eb76L48-R55)
[[7]](diffhunk://#diff-e001b7a4b63603b9b14f00de78a4d570bb76c5f57d856a24643f071032e12356L66-R73)
[[8]](diffhunk://#diff-5582954e8a9983988dc8854ad82067fb2ac6269b988e07357ad8db1dfec5f1a0L39-R41)
**Container and utility updates:**
* Refactored the `garray` container implementation and related
constructors/methods to use `[]any` instead of `[]interface{}`, along
with corresponding function signatures.
[[1]](diffhunk://#diff-3a1259e160a4dfa5fe49dfe739fbdb986c0d0a2220a709882ea48d3ae1b8f911L31-R31)
[[2]](diffhunk://#diff-3a1259e160a4dfa5fe49dfe739fbdb986c0d0a2220a709882ea48d3ae1b8f911L52-R52)
[[3]](diffhunk://#diff-3a1259e160a4dfa5fe49dfe739fbdb986c0d0a2220a709882ea48d3ae1b8f911L62-R62)
[[4]](diffhunk://#diff-3a1259e160a4dfa5fe49dfe739fbdb986c0d0a2220a709882ea48d3ae1b8f911L73-R86)
[[5]](diffhunk://#diff-3a1259e160a4dfa5fe49dfe739fbdb986c0d0a2220a709882ea48d3ae1b8f911L96-R97)
[[6]](diffhunk://#diff-3a1259e160a4dfa5fe49dfe739fbdb986c0d0a2220a709882ea48d3ae1b8f911L107-R114)
[[7]](diffhunk://#diff-3a1259e160a4dfa5fe49dfe739fbdb986c0d0a2220a709882ea48d3ae1b8f911L124-R124)
[[8]](diffhunk://#diff-3a1259e160a4dfa5fe49dfe739fbdb986c0d0a2220a709882ea48d3ae1b8f911L135-R143)
[[9]](diffhunk://#diff-3a1259e160a4dfa5fe49dfe739fbdb986c0d0a2220a709882ea48d3ae1b8f911L167-R167)
These changes collectively modernize the codebase and prepare it for
future Go developments by using the idiomatic `any` type.
759 lines
16 KiB
Go
759 lines
16 KiB
Go
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
|
|
//
|
|
// This Source Code Form is subject to the terms of the MIT License.
|
|
// If a copy of the MIT was not distributed with this file,
|
|
// You can obtain one at https://github.com/gogf/gf.
|
|
|
|
package glist
|
|
|
|
import (
|
|
"container/list"
|
|
"testing"
|
|
|
|
"github.com/gogf/gf/v2/internal/json"
|
|
"github.com/gogf/gf/v2/test/gtest"
|
|
"github.com/gogf/gf/v2/util/gconv"
|
|
)
|
|
|
|
func checkListLen(t *gtest.T, l *List, len int) bool {
|
|
if n := l.Len(); n != len {
|
|
t.Errorf("l.Len() = %d, want %d", n, len)
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
func checkListPointers(t *gtest.T, l *List, es []*Element) {
|
|
if !checkListLen(t, l, len(es)) {
|
|
return
|
|
}
|
|
l.RLockFunc(func(list *list.List) {
|
|
for i, e := 0, l.list.Front(); i < list.Len(); i, e = i+1, e.Next() {
|
|
if e.Prev() != es[i].Prev() {
|
|
t.Errorf("list[%d].Prev = %p, want %p", i, e.Prev(), es[i].Prev())
|
|
}
|
|
if e.Next() != es[i].Next() {
|
|
t.Errorf("list[%d].Next = %p, want %p", i, e.Next(), es[i].Next())
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestVar(t *testing.T) {
|
|
var l List
|
|
l.PushFront(1)
|
|
l.PushFront(2)
|
|
if v := l.PopBack(); v != 1 {
|
|
t.Errorf("EXPECT %v, GOT %v", 1, v)
|
|
} else {
|
|
// fmt.Println(v)
|
|
}
|
|
if v := l.PopBack(); v != 2 {
|
|
t.Errorf("EXPECT %v, GOT %v", 2, v)
|
|
} else {
|
|
// fmt.Println(v)
|
|
}
|
|
if v := l.PopBack(); v != nil {
|
|
t.Errorf("EXPECT %v, GOT %v", nil, v)
|
|
} else {
|
|
// fmt.Println(v)
|
|
}
|
|
l.PushBack(1)
|
|
l.PushBack(2)
|
|
if v := l.PopFront(); v != 1 {
|
|
t.Errorf("EXPECT %v, GOT %v", 1, v)
|
|
} else {
|
|
// fmt.Println(v)
|
|
}
|
|
if v := l.PopFront(); v != 2 {
|
|
t.Errorf("EXPECT %v, GOT %v", 2, v)
|
|
} else {
|
|
// fmt.Println(v)
|
|
}
|
|
if v := l.PopFront(); v != nil {
|
|
t.Errorf("EXPECT %v, GOT %v", nil, v)
|
|
} else {
|
|
// fmt.Println(v)
|
|
}
|
|
}
|
|
|
|
func TestBasic(t *testing.T) {
|
|
l := New()
|
|
l.PushFront(1)
|
|
l.PushFront(2)
|
|
if v := l.PopBack(); v != 1 {
|
|
t.Errorf("EXPECT %v, GOT %v", 1, v)
|
|
} else {
|
|
// fmt.Println(v)
|
|
}
|
|
if v := l.PopBack(); v != 2 {
|
|
t.Errorf("EXPECT %v, GOT %v", 2, v)
|
|
} else {
|
|
// fmt.Println(v)
|
|
}
|
|
if v := l.PopBack(); v != nil {
|
|
t.Errorf("EXPECT %v, GOT %v", nil, v)
|
|
} else {
|
|
// fmt.Println(v)
|
|
}
|
|
l.PushBack(1)
|
|
l.PushBack(2)
|
|
if v := l.PopFront(); v != 1 {
|
|
t.Errorf("EXPECT %v, GOT %v", 1, v)
|
|
} else {
|
|
// fmt.Println(v)
|
|
}
|
|
if v := l.PopFront(); v != 2 {
|
|
t.Errorf("EXPECT %v, GOT %v", 2, v)
|
|
} else {
|
|
// fmt.Println(v)
|
|
}
|
|
if v := l.PopFront(); v != nil {
|
|
t.Errorf("EXPECT %v, GOT %v", nil, v)
|
|
} else {
|
|
// fmt.Println(v)
|
|
}
|
|
}
|
|
|
|
func TestList(t *testing.T) {
|
|
gtest.C(t, func(t *gtest.T) {
|
|
l := New()
|
|
checkListPointers(t, l, []*Element{})
|
|
|
|
// Single element list
|
|
e := l.PushFront("a")
|
|
checkListPointers(t, l, []*Element{e})
|
|
l.MoveToFront(e)
|
|
checkListPointers(t, l, []*Element{e})
|
|
l.MoveToBack(e)
|
|
checkListPointers(t, l, []*Element{e})
|
|
l.Remove(e)
|
|
checkListPointers(t, l, []*Element{})
|
|
|
|
// Bigger list
|
|
e2 := l.PushFront(2)
|
|
e1 := l.PushFront(1)
|
|
e3 := l.PushBack(3)
|
|
e4 := l.PushBack("banana")
|
|
checkListPointers(t, l, []*Element{e1, e2, e3, e4})
|
|
|
|
l.Remove(e2)
|
|
checkListPointers(t, l, []*Element{e1, e3, e4})
|
|
|
|
l.MoveToFront(e3) // move from middle
|
|
checkListPointers(t, l, []*Element{e3, e1, e4})
|
|
|
|
l.MoveToFront(e1)
|
|
l.MoveToBack(e3) // move from middle
|
|
checkListPointers(t, l, []*Element{e1, e4, e3})
|
|
|
|
l.MoveToFront(e3) // move from back
|
|
checkListPointers(t, l, []*Element{e3, e1, e4})
|
|
l.MoveToFront(e3) // should be no-op
|
|
checkListPointers(t, l, []*Element{e3, e1, e4})
|
|
|
|
l.MoveToBack(e3) // move from front
|
|
checkListPointers(t, l, []*Element{e1, e4, e3})
|
|
l.MoveToBack(e3) // should be no-op
|
|
checkListPointers(t, l, []*Element{e1, e4, e3})
|
|
|
|
e2 = l.InsertBefore(e1, 2) // insert before front
|
|
checkListPointers(t, l, []*Element{e2, e1, e4, e3})
|
|
l.Remove(e2)
|
|
e2 = l.InsertBefore(e4, 2) // insert before middle
|
|
checkListPointers(t, l, []*Element{e1, e2, e4, e3})
|
|
l.Remove(e2)
|
|
e2 = l.InsertBefore(e3, 2) // insert before back
|
|
checkListPointers(t, l, []*Element{e1, e4, e2, e3})
|
|
l.Remove(e2)
|
|
|
|
e2 = l.InsertAfter(e1, 2) // insert after front
|
|
checkListPointers(t, l, []*Element{e1, e2, e4, e3})
|
|
l.Remove(e2)
|
|
e2 = l.InsertAfter(e4, 2) // insert after middle
|
|
checkListPointers(t, l, []*Element{e1, e4, e2, e3})
|
|
l.Remove(e2)
|
|
e2 = l.InsertAfter(e3, 2) // insert after back
|
|
checkListPointers(t, l, []*Element{e1, e4, e3, e2})
|
|
l.Remove(e2)
|
|
|
|
// Check standard iteration.
|
|
sum := 0
|
|
for e := l.Front(); e != nil; e = e.Next() {
|
|
if i, ok := e.Value.(int); ok {
|
|
sum += i
|
|
}
|
|
}
|
|
if sum != 4 {
|
|
t.Errorf("sum over l = %d, want 4", sum)
|
|
}
|
|
|
|
// Clear all elements by iterating
|
|
var next *Element
|
|
for e := l.Front(); e != nil; e = next {
|
|
next = e.Next()
|
|
l.Remove(e)
|
|
}
|
|
checkListPointers(t, l, []*Element{})
|
|
})
|
|
}
|
|
|
|
func checkList(t *gtest.T, l *List, es []any) {
|
|
if !checkListLen(t, l, len(es)) {
|
|
return
|
|
}
|
|
|
|
i := 0
|
|
for e := l.Front(); e != nil; e = e.Next() {
|
|
|
|
switch e.Value.(type) {
|
|
case int:
|
|
if le := e.Value.(int); le != es[i] {
|
|
t.Errorf("elt[%d].Value() = %v, want %v", i, le, es[i])
|
|
}
|
|
// default string
|
|
default:
|
|
if le := e.Value.(string); le != es[i] {
|
|
t.Errorf("elt[%v].Value() = %v, want %v", i, le, es[i])
|
|
}
|
|
}
|
|
|
|
i++
|
|
}
|
|
|
|
// for e := l.Front(); e != nil; e = e.Next() {
|
|
// le := e.Value.(int)
|
|
// if le != es[i] {
|
|
// t.Errorf("elt[%d].Value() = %v, want %v", i, le, es[i])
|
|
// }
|
|
// i++
|
|
// }
|
|
}
|
|
|
|
func TestExtending(t *testing.T) {
|
|
gtest.C(t, func(t *gtest.T) {
|
|
l1 := New()
|
|
l2 := New()
|
|
|
|
l1.PushBack(1)
|
|
l1.PushBack(2)
|
|
l1.PushBack(3)
|
|
|
|
l2.PushBack(4)
|
|
l2.PushBack(5)
|
|
|
|
l3 := New()
|
|
l3.PushBackList(l1)
|
|
checkList(t, l3, []any{1, 2, 3})
|
|
l3.PushBackList(l2)
|
|
checkList(t, l3, []any{1, 2, 3, 4, 5})
|
|
|
|
l3 = New()
|
|
l3.PushFrontList(l2)
|
|
checkList(t, l3, []any{4, 5})
|
|
l3.PushFrontList(l1)
|
|
checkList(t, l3, []any{1, 2, 3, 4, 5})
|
|
|
|
checkList(t, l1, []any{1, 2, 3})
|
|
checkList(t, l2, []any{4, 5})
|
|
|
|
l3 = New()
|
|
l3.PushBackList(l1)
|
|
checkList(t, l3, []any{1, 2, 3})
|
|
l3.PushBackList(l3)
|
|
checkList(t, l3, []any{1, 2, 3, 1, 2, 3})
|
|
|
|
l3 = New()
|
|
l3.PushFrontList(l1)
|
|
checkList(t, l3, []any{1, 2, 3})
|
|
l3.PushFrontList(l3)
|
|
checkList(t, l3, []any{1, 2, 3, 1, 2, 3})
|
|
|
|
l3 = New()
|
|
l1.PushBackList(l3)
|
|
checkList(t, l1, []any{1, 2, 3})
|
|
l1.PushFrontList(l3)
|
|
checkList(t, l1, []any{1, 2, 3})
|
|
})
|
|
}
|
|
|
|
func TestRemove(t *testing.T) {
|
|
gtest.C(t, func(t *gtest.T) {
|
|
l := New()
|
|
e1 := l.PushBack(1)
|
|
e2 := l.PushBack(2)
|
|
checkListPointers(t, l, []*Element{e1, e2})
|
|
// e := l.Front()
|
|
// l.Remove(e)
|
|
// checkListPointers(t, l, []*Element{e2})
|
|
// l.Remove(e)
|
|
// checkListPointers(t, l, []*Element{e2})
|
|
})
|
|
}
|
|
|
|
func Test_Issue4103(t *testing.T) {
|
|
l1 := New()
|
|
l1.PushBack(1)
|
|
l1.PushBack(2)
|
|
|
|
l2 := New()
|
|
l2.PushBack(3)
|
|
l2.PushBack(4)
|
|
|
|
e := l1.Front()
|
|
l2.Remove(e) // l2 should not change because e is not an element of l2
|
|
if n := l2.Len(); n != 2 {
|
|
t.Errorf("l2.Len() = %d, want 2", n)
|
|
}
|
|
|
|
l1.InsertBefore(e, 8)
|
|
if n := l1.Len(); n != 3 {
|
|
t.Errorf("l1.Len() = %d, want 3", n)
|
|
}
|
|
}
|
|
|
|
func Test_Issue6349(t *testing.T) {
|
|
l := New()
|
|
l.PushBack(1)
|
|
l.PushBack(2)
|
|
|
|
e := l.Front()
|
|
l.Remove(e)
|
|
if e.Value != 1 {
|
|
t.Errorf("e.value = %d, want 1", e.Value)
|
|
}
|
|
// if e.Next() != nil {
|
|
// t.Errorf("e.Next() != nil")
|
|
// }
|
|
// if e.Prev() != nil {
|
|
// t.Errorf("e.Prev() != nil")
|
|
// }
|
|
}
|
|
|
|
func TestMove(t *testing.T) {
|
|
gtest.C(t, func(t *gtest.T) {
|
|
l := New()
|
|
e1 := l.PushBack(1)
|
|
e2 := l.PushBack(2)
|
|
e3 := l.PushBack(3)
|
|
e4 := l.PushBack(4)
|
|
|
|
l.MoveAfter(e3, e3)
|
|
checkListPointers(t, l, []*Element{e1, e2, e3, e4})
|
|
l.MoveBefore(e2, e2)
|
|
checkListPointers(t, l, []*Element{e1, e2, e3, e4})
|
|
|
|
l.MoveAfter(e3, e2)
|
|
checkListPointers(t, l, []*Element{e1, e2, e3, e4})
|
|
l.MoveBefore(e2, e3)
|
|
checkListPointers(t, l, []*Element{e1, e2, e3, e4})
|
|
|
|
l.MoveBefore(e2, e4)
|
|
checkListPointers(t, l, []*Element{e1, e3, e2, e4})
|
|
e2, e3 = e3, e2
|
|
|
|
l.MoveBefore(e4, e1)
|
|
checkListPointers(t, l, []*Element{e4, e1, e2, e3})
|
|
e1, e2, e3, e4 = e4, e1, e2, e3
|
|
|
|
l.MoveAfter(e4, e1)
|
|
checkListPointers(t, l, []*Element{e1, e4, e2, e3})
|
|
e2, e3, e4 = e4, e2, e3
|
|
|
|
l.MoveAfter(e2, e3)
|
|
checkListPointers(t, l, []*Element{e1, e3, e2, e4})
|
|
e2, e3 = e3, e2
|
|
})
|
|
}
|
|
|
|
// Test PushFront, PushBack, PushFrontList, PushBackList with uninitialized List
|
|
func TestZeroList(t *testing.T) {
|
|
gtest.C(t, func(t *gtest.T) {
|
|
var l1 = New()
|
|
l1.PushFront(1)
|
|
checkList(t, l1, []any{1})
|
|
|
|
var l2 = New()
|
|
l2.PushBack(1)
|
|
checkList(t, l2, []any{1})
|
|
|
|
var l3 = New()
|
|
l3.PushFrontList(l1)
|
|
checkList(t, l3, []any{1})
|
|
|
|
var l4 = New()
|
|
l4.PushBackList(l2)
|
|
checkList(t, l4, []any{1})
|
|
})
|
|
}
|
|
|
|
// Test that a list l is not modified when calling InsertBefore with a mark that is not an element of l.
|
|
func TestInsertBeforeUnknownMark(t *testing.T) {
|
|
gtest.C(t, func(t *gtest.T) {
|
|
l := New()
|
|
l.PushBack(1)
|
|
l.PushBack(2)
|
|
l.PushBack(3)
|
|
l.InsertBefore(new(Element), 1)
|
|
checkList(t, l, []any{1, 2, 3})
|
|
})
|
|
}
|
|
|
|
// Test that a list l is not modified when calling InsertAfter with a mark that is not an element of l.
|
|
func TestInsertAfterUnknownMark(t *testing.T) {
|
|
gtest.C(t, func(t *gtest.T) {
|
|
l := New()
|
|
l.PushBack(1)
|
|
l.PushBack(2)
|
|
l.PushBack(3)
|
|
l.InsertAfter(new(Element), 1)
|
|
checkList(t, l, []any{1, 2, 3})
|
|
})
|
|
}
|
|
|
|
// Test that a list l is not modified when calling MoveAfter or MoveBefore with a mark that is not an element of l.
|
|
func TestMoveUnknownMark(t *testing.T) {
|
|
gtest.C(t, func(t *gtest.T) {
|
|
l1 := New()
|
|
e1 := l1.PushBack(1)
|
|
|
|
l2 := New()
|
|
e2 := l2.PushBack(2)
|
|
|
|
l1.MoveAfter(e1, e2)
|
|
checkList(t, l1, []any{1})
|
|
checkList(t, l2, []any{2})
|
|
|
|
l1.MoveBefore(e1, e2)
|
|
checkList(t, l1, []any{1})
|
|
checkList(t, l2, []any{2})
|
|
})
|
|
}
|
|
|
|
func TestList_RemoveAll(t *testing.T) {
|
|
gtest.C(t, func(t *gtest.T) {
|
|
l := New()
|
|
l.PushBack(1)
|
|
l.RemoveAll()
|
|
checkList(t, l, []any{})
|
|
l.PushBack(2)
|
|
checkList(t, l, []any{2})
|
|
})
|
|
}
|
|
|
|
func TestList_PushFronts(t *testing.T) {
|
|
gtest.C(t, func(t *gtest.T) {
|
|
l := New()
|
|
a1 := []any{1, 2}
|
|
l.PushFronts(a1)
|
|
checkList(t, l, []any{2, 1})
|
|
a1 = []any{3, 4, 5}
|
|
l.PushFronts(a1)
|
|
checkList(t, l, []any{5, 4, 3, 2, 1})
|
|
})
|
|
}
|
|
|
|
func TestList_PushBacks(t *testing.T) {
|
|
gtest.C(t, func(t *gtest.T) {
|
|
l := New()
|
|
a1 := []any{1, 2}
|
|
l.PushBacks(a1)
|
|
checkList(t, l, []any{1, 2})
|
|
a1 = []any{3, 4, 5}
|
|
l.PushBacks(a1)
|
|
checkList(t, l, []any{1, 2, 3, 4, 5})
|
|
})
|
|
}
|
|
|
|
func TestList_PopBacks(t *testing.T) {
|
|
gtest.C(t, func(t *gtest.T) {
|
|
l := New()
|
|
a1 := []any{1, 2, 3, 4}
|
|
a2 := []any{"a", "c", "b", "e"}
|
|
l.PushFronts(a1)
|
|
i1 := l.PopBacks(2)
|
|
t.Assert(i1, []any{1, 2})
|
|
|
|
l.PushBacks(a2) // 4.3,a,c,b,e
|
|
i1 = l.PopBacks(3)
|
|
t.Assert(i1, []any{"e", "b", "c"})
|
|
})
|
|
}
|
|
|
|
func TestList_PopFronts(t *testing.T) {
|
|
gtest.C(t, func(t *gtest.T) {
|
|
l := New()
|
|
a1 := []any{1, 2, 3, 4}
|
|
l.PushFronts(a1)
|
|
i1 := l.PopFronts(2)
|
|
t.Assert(i1, []any{4, 3})
|
|
t.Assert(l.Len(), 2)
|
|
})
|
|
}
|
|
|
|
func TestList_PopBackAll(t *testing.T) {
|
|
gtest.C(t, func(t *gtest.T) {
|
|
l := New()
|
|
a1 := []any{1, 2, 3, 4}
|
|
l.PushFronts(a1)
|
|
i1 := l.PopBackAll()
|
|
t.Assert(i1, []any{1, 2, 3, 4})
|
|
t.Assert(l.Len(), 0)
|
|
})
|
|
}
|
|
|
|
func TestList_PopFrontAll(t *testing.T) {
|
|
gtest.C(t, func(t *gtest.T) {
|
|
l := New()
|
|
a1 := []any{1, 2, 3, 4}
|
|
l.PushFronts(a1)
|
|
i1 := l.PopFrontAll()
|
|
t.Assert(i1, []any{4, 3, 2, 1})
|
|
t.Assert(l.Len(), 0)
|
|
})
|
|
}
|
|
|
|
func TestList_FrontAll(t *testing.T) {
|
|
gtest.C(t, func(t *gtest.T) {
|
|
l := New()
|
|
a1 := []any{1, 2, 3, 4}
|
|
l.PushFronts(a1)
|
|
i1 := l.FrontAll()
|
|
t.Assert(i1, []any{4, 3, 2, 1})
|
|
t.Assert(l.Len(), 4)
|
|
})
|
|
}
|
|
|
|
func TestList_BackAll(t *testing.T) {
|
|
gtest.C(t, func(t *gtest.T) {
|
|
l := New()
|
|
a1 := []any{1, 2, 3, 4}
|
|
l.PushFronts(a1)
|
|
i1 := l.BackAll()
|
|
t.Assert(i1, []any{1, 2, 3, 4})
|
|
t.Assert(l.Len(), 4)
|
|
})
|
|
}
|
|
|
|
func TestList_FrontValue(t *testing.T) {
|
|
gtest.C(t, func(t *gtest.T) {
|
|
l := New()
|
|
l2 := New()
|
|
a1 := []any{1, 2, 3, 4}
|
|
l.PushFronts(a1)
|
|
i1 := l.FrontValue()
|
|
t.Assert(gconv.Int(i1), 4)
|
|
t.Assert(l.Len(), 4)
|
|
|
|
i1 = l2.FrontValue()
|
|
t.Assert(i1, nil)
|
|
})
|
|
}
|
|
|
|
func TestList_BackValue(t *testing.T) {
|
|
gtest.C(t, func(t *gtest.T) {
|
|
l := New()
|
|
l2 := New()
|
|
a1 := []any{1, 2, 3, 4}
|
|
l.PushFronts(a1)
|
|
i1 := l.BackValue()
|
|
t.Assert(gconv.Int(i1), 1)
|
|
t.Assert(l.Len(), 4)
|
|
|
|
i1 = l2.FrontValue()
|
|
t.Assert(i1, nil)
|
|
})
|
|
}
|
|
|
|
func TestList_Back(t *testing.T) {
|
|
gtest.C(t, func(t *gtest.T) {
|
|
l := New()
|
|
a1 := []any{1, 2, 3, 4}
|
|
l.PushFronts(a1)
|
|
e1 := l.Back()
|
|
t.Assert(e1.Value, 1)
|
|
t.Assert(l.Len(), 4)
|
|
})
|
|
}
|
|
|
|
func TestList_Size(t *testing.T) {
|
|
gtest.C(t, func(t *gtest.T) {
|
|
l := New()
|
|
a1 := []any{1, 2, 3, 4}
|
|
l.PushFronts(a1)
|
|
t.Assert(l.Size(), 4)
|
|
l.PopFront()
|
|
t.Assert(l.Size(), 3)
|
|
})
|
|
}
|
|
|
|
func TestList_Removes(t *testing.T) {
|
|
gtest.C(t, func(t *gtest.T) {
|
|
l := New()
|
|
a1 := []any{1, 2, 3, 4}
|
|
l.PushFronts(a1)
|
|
e1 := l.Back()
|
|
l.Removes([]*Element{e1})
|
|
t.Assert(l.Len(), 3)
|
|
|
|
e2 := l.Back()
|
|
l.Removes([]*Element{e2})
|
|
t.Assert(l.Len(), 2)
|
|
checkList(t, l, []any{4, 3})
|
|
})
|
|
}
|
|
|
|
func TestList_Pop(t *testing.T) {
|
|
gtest.C(t, func(t *gtest.T) {
|
|
l := NewFrom([]any{1, 2, 3, 4, 5, 6, 7, 8, 9})
|
|
|
|
t.Assert(l.PopBack(), 9)
|
|
t.Assert(l.PopBacks(2), []any{8, 7})
|
|
t.Assert(l.PopFront(), 1)
|
|
t.Assert(l.PopFronts(2), []any{2, 3})
|
|
})
|
|
}
|
|
|
|
func TestList_Clear(t *testing.T) {
|
|
gtest.C(t, func(t *gtest.T) {
|
|
l := New()
|
|
a1 := []any{1, 2, 3, 4}
|
|
l.PushFronts(a1)
|
|
l.Clear()
|
|
t.Assert(l.Len(), 0)
|
|
})
|
|
}
|
|
|
|
func TestList_IteratorAsc(t *testing.T) {
|
|
gtest.C(t, func(t *gtest.T) {
|
|
l := New()
|
|
a1 := []any{1, 2, 5, 6, 3, 4}
|
|
l.PushFronts(a1)
|
|
e1 := l.Back()
|
|
fun1 := func(e *Element) bool {
|
|
return gconv.Int(e1.Value) > 2
|
|
}
|
|
checkList(t, l, []any{4, 3, 6, 5, 2, 1})
|
|
l.IteratorAsc(fun1)
|
|
checkList(t, l, []any{4, 3, 6, 5, 2, 1})
|
|
})
|
|
}
|
|
|
|
func TestList_IteratorDesc(t *testing.T) {
|
|
gtest.C(t, func(t *gtest.T) {
|
|
l := New()
|
|
a1 := []any{1, 2, 3, 4}
|
|
l.PushFronts(a1)
|
|
e1 := l.Back()
|
|
fun1 := func(e *Element) bool {
|
|
return gconv.Int(e1.Value) > 6
|
|
}
|
|
l.IteratorDesc(fun1)
|
|
t.Assert(l.Len(), 4)
|
|
checkList(t, l, []any{4, 3, 2, 1})
|
|
})
|
|
}
|
|
|
|
func TestList_Iterator(t *testing.T) {
|
|
gtest.C(t, func(t *gtest.T) {
|
|
l := New()
|
|
a1 := []any{"a", "b", "c", "d", "e"}
|
|
l.PushFronts(a1)
|
|
e1 := l.Back()
|
|
fun1 := func(e *Element) bool {
|
|
return gconv.String(e1.Value) > "c"
|
|
}
|
|
checkList(t, l, []any{"e", "d", "c", "b", "a"})
|
|
l.Iterator(fun1)
|
|
checkList(t, l, []any{"e", "d", "c", "b", "a"})
|
|
})
|
|
}
|
|
|
|
func TestList_Join(t *testing.T) {
|
|
gtest.C(t, func(t *gtest.T) {
|
|
l := NewFrom([]any{1, 2, "a", `"b"`, `\c`})
|
|
t.Assert(l.Join(","), `1,2,a,"b",\c`)
|
|
t.Assert(l.Join("."), `1.2.a."b".\c`)
|
|
})
|
|
}
|
|
|
|
func TestList_String(t *testing.T) {
|
|
gtest.C(t, func(t *gtest.T) {
|
|
l := NewFrom([]any{1, 2, "a", `"b"`, `\c`})
|
|
t.Assert(l.String(), `[1,2,a,"b",\c]`)
|
|
})
|
|
}
|
|
|
|
func TestList_Json(t *testing.T) {
|
|
// Marshal
|
|
gtest.C(t, func(t *gtest.T) {
|
|
a := []any{"a", "b", "c"}
|
|
l := New()
|
|
l.PushBacks(a)
|
|
b1, err1 := json.Marshal(l)
|
|
b2, err2 := json.Marshal(a)
|
|
t.Assert(err1, err2)
|
|
t.Assert(b1, b2)
|
|
})
|
|
// Unmarshal
|
|
gtest.C(t, func(t *gtest.T) {
|
|
a := []any{"a", "b", "c"}
|
|
l := New()
|
|
b, err := json.Marshal(a)
|
|
t.AssertNil(err)
|
|
|
|
err = json.UnmarshalUseNumber(b, l)
|
|
t.AssertNil(err)
|
|
t.Assert(l.FrontAll(), a)
|
|
})
|
|
gtest.C(t, func(t *gtest.T) {
|
|
var l List
|
|
a := []any{"a", "b", "c"}
|
|
b, err := json.Marshal(a)
|
|
t.AssertNil(err)
|
|
|
|
err = json.UnmarshalUseNumber(b, &l)
|
|
t.AssertNil(err)
|
|
t.Assert(l.FrontAll(), a)
|
|
})
|
|
}
|
|
|
|
func TestList_UnmarshalValue(t *testing.T) {
|
|
type TList struct {
|
|
Name string
|
|
List *List
|
|
}
|
|
// JSON
|
|
gtest.C(t, func(t *gtest.T) {
|
|
var tlist *TList
|
|
err := gconv.Struct(map[string]any{
|
|
"name": "john",
|
|
"list": []byte(`[1,2,3]`),
|
|
}, &tlist)
|
|
t.AssertNil(err)
|
|
t.Assert(tlist.Name, "john")
|
|
t.Assert(tlist.List.FrontAll(), []any{1, 2, 3})
|
|
})
|
|
// Map
|
|
gtest.C(t, func(t *gtest.T) {
|
|
var tlist *TList
|
|
err := gconv.Struct(map[string]any{
|
|
"name": "john",
|
|
"list": []any{1, 2, 3},
|
|
}, &tlist)
|
|
t.AssertNil(err)
|
|
t.Assert(tlist.Name, "john")
|
|
t.Assert(tlist.List.FrontAll(), []any{1, 2, 3})
|
|
})
|
|
}
|
|
|
|
func TestList_DeepCopy(t *testing.T) {
|
|
gtest.C(t, func(t *gtest.T) {
|
|
l := NewFrom([]any{1, 2, "a", `"b"`, `\c`})
|
|
copyList := l.DeepCopy()
|
|
cl := copyList.(*List)
|
|
cl.PopBack()
|
|
t.AssertNE(l.Size(), cl.Size())
|
|
})
|
|
}
|