Исходники и презентации
This commit is contained in:
49
homework/allocator/homework_test.go
Normal file
49
homework/allocator/homework_test.go
Normal file
@ -0,0 +1,49 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
"unsafe"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
// go test -v homework_test.go
|
||||
|
||||
func Defragment(memory []byte, pointers []unsafe.Pointer) {
|
||||
// need to implement
|
||||
}
|
||||
|
||||
func TestDefragmentation(t *testing.T) {
|
||||
var fragmentedMemory = []byte{
|
||||
0xFF, 0x00, 0x00, 0x00,
|
||||
0x00, 0xFF, 0x00, 0x00,
|
||||
0x00, 0x00, 0xFF, 0x00,
|
||||
0x00, 0x00, 0x00, 0xFF,
|
||||
}
|
||||
|
||||
var fragmentedPointers = []unsafe.Pointer{
|
||||
unsafe.Pointer(&fragmentedMemory[0]),
|
||||
unsafe.Pointer(&fragmentedMemory[5]),
|
||||
unsafe.Pointer(&fragmentedMemory[10]),
|
||||
unsafe.Pointer(&fragmentedMemory[15]),
|
||||
}
|
||||
|
||||
var defragmentedPointers = []unsafe.Pointer{
|
||||
unsafe.Pointer(&fragmentedMemory[0]),
|
||||
unsafe.Pointer(&fragmentedMemory[1]),
|
||||
unsafe.Pointer(&fragmentedMemory[2]),
|
||||
unsafe.Pointer(&fragmentedMemory[3]),
|
||||
}
|
||||
|
||||
var defragmentedMemory = []byte{
|
||||
0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
}
|
||||
|
||||
Defragment(fragmentedMemory, fragmentedPointers)
|
||||
assert.True(t, reflect.DeepEqual(defragmentedMemory, fragmentedMemory))
|
||||
assert.True(t, reflect.DeepEqual(defragmentedPointers, fragmentedPointers))
|
||||
}
|
||||
58
homework/channels/homework_test.go
Normal file
58
homework/channels/homework_test.go
Normal file
@ -0,0 +1,58 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
// go test -v homework_test.go
|
||||
|
||||
type WorkerPool struct {
|
||||
// need to implement
|
||||
}
|
||||
|
||||
func NewWorkerPool(workersNumber int) *WorkerPool {
|
||||
// need to implement
|
||||
return &WorkerPool{}
|
||||
}
|
||||
|
||||
// Return an error if the pool is full
|
||||
func (wp *WorkerPool) AddTask(task func()) error {
|
||||
// need to implement
|
||||
return nil
|
||||
}
|
||||
|
||||
// Shutdown all workers and wait for all
|
||||
// tasks in the pool to complete
|
||||
func (wp *WorkerPool) Shutdown() {
|
||||
// need to implement
|
||||
}
|
||||
|
||||
func TestWorkerPool(t *testing.T) {
|
||||
var counter atomic.Int32
|
||||
task := func() {
|
||||
time.Sleep(time.Millisecond * 500)
|
||||
counter.Add(1)
|
||||
}
|
||||
|
||||
pool := NewWorkerPool(2)
|
||||
_ = pool.AddTask(task)
|
||||
_ = pool.AddTask(task)
|
||||
_ = pool.AddTask(task)
|
||||
|
||||
time.Sleep(time.Millisecond * 600)
|
||||
assert.Equal(t, int32(2), counter.Load())
|
||||
|
||||
time.Sleep(time.Millisecond * 600)
|
||||
assert.Equal(t, int32(3), counter.Load())
|
||||
|
||||
_ = pool.AddTask(task)
|
||||
_ = pool.AddTask(task)
|
||||
_ = pool.AddTask(task)
|
||||
pool.Shutdown() // wait tasks
|
||||
|
||||
assert.Equal(t, int32(6), counter.Load())
|
||||
}
|
||||
74
homework/contexts/homework_test.go
Normal file
74
homework/contexts/homework_test.go
Normal file
@ -0,0 +1,74 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
type Group struct {
|
||||
// need to implement
|
||||
}
|
||||
|
||||
func NewErrGroup(ctx context.Context) (*Group, context.Context) {
|
||||
// need to implement
|
||||
return &Group{}, ctx
|
||||
}
|
||||
|
||||
func (g *Group) Go(action func() error) {
|
||||
// need to implement
|
||||
}
|
||||
|
||||
func (g *Group) Wait() error {
|
||||
// need to implement
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestErrGroupWithoutError(t *testing.T) {
|
||||
var counter atomic.Int32
|
||||
group, _ := NewErrGroup(context.Background())
|
||||
|
||||
for i := 0; i < 5; i++ {
|
||||
group.Go(func() error {
|
||||
time.Sleep(time.Second)
|
||||
counter.Add(1)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
err := group.Wait()
|
||||
assert.Equal(t, int32(5), counter.Load())
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestErrGroupWithError(t *testing.T) {
|
||||
var counter atomic.Int32
|
||||
group, ctx := NewErrGroup(context.Background())
|
||||
|
||||
for i := 0; i < 5; i++ {
|
||||
group.Go(func() error {
|
||||
timer := time.NewTimer(time.Second)
|
||||
defer timer.Stop()
|
||||
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
case <-timer.C:
|
||||
counter.Add(1)
|
||||
return nil
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
group.Go(func() error {
|
||||
return errors.New("error")
|
||||
})
|
||||
|
||||
err := group.Wait()
|
||||
assert.Equal(t, int32(0), counter.Load())
|
||||
assert.Error(t, err)
|
||||
}
|
||||
48
homework/data_types/homework_test.go
Normal file
48
homework/data_types/homework_test.go
Normal file
@ -0,0 +1,48 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
// go test -v homework_test.go
|
||||
|
||||
func ToLittleEndian(number uint32) uint32 {
|
||||
return 0 // need to implement
|
||||
}
|
||||
|
||||
func TestСonversion(t *testing.T) {
|
||||
tests := map[string]struct {
|
||||
number uint32
|
||||
result uint32
|
||||
}{
|
||||
"test case #1": {
|
||||
number: 0x00000000,
|
||||
result: 0x00000000,
|
||||
},
|
||||
"test case #2": {
|
||||
number: 0xFFFFFFFF,
|
||||
result: 0xFFFFFFFF,
|
||||
},
|
||||
"test case #3": {
|
||||
number: 0x00FF00FF,
|
||||
result: 0xFF00FF00,
|
||||
},
|
||||
"test case #4": {
|
||||
number: 0x0000FFFF,
|
||||
result: 0xFFFF0000,
|
||||
},
|
||||
"test case #5": {
|
||||
number: 0x01020304,
|
||||
result: 0x04030201,
|
||||
},
|
||||
}
|
||||
|
||||
for name, test := range tests {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
result := ToLittleEndian(test.number)
|
||||
assert.Equal(t, test.result, result)
|
||||
})
|
||||
}
|
||||
}
|
||||
33
homework/errors/homework_test.go
Normal file
33
homework/errors/homework_test.go
Normal file
@ -0,0 +1,33 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
// go test -v homework_test.go
|
||||
|
||||
type MultiError struct {
|
||||
// need to implement
|
||||
}
|
||||
|
||||
func (e *MultiError) Error() string {
|
||||
// need to implement
|
||||
return ""
|
||||
}
|
||||
|
||||
func Append(err error, errs ...error) *MultiError {
|
||||
// need to implement
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestMultiError(t *testing.T) {
|
||||
var err error
|
||||
err = Append(err, errors.New("error 1"))
|
||||
err = Append(err, errors.New("error 2"))
|
||||
|
||||
expectedMessage := "2 errors occured:\n\t* error 1\t* error 2\n"
|
||||
assert.EqualError(t, err, expectedMessage)
|
||||
}
|
||||
150
homework/functions/homework_test.go
Normal file
150
homework/functions/homework_test.go
Normal file
@ -0,0 +1,150 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func Map(data []int, action func(int) int) []int {
|
||||
// need to implement
|
||||
return nil
|
||||
}
|
||||
|
||||
func Filter(data []int, action func(int) bool) []int {
|
||||
// need to implement
|
||||
return nil
|
||||
}
|
||||
|
||||
func Reduce(data []int, initial int, action func(int, int) int) int {
|
||||
// need to implement
|
||||
return 0
|
||||
}
|
||||
|
||||
func TestMap(t *testing.T) {
|
||||
tests := map[string]struct {
|
||||
data []int
|
||||
action func(int) int
|
||||
result []int
|
||||
}{
|
||||
"nil numbers": {
|
||||
action: func(number int) int {
|
||||
return -number
|
||||
},
|
||||
},
|
||||
"empty numbers": {
|
||||
data: []int{},
|
||||
action: func(number int) int {
|
||||
return -number
|
||||
},
|
||||
result: []int{},
|
||||
},
|
||||
"inc numbers": {
|
||||
data: []int{1, 2, 3, 4, 5},
|
||||
action: func(number int) int {
|
||||
return number + 1
|
||||
},
|
||||
result: []int{2, 3, 4, 5, 6},
|
||||
},
|
||||
"double numbers": {
|
||||
data: []int{1, 2, 3, 4, 5},
|
||||
action: func(number int) int {
|
||||
return number * number
|
||||
},
|
||||
result: []int{1, 4, 9, 16, 25},
|
||||
},
|
||||
}
|
||||
|
||||
for name, test := range tests {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
result := Map(test.data, test.action)
|
||||
assert.True(t, reflect.DeepEqual(test.result, result))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestFilter(t *testing.T) {
|
||||
tests := map[string]struct {
|
||||
data []int
|
||||
action func(int) bool
|
||||
result []int
|
||||
}{
|
||||
"nil numbers": {
|
||||
action: func(number int) bool {
|
||||
return number == 0
|
||||
},
|
||||
},
|
||||
"empty numbers": {
|
||||
data: []int{},
|
||||
action: func(number int) bool {
|
||||
return number == 1
|
||||
},
|
||||
result: []int{},
|
||||
},
|
||||
"even numbers": {
|
||||
data: []int{1, 2, 3, 4, 5},
|
||||
action: func(number int) bool {
|
||||
return number%2 == 0
|
||||
},
|
||||
result: []int{2, 4},
|
||||
},
|
||||
"positive numbers": {
|
||||
data: []int{-1, -2, 1, 2},
|
||||
action: func(number int) bool {
|
||||
return number > 0
|
||||
},
|
||||
result: []int{1, 2},
|
||||
},
|
||||
}
|
||||
|
||||
for name, test := range tests {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
result := Filter(test.data, test.action)
|
||||
assert.True(t, reflect.DeepEqual(test.result, result))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestReduce(t *testing.T) {
|
||||
tests := map[string]struct {
|
||||
initial int
|
||||
data []int
|
||||
action func(int, int) int
|
||||
result int
|
||||
}{
|
||||
"nil numbers": {
|
||||
action: func(lhs, rhs int) int {
|
||||
return 0
|
||||
},
|
||||
},
|
||||
"empty numbers": {
|
||||
data: []int{},
|
||||
action: func(lhs, rhs int) int {
|
||||
return 0
|
||||
},
|
||||
},
|
||||
"sum of numbers": {
|
||||
data: []int{1, 2, 3, 4, 5},
|
||||
action: func(lhs, rhs int) int {
|
||||
return lhs + rhs
|
||||
},
|
||||
result: 15,
|
||||
},
|
||||
"sum of numbers with initial value": {
|
||||
initial: 10,
|
||||
data: []int{1, 2, 3, 4, 5},
|
||||
action: func(lhs, rhs int) int {
|
||||
return lhs + rhs
|
||||
},
|
||||
result: 25,
|
||||
},
|
||||
}
|
||||
|
||||
for name, test := range tests {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
result := Reduce(test.data, test.initial, test.action)
|
||||
assert.Equal(t, test.result, result)
|
||||
})
|
||||
}
|
||||
}
|
||||
62
homework/garbage_collector/homework_test.go
Normal file
62
homework/garbage_collector/homework_test.go
Normal file
@ -0,0 +1,62 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
"unsafe"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
// go test -v homework_test.go
|
||||
|
||||
func Trace(stacks [][]uintptr) []uintptr {
|
||||
// need to implement
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestTrace(t *testing.T) {
|
||||
var heapObjects = []int{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
}
|
||||
|
||||
var heapPointer1 *int = &heapObjects[1]
|
||||
var heapPointer2 *int = &heapObjects[2]
|
||||
var heapPointer3 *int = nil
|
||||
var heapPointer4 **int = &heapPointer3
|
||||
|
||||
var stacks = [][]uintptr{
|
||||
{
|
||||
uintptr(unsafe.Pointer(&heapPointer1)), 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, uintptr(unsafe.Pointer(&heapObjects[0])),
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
},
|
||||
{
|
||||
uintptr(unsafe.Pointer(&heapPointer2)), 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, uintptr(unsafe.Pointer(&heapObjects[1])),
|
||||
0x00, 0x00, 0x00, uintptr(unsafe.Pointer(&heapObjects[2])),
|
||||
uintptr(unsafe.Pointer(&heapPointer4)), 0x00, 0x00, 0x00,
|
||||
},
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, uintptr(unsafe.Pointer(&heapObjects[3])),
|
||||
},
|
||||
}
|
||||
|
||||
pointers := Trace(stacks)
|
||||
expectedPointers := []uintptr{
|
||||
uintptr(unsafe.Pointer(&heapPointer1)),
|
||||
uintptr(unsafe.Pointer(&heapObjects[0])),
|
||||
uintptr(unsafe.Pointer(&heapPointer2)),
|
||||
uintptr(unsafe.Pointer(&heapObjects[1])),
|
||||
uintptr(unsafe.Pointer(&heapObjects[2])),
|
||||
uintptr(unsafe.Pointer(&heapPointer4)),
|
||||
uintptr(unsafe.Pointer(&heapPointer3)),
|
||||
uintptr(unsafe.Pointer(&heapObjects[3])),
|
||||
}
|
||||
|
||||
assert.True(t, reflect.DeepEqual(expectedPointers, pointers))
|
||||
}
|
||||
56
homework/generics_and_reflection/homework_test.go
Normal file
56
homework/generics_and_reflection/homework_test.go
Normal file
@ -0,0 +1,56 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
// go test -v homework_test.go
|
||||
|
||||
type Person struct {
|
||||
Name string `properties:"name"`
|
||||
Address string `properties:"address,omitempty"`
|
||||
Age int `properties:"age"`
|
||||
Married bool `properties:"married"`
|
||||
}
|
||||
|
||||
func Serialize(person Person) string {
|
||||
// need to implement
|
||||
return ""
|
||||
}
|
||||
|
||||
func TestSerialization(t *testing.T) {
|
||||
tests := map[string]struct {
|
||||
person Person
|
||||
result string
|
||||
}{
|
||||
"test case with empty fields": {
|
||||
result: "name=\nage=0\nmarried=false",
|
||||
},
|
||||
"test case with fields": {
|
||||
person: Person{
|
||||
Name: "John Doe",
|
||||
Age: 30,
|
||||
Married: true,
|
||||
},
|
||||
result: "name=John Doe\nage=30\nmarried=true",
|
||||
},
|
||||
"test case with omitempty field": {
|
||||
person: Person{
|
||||
Name: "John Doe",
|
||||
Age: 30,
|
||||
Married: true,
|
||||
Address: "Paris",
|
||||
},
|
||||
result: "name=John Doe\naddress=Paris\nage=30\nmarried=true",
|
||||
},
|
||||
}
|
||||
|
||||
for name, test := range tests {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
result := Serialize(test.person)
|
||||
assert.Equal(t, test.result, result)
|
||||
})
|
||||
}
|
||||
}
|
||||
63
homework/goroutines_and_scheduler/homework_test.go
Normal file
63
homework/goroutines_and_scheduler/homework_test.go
Normal file
@ -0,0 +1,63 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
type Task struct {
|
||||
Identifier int
|
||||
Priority int
|
||||
}
|
||||
|
||||
type Scheduler struct {
|
||||
// need to implement
|
||||
}
|
||||
|
||||
func NewScheduler() Scheduler {
|
||||
// need to implement
|
||||
return Scheduler{}
|
||||
}
|
||||
|
||||
func (s *Scheduler) AddTask(task Task) {
|
||||
// need to implement
|
||||
}
|
||||
|
||||
func (s *Scheduler) ChangeTaskPriority(taskID int, newPriority int) {
|
||||
// need to implement
|
||||
}
|
||||
|
||||
func (s *Scheduler) GetTask() Task {
|
||||
// need to implement
|
||||
return Task{}
|
||||
}
|
||||
|
||||
func TestTrace(t *testing.T) {
|
||||
task1 := Task{Identifier: 1, Priority: 10}
|
||||
task2 := Task{Identifier: 2, Priority: 20}
|
||||
task3 := Task{Identifier: 3, Priority: 30}
|
||||
task4 := Task{Identifier: 4, Priority: 40}
|
||||
task5 := Task{Identifier: 5, Priority: 50}
|
||||
|
||||
scheduler := NewScheduler()
|
||||
scheduler.AddTask(task1)
|
||||
scheduler.AddTask(task2)
|
||||
scheduler.AddTask(task3)
|
||||
scheduler.AddTask(task4)
|
||||
scheduler.AddTask(task5)
|
||||
|
||||
task := scheduler.GetTask()
|
||||
assert.Equal(t, task5, task)
|
||||
|
||||
task = scheduler.GetTask()
|
||||
assert.Equal(t, task4, task)
|
||||
|
||||
scheduler.ChangeTaskPriority(1, 100)
|
||||
|
||||
task = scheduler.GetTask()
|
||||
assert.Equal(t, task1, task)
|
||||
|
||||
task = scheduler.GetTask()
|
||||
assert.Equal(t, task3, task)
|
||||
}
|
||||
63
homework/interfaces/homework_test.go
Normal file
63
homework/interfaces/homework_test.go
Normal file
@ -0,0 +1,63 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
// go test -v homework_test.go
|
||||
|
||||
type UserService struct {
|
||||
// not need to implement
|
||||
NotEmptyStruct bool
|
||||
}
|
||||
type MessageService struct {
|
||||
// not need to implement
|
||||
NotEmptyStruct bool
|
||||
}
|
||||
|
||||
type Container struct {
|
||||
// need to implement
|
||||
}
|
||||
|
||||
func NewContainer() *Container {
|
||||
// need to implement
|
||||
return &Container{}
|
||||
}
|
||||
|
||||
func (c *Container) RegisterType(name string, constructor interface{}) {
|
||||
// need to implement
|
||||
}
|
||||
|
||||
func (c *Container) Resolve(name string) (interface{}, error) {
|
||||
// need to implement
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func TestDIContainer(t *testing.T) {
|
||||
container := NewContainer()
|
||||
container.RegisterType("UserService", func() interface{} {
|
||||
return &UserService{}
|
||||
})
|
||||
container.RegisterType("MessageService", func() interface{} {
|
||||
return &MessageService{}
|
||||
})
|
||||
|
||||
userService1, err := container.Resolve("UserService")
|
||||
assert.NoError(t, err)
|
||||
userService2, err := container.Resolve("UserService")
|
||||
assert.NoError(t, err)
|
||||
|
||||
u1 := userService1.(*UserService)
|
||||
u2 := userService2.(*UserService)
|
||||
assert.False(t, u1 == u2)
|
||||
|
||||
messageService, err := container.Resolve("MessageService")
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, messageService)
|
||||
|
||||
paymentService, err := container.Resolve("PaymentService")
|
||||
assert.Error(t, err)
|
||||
assert.Nil(t, paymentService)
|
||||
}
|
||||
83
homework/maps/homewrok_test.go
Normal file
83
homework/maps/homewrok_test.go
Normal file
@ -0,0 +1,83 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
// go test -v homework_test.go
|
||||
|
||||
type OrderedMap struct {
|
||||
// need to implement
|
||||
}
|
||||
|
||||
func NewOrderedMap() OrderedMap {
|
||||
return OrderedMap{} // need to implement
|
||||
}
|
||||
|
||||
func (m *OrderedMap) Insert(key, value int) {
|
||||
// need to implement
|
||||
}
|
||||
|
||||
func (m *OrderedMap) Erase(key int) {
|
||||
// need to implement
|
||||
}
|
||||
|
||||
func (m *OrderedMap) Contains(key int) bool {
|
||||
return false // need to implement
|
||||
}
|
||||
|
||||
func (m *OrderedMap) Size() int {
|
||||
return 0 // need to implement
|
||||
}
|
||||
|
||||
func (m *OrderedMap) ForEach(action func(int, int)) {
|
||||
// need to implement
|
||||
}
|
||||
|
||||
func TestCircularQueue(t *testing.T) {
|
||||
data := NewOrderedMap()
|
||||
assert.Zero(t, data.Size())
|
||||
|
||||
data.Insert(10, 10)
|
||||
data.Insert(5, 5)
|
||||
data.Insert(15, 15)
|
||||
data.Insert(2, 2)
|
||||
data.Insert(4, 4)
|
||||
data.Insert(12, 12)
|
||||
data.Insert(14, 14)
|
||||
|
||||
assert.Equal(t, 7, data.Size())
|
||||
assert.True(t, data.Contains(4))
|
||||
assert.True(t, data.Contains(12))
|
||||
assert.False(t, data.Contains(3))
|
||||
assert.False(t, data.Contains(13))
|
||||
|
||||
var keys []int
|
||||
expectedKeys := []int{2, 4, 5, 10, 12, 14, 15}
|
||||
data.ForEach(func(key, _ int) {
|
||||
keys = append(keys, key)
|
||||
})
|
||||
|
||||
assert.True(t, reflect.DeepEqual(expectedKeys, keys))
|
||||
|
||||
data.Erase(15)
|
||||
data.Erase(14)
|
||||
data.Erase(2)
|
||||
|
||||
assert.Equal(t, 4, data.Size())
|
||||
assert.True(t, data.Contains(4))
|
||||
assert.True(t, data.Contains(12))
|
||||
assert.False(t, data.Contains(2))
|
||||
assert.False(t, data.Contains(14))
|
||||
|
||||
keys = nil
|
||||
expectedKeys = []int{4, 5, 10, 12}
|
||||
data.ForEach(func(key, _ int) {
|
||||
keys = append(keys, key)
|
||||
})
|
||||
|
||||
assert.True(t, reflect.DeepEqual(expectedKeys, keys))
|
||||
}
|
||||
86
homework/slices_and_arrays/homework_test.go
Normal file
86
homework/slices_and_arrays/homework_test.go
Normal file
@ -0,0 +1,86 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
// go test -v homework_test.go
|
||||
|
||||
type CircularQueue struct {
|
||||
values []int
|
||||
// need to implement
|
||||
}
|
||||
|
||||
func NewCircularQueue(size int) CircularQueue {
|
||||
return CircularQueue{} // need to implement
|
||||
}
|
||||
|
||||
func (q *CircularQueue) Push(value int) bool {
|
||||
return false // need to implement
|
||||
}
|
||||
|
||||
func (q *CircularQueue) Pop() bool {
|
||||
return false // need to implement
|
||||
}
|
||||
|
||||
func (q *CircularQueue) Front() int {
|
||||
return -1 // need to implement
|
||||
}
|
||||
|
||||
func (q *CircularQueue) Back() int {
|
||||
return -1 // need to implement
|
||||
}
|
||||
|
||||
func (q *CircularQueue) Empty() bool {
|
||||
return false // need to implement
|
||||
}
|
||||
|
||||
func (q *CircularQueue) Full() bool {
|
||||
return false // need to implement
|
||||
}
|
||||
|
||||
func TestCircularQueue(t *testing.T) {
|
||||
const queueSize = 3
|
||||
queue := NewCircularQueue(queueSize)
|
||||
|
||||
assert.True(t, queue.Empty())
|
||||
assert.False(t, queue.Full())
|
||||
|
||||
assert.Equal(t, -1, queue.Front())
|
||||
assert.Equal(t, -1, queue.Back())
|
||||
assert.False(t, queue.Pop())
|
||||
|
||||
assert.True(t, queue.Push(1))
|
||||
assert.True(t, queue.Push(2))
|
||||
assert.True(t, queue.Push(3))
|
||||
assert.False(t, queue.Push(4))
|
||||
|
||||
assert.True(t, reflect.DeepEqual([]int{1, 2, 3}, queue.values))
|
||||
|
||||
assert.False(t, queue.Empty())
|
||||
assert.True(t, queue.Full())
|
||||
|
||||
assert.Equal(t, 1, queue.Front())
|
||||
assert.Equal(t, 3, queue.Back())
|
||||
|
||||
assert.True(t, queue.Pop())
|
||||
assert.False(t, queue.Empty())
|
||||
assert.False(t, queue.Full())
|
||||
assert.True(t, queue.Push(4))
|
||||
|
||||
assert.True(t, reflect.DeepEqual([]int{4, 2, 3}, queue.values))
|
||||
|
||||
assert.Equal(t, 2, queue.Front())
|
||||
assert.Equal(t, 4, queue.Back())
|
||||
|
||||
assert.True(t, queue.Pop())
|
||||
assert.True(t, queue.Pop())
|
||||
assert.True(t, queue.Pop())
|
||||
assert.False(t, queue.Pop())
|
||||
|
||||
assert.True(t, queue.Empty())
|
||||
assert.False(t, queue.Full())
|
||||
}
|
||||
74
homework/strings/homework_test.go
Normal file
74
homework/strings/homework_test.go
Normal file
@ -0,0 +1,74 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
"unsafe"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
type COWBuffer struct {
|
||||
data []byte
|
||||
refs *int
|
||||
// need to implement
|
||||
}
|
||||
|
||||
func NewCOWBuffer(data []byte) COWBuffer {
|
||||
return COWBuffer{} // need to implement
|
||||
}
|
||||
|
||||
func (b *COWBuffer) Clone() COWBuffer {
|
||||
return COWBuffer{} // need to implement
|
||||
}
|
||||
|
||||
func (b *COWBuffer) Close() {
|
||||
// need to implement
|
||||
}
|
||||
|
||||
func (b *COWBuffer) Update(index int, value byte) bool {
|
||||
return false // need to implement
|
||||
}
|
||||
|
||||
func (b *COWBuffer) String() string {
|
||||
return "" // need to implement
|
||||
}
|
||||
|
||||
func TestCOWBuffer(t *testing.T) {
|
||||
data := []byte{'a', 'b', 'c', 'd'}
|
||||
buffer := NewCOWBuffer(data)
|
||||
defer buffer.Close()
|
||||
|
||||
copy1 := buffer.Clone()
|
||||
copy2 := buffer.Clone()
|
||||
|
||||
assert.Equal(t, unsafe.SliceData(data), unsafe.SliceData(buffer.data))
|
||||
assert.Equal(t, unsafe.SliceData(buffer.data), unsafe.SliceData(copy1.data))
|
||||
assert.Equal(t, unsafe.SliceData(copy1.data), unsafe.SliceData(copy2.data))
|
||||
|
||||
assert.True(t, (*byte)(unsafe.SliceData(data)) == unsafe.StringData(buffer.String()))
|
||||
assert.True(t, (*byte)(unsafe.StringData(buffer.String())) == unsafe.StringData(copy1.String()))
|
||||
assert.True(t, (*byte)(unsafe.StringData(copy1.String())) == unsafe.StringData(copy2.String()))
|
||||
|
||||
assert.True(t, buffer.Update(0, 'g'))
|
||||
assert.False(t, buffer.Update(-1, 'g'))
|
||||
assert.False(t, buffer.Update(4, 'g'))
|
||||
|
||||
assert.True(t, reflect.DeepEqual([]byte{'g', 'b', 'c', 'd'}, buffer.data))
|
||||
assert.True(t, reflect.DeepEqual([]byte{'a', 'b', 'c', 'd'}, copy1.data))
|
||||
assert.True(t, reflect.DeepEqual([]byte{'a', 'b', 'c', 'd'}, copy2.data))
|
||||
|
||||
assert.NotEqual(t, unsafe.SliceData(buffer.data), unsafe.SliceData(copy1.data))
|
||||
assert.Equal(t, unsafe.SliceData(copy1.data), unsafe.SliceData(copy2.data))
|
||||
|
||||
copy1.Close()
|
||||
|
||||
previous := copy2.data
|
||||
copy2.Update(0, 'f')
|
||||
current := copy2.data
|
||||
|
||||
// 1 reference - don't need to copy buffer during update
|
||||
assert.Equal(t, unsafe.SliceData(previous), unsafe.SliceData(current))
|
||||
|
||||
copy2.Close()
|
||||
}
|
||||
226
homework/structs/homework_test.go
Normal file
226
homework/structs/homework_test.go
Normal file
@ -0,0 +1,226 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"math"
|
||||
"testing"
|
||||
"unsafe"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
type Option func(*GamePerson)
|
||||
|
||||
func WithName(name string) func(*GamePerson) {
|
||||
return func(person *GamePerson) {
|
||||
// need to implement
|
||||
}
|
||||
}
|
||||
|
||||
func WithCoordinates(x, y, z int) func(*GamePerson) {
|
||||
return func(person *GamePerson) {
|
||||
// need to implement
|
||||
}
|
||||
}
|
||||
|
||||
func WithGold(gold int) func(*GamePerson) {
|
||||
return func(person *GamePerson) {
|
||||
// need to implement
|
||||
}
|
||||
}
|
||||
|
||||
func WithMana(mana int) func(*GamePerson) {
|
||||
return func(person *GamePerson) {
|
||||
// need to implement
|
||||
}
|
||||
}
|
||||
|
||||
func WithHealth(health int) func(*GamePerson) {
|
||||
return func(person *GamePerson) {
|
||||
// need to implement
|
||||
}
|
||||
}
|
||||
|
||||
func WithRespect(respect int) func(*GamePerson) {
|
||||
return func(person *GamePerson) {
|
||||
// need to implement
|
||||
}
|
||||
}
|
||||
|
||||
func WithStrength(strength int) func(*GamePerson) {
|
||||
return func(person *GamePerson) {
|
||||
// need to implement
|
||||
}
|
||||
}
|
||||
|
||||
func WithExperience(experience int) func(*GamePerson) {
|
||||
return func(person *GamePerson) {
|
||||
// need to implement
|
||||
}
|
||||
}
|
||||
|
||||
func WithLevel(level int) func(*GamePerson) {
|
||||
return func(person *GamePerson) {
|
||||
// need to implement
|
||||
}
|
||||
}
|
||||
|
||||
func WithHouse() func(*GamePerson) {
|
||||
return func(person *GamePerson) {
|
||||
// need to implement
|
||||
}
|
||||
}
|
||||
|
||||
func WithGun() func(*GamePerson) {
|
||||
return func(person *GamePerson) {
|
||||
// need to implement
|
||||
}
|
||||
}
|
||||
|
||||
func WithFamily() func(*GamePerson) {
|
||||
return func(person *GamePerson) {
|
||||
// need to implement
|
||||
}
|
||||
}
|
||||
|
||||
func WithType(personType int) func(*GamePerson) {
|
||||
return func(person *GamePerson) {
|
||||
// need to implement
|
||||
}
|
||||
}
|
||||
|
||||
const (
|
||||
BuilderGamePersonType = iota
|
||||
BlacksmithGamePersonType
|
||||
WarriorGamePersonType
|
||||
)
|
||||
|
||||
type GamePerson struct {
|
||||
// need to implement
|
||||
}
|
||||
|
||||
func NewGamePerson(options ...Option) GamePerson {
|
||||
// need to implement
|
||||
return GamePerson{}
|
||||
}
|
||||
|
||||
func (p *GamePerson) Name() string {
|
||||
// need to implement
|
||||
return ""
|
||||
}
|
||||
|
||||
func (p *GamePerson) X() int {
|
||||
// need to implement
|
||||
return 0
|
||||
}
|
||||
|
||||
func (p *GamePerson) Y() int {
|
||||
// need to implement
|
||||
return 0
|
||||
}
|
||||
|
||||
func (p *GamePerson) Z() int {
|
||||
// need to implement
|
||||
return 0
|
||||
}
|
||||
|
||||
func (p *GamePerson) Gold() int {
|
||||
// need to implement
|
||||
return 0
|
||||
}
|
||||
|
||||
func (p *GamePerson) Mana() int {
|
||||
// need to implement
|
||||
return 0
|
||||
}
|
||||
|
||||
func (p *GamePerson) Health() int {
|
||||
// need to implement
|
||||
return 0
|
||||
}
|
||||
|
||||
func (p *GamePerson) Respect() int {
|
||||
// need to implement
|
||||
return 0
|
||||
}
|
||||
|
||||
func (p *GamePerson) Strength() int {
|
||||
// need to implement
|
||||
return 0
|
||||
}
|
||||
|
||||
func (p *GamePerson) Experience() int {
|
||||
// need to implement
|
||||
return 0
|
||||
}
|
||||
|
||||
func (p *GamePerson) Level() int {
|
||||
// need to implement
|
||||
return 0
|
||||
}
|
||||
|
||||
func (p *GamePerson) HasHouse() bool {
|
||||
// need to implement
|
||||
return false
|
||||
}
|
||||
|
||||
func (p *GamePerson) HasGun() bool {
|
||||
// need to implement
|
||||
return false
|
||||
}
|
||||
|
||||
func (p *GamePerson) HasFamilty() bool {
|
||||
// need to implement
|
||||
return false
|
||||
}
|
||||
|
||||
func (p *GamePerson) Type() int {
|
||||
// need to implement
|
||||
return 0
|
||||
}
|
||||
|
||||
func TestGamePerson(t *testing.T) {
|
||||
assert.LessOrEqual(t, unsafe.Sizeof(GamePerson{}), uintptr(64))
|
||||
|
||||
const x, y, z = math.MinInt32, math.MaxInt32, 0
|
||||
const name = "aaaaaaaaaaaaa_bbbbbbbbbbbbb_cccccccccccccc"
|
||||
const personType = BuilderGamePersonType
|
||||
const gold = math.MaxInt32
|
||||
const mana = 1000
|
||||
const health = 1000
|
||||
const respect = 10
|
||||
const strength = 10
|
||||
const experience = 10
|
||||
const level = 10
|
||||
|
||||
options := []Option{
|
||||
WithName(name),
|
||||
WithCoordinates(x, y, z),
|
||||
WithGold(gold),
|
||||
WithMana(mana),
|
||||
WithHealth(health),
|
||||
WithRespect(respect),
|
||||
WithStrength(strength),
|
||||
WithExperience(experience),
|
||||
WithLevel(level),
|
||||
WithHouse(),
|
||||
WithFamily(),
|
||||
WithType(personType),
|
||||
}
|
||||
|
||||
person := NewGamePerson(options...)
|
||||
assert.Equal(t, name, person.Name())
|
||||
assert.Equal(t, x, person.X())
|
||||
assert.Equal(t, y, person.Y())
|
||||
assert.Equal(t, z, person.Z())
|
||||
assert.Equal(t, gold, person.Gold())
|
||||
assert.Equal(t, mana, person.Mana())
|
||||
assert.Equal(t, health, person.Health())
|
||||
assert.Equal(t, respect, person.Respect())
|
||||
assert.Equal(t, strength, person.Strength())
|
||||
assert.Equal(t, experience, person.Experience())
|
||||
assert.Equal(t, level, person.Level())
|
||||
assert.True(t, person.HasHouse())
|
||||
assert.True(t, person.HasFamilty())
|
||||
assert.False(t, person.HasGun())
|
||||
assert.Equal(t, personType, person.Type())
|
||||
}
|
||||
123
homework/sync_primitives/homework_test.go
Normal file
123
homework/sync_primitives/homework_test.go
Normal file
@ -0,0 +1,123 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
type RWMutex struct {
|
||||
// need to implement
|
||||
}
|
||||
|
||||
func (m *RWMutex) Lock() {
|
||||
// need to implement
|
||||
}
|
||||
|
||||
func (m *RWMutex) Unlock() {
|
||||
// need to implement
|
||||
}
|
||||
|
||||
func (m *RWMutex) RLock() {
|
||||
// need to implement
|
||||
|
||||
}
|
||||
|
||||
func (m *RWMutex) RUnlock() {
|
||||
// need to implement
|
||||
}
|
||||
|
||||
func TestRWMutexWithWriter(t *testing.T) {
|
||||
var mutex RWMutex
|
||||
mutex.Lock() // writer
|
||||
|
||||
var mutualExlusionWithWriter atomic.Bool
|
||||
mutualExlusionWithWriter.Store(true)
|
||||
var mutualExlusionWithReader atomic.Bool
|
||||
mutualExlusionWithReader.Store(true)
|
||||
|
||||
go func() {
|
||||
mutex.Lock() // another writer
|
||||
mutualExlusionWithWriter.Store(false)
|
||||
}()
|
||||
|
||||
go func() {
|
||||
mutex.RLock() // another reader
|
||||
mutualExlusionWithReader.Store(false)
|
||||
}()
|
||||
|
||||
time.Sleep(time.Second)
|
||||
assert.True(t, mutualExlusionWithWriter.Load())
|
||||
assert.True(t, mutualExlusionWithReader.Load())
|
||||
}
|
||||
|
||||
func TestRWMutexWithReaders(t *testing.T) {
|
||||
var mutex RWMutex
|
||||
mutex.RLock() // reader
|
||||
|
||||
var mutualExlusionWithWriter atomic.Bool
|
||||
mutualExlusionWithWriter.Store(true)
|
||||
|
||||
go func() {
|
||||
mutex.Lock() // another writer
|
||||
mutualExlusionWithWriter.Store(false)
|
||||
}()
|
||||
|
||||
time.Sleep(time.Second)
|
||||
assert.True(t, mutualExlusionWithWriter.Load())
|
||||
}
|
||||
|
||||
func TestRWMutexMultipleReaders(t *testing.T) {
|
||||
var mutex RWMutex
|
||||
mutex.RLock() // reader
|
||||
|
||||
var readersCount atomic.Int32
|
||||
readersCount.Add(1)
|
||||
|
||||
go func() {
|
||||
mutex.RLock() // another reader
|
||||
readersCount.Add(1)
|
||||
}()
|
||||
|
||||
go func() {
|
||||
mutex.RLock() // another reader
|
||||
readersCount.Add(1)
|
||||
}()
|
||||
|
||||
time.Sleep(time.Second)
|
||||
assert.Equal(t, int32(3), readersCount.Load())
|
||||
}
|
||||
|
||||
func TestRWMutexWithWriterPriority(t *testing.T) {
|
||||
var mutex RWMutex
|
||||
mutex.RLock() // reader
|
||||
|
||||
var mutualExlusionWithWriter atomic.Bool
|
||||
mutualExlusionWithWriter.Store(true)
|
||||
var readersCount atomic.Int32
|
||||
readersCount.Add(1)
|
||||
|
||||
go func() {
|
||||
mutex.Lock() // another writer is waiting for reader
|
||||
mutualExlusionWithWriter.Store(false)
|
||||
}()
|
||||
|
||||
time.Sleep(time.Second)
|
||||
|
||||
go func() {
|
||||
mutex.RLock() // another reader is waiting for a higher priority writer
|
||||
readersCount.Add(1)
|
||||
}()
|
||||
|
||||
go func() {
|
||||
mutex.RLock() // another reader is waiting for a higher priority writer
|
||||
readersCount.Add(1)
|
||||
}()
|
||||
|
||||
time.Sleep(time.Second)
|
||||
|
||||
assert.True(t, mutualExlusionWithWriter.Load())
|
||||
assert.Equal(t, int32(1), readersCount.Load())
|
||||
}
|
||||
Reference in New Issue
Block a user