Skip to content

Commit

Permalink
Merge branch 'refs/heads/develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
GreatDiscovery committed Jun 18, 2024
2 parents 1654157 + 3a61328 commit 43eaae8
Show file tree
Hide file tree
Showing 15 changed files with 757 additions and 21 deletions.
55 changes: 55 additions & 0 deletions test/basic/os/signal_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package main

import (
"context"
"github.com/sirupsen/logrus"
"log"
"os"
"os/signal"
"syscall"
"testing"
)

func handleExitSignals(ctx context.Context, logger *logrus.Entry, cancel context.CancelFunc) {
ch := make(chan os.Signal, 32)
signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM)

for {
select {
case s := <-ch:
logger.WithField("signal", s).Debugf("Caught exit signal")
cancel()
return
case <-ctx.Done():
return
}
}
}

func TestSignal(t *testing.T) {
// 创建一个channel用于接收操作系统发送的信号
sigChan := make(chan os.Signal, 1)
// 监听SIGINT和SIGTERM信号
signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)

// 创建一个channel用于通知程序退出
exitChan := make(chan struct{})

// 启动一个goroutine来处理信号
go func() {
select {
// 阻塞等待信号
case sig := <-sigChan:
// 收到信号后打印日志
log.Printf("Received signal: %v", sig)
// 向exitChan发送消息,通知程序退出
close(exitChan)
}
}()

// 在主goroutine中等待exitChan被关闭,然后退出程序
<-exitChan
log.Println("Shutting down gracefully...")
// 在这里执行任何需要在退出时清理的操作
log.Println("Exiting.")
}
37 changes: 37 additions & 0 deletions test/basic/rand_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package main

import (
"fmt"
"math/rand"
"sync"
"testing"
)

// 测试并发调用rand冲突的概率
func TestRand(t *testing.T) {
counter := make(map[int]int)

wg := sync.WaitGroup{}
var mu sync.Mutex

for i := 0; i < 30; i++ {
wg.Add(1)
go func() {
defer wg.Done()
for i := 0; i < 100000; i++ {
randInt := rand.Int()
mu.Lock()
counter[randInt] = counter[randInt] + 1
mu.Unlock()
}
}()
}
wg.Wait()
for k, v := range counter {
if v > 1 {
fmt.Println(fmt.Sprintf("k=%d, v=%d", k, v))
}
}
fmt.Println("end")

}
33 changes: 27 additions & 6 deletions test/basic/sort_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,31 @@ package main

import (
"fmt"
"math/rand"
"sort"
"strings"
"testing"
"time"
)

func TestSortByFunc(t *testing.T) {
func shuffle(arr []int) {
rand.Seed(time.Now().UnixNano())
rand.Shuffle(len(arr), func(i, j int) {
arr[i], arr[j] = arr[j], arr[i]
})
}

s1 := []string{"xx-1-0", "xx-2-1", "xx-51-0", "xx-51-1", "xx-3-1", "xx-3-0"}
func TestShuffle(t *testing.T) {
arr := []int{1, 2, 3, 4, 5}
fmt.Println("Original array:", arr)

shuffle(arr)
fmt.Println("Shuffled array:", arr)
}

func TestSortByFunc(t *testing.T) {
str1 := "k8redis-jiayun-simba-sh4-1-0-3 k8redis-jiayun-simba-sh4-1-0-2 k8redis-jiayun-simba-sh4-1-1-3 k8redis-jiayun-simba-sh4-1-2-3 k8redis-jiayun-simba-sh4-1-1-2 k8redis-jiayun-simba-sh4-1-2-2"
s1 := strings.Split(str1, " ")
fmt.Println("before sort =", s1)
sortSlice(s1)
fmt.Println("after sort =", s1)
Expand All @@ -25,11 +42,15 @@ func sortSlice(s1 []string) []string {
version2 := split2[len(split2)-2]
if role1 > role2 {
return true
} else if role1 == role2 {
if version1 < version2 {
return true
} else {
return false
}
} else {
return false
}
if version1 < version2 {
return true
}
return false
})
return s1
}
125 changes: 125 additions & 0 deletions test/basic/time_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
package main

import (
"context"
"fmt"
"k8s.io/apimachinery/pkg/util/runtime"
"testing"
"time"
)

func TestTimeFormat(t *testing.T) {
// 获取当前时间
currentTime := time.Now()
// 设置时区
location, _ := time.LoadLocation("Asia/Shanghai")
// 将时间转换为指定时区
currentTime = currentTime.In(location)
// 格式化时间为指定的字符串格式
formattedTime := currentTime.Format("2006-01-02T15:04:05-07:00")

// 输出格式化后的时间字符串
fmt.Println("格式化后的时间字符串:", formattedTime)
}

var count = 0

func TestTicker(t *testing.T) {
background := context.Background()
err := PollUntilContextTimeout(background, time.Second, 20*time.Second, false, printTime())
if err != nil {
fmt.Println(err)
}
}

func printTime() ConditionWithContextFunc {
return func(_ context.Context) (done bool, err error) {
count++
if count > 12 {
return true, nil
} else {
fmt.Println(time.Now())
return false, nil
}
}
}

func PollUntilContextTimeout(ctx context.Context, interval, timeout time.Duration, immediate bool, condition ConditionWithContextFunc) error {
deadlineCtx, deadlineCancel := context.WithTimeout(ctx, timeout)
defer deadlineCancel()
return loopConditionUntilContext(deadlineCtx, interval, immediate, false, condition)
}

// ConditionWithContextFunc returns true if the condition is satisfied, or an error
// if the loop should be aborted.
//
// The caller passes along a context that can be used by the condition function.
type ConditionWithContextFunc func(context.Context) (done bool, err error)

// 多次循环,每次循环后延迟加倍,直到超时
func loopConditionUntilContext(ctx context.Context, initialInterval time.Duration, immediate, sliding bool, condition ConditionWithContextFunc) error {
t := time.NewTimer(initialInterval)
interval := initialInterval
ratio := time.Duration(2)
defer t.Stop()

var timeCh <-chan time.Time
doneCh := ctx.Done()

// if immediate is true the condition is
// guaranteed to be executed at least once,
// if we haven't requested immediate execution, delay once
if immediate {
if ok, err := func() (bool, error) {
defer runtime.HandleCrash()
return condition(ctx)
}(); err != nil || ok {
return err
}
} else {
timeCh = t.C
select {
case <-doneCh:
return ctx.Err()
case <-timeCh:
}
}

for {
// checking ctx.Err() is slightly faster than checking a select
if err := ctx.Err(); err != nil {
return err
}

if !sliding {
interval = interval * ratio
t.Reset(interval)
}
if ok, err := func() (bool, error) {
defer runtime.HandleCrash()
return condition(ctx)
}(); err != nil || ok {
return err
}
if sliding {
interval = interval * ratio
t.Reset(interval)
}

if timeCh == nil {
timeCh = t.C
}

// NOTE: b/c there is no priority selection in golang
// it is possible for this to race, meaning we could
// trigger t.C and doneCh, and t.C select falls through.
// In order to mitigate we re-check doneCh at the beginning
// of every loop to guarantee at-most one extra execution
// of condition.
select {
case <-doneCh:
return ctx.Err()
case <-timeCh:
}
}
}
1 change: 1 addition & 0 deletions test/concurrent/ants_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ func TestAnts(t *testing.T) {
_ = ants.Submit(syncCalculateSum)
}
wg.Wait()

fmt.Printf("running goroutines: %d\n", ants.Running())
fmt.Printf("finish all tasks.\n")

Expand Down
33 changes: 33 additions & 0 deletions test/concurrent/atomic_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package concurrent

import (
"fmt"
"sync"
"sync/atomic"
"testing"
)

func TestAtomic(t *testing.T) {
var a int64 = 0
var b int64 = 0
wg := sync.WaitGroup{}
for i := 0; i < 500; i++ {
wg.Add(1)
go func() {
defer wg.Done()
atomic.AddInt64(&a, 1)
}()
}
wg.Wait()

for i := 0; i < 500; i++ {
wg.Add(1)
go func() {
defer wg.Done()
b = b + 1
}()
}
wg.Wait()
fmt.Println("a=", a)
fmt.Println("b=", b)
}
33 changes: 32 additions & 1 deletion test/concurrent/context_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package concurrent
import (
"context"
"fmt"
"github.com/stretchr/testify/assert"
"sync"
"testing"
"time"
Expand Down Expand Up @@ -57,7 +58,10 @@ func TestWithValue(t *testing.T) {
root := context.Background()
sub := context.WithValue(root, key{}, "key")
s, _ := sub.Value(key{}).(string)
fmt.Printf("s=%s\n", s)
fmt.Printf("sub.s=%s\n", s)
s2 := root.Value(key{})
// context只能从上到下传递value,而不能从下往上传递value
assert.Equal(t, s2, nil)
}

func TestContext(t *testing.T) {
Expand Down Expand Up @@ -109,3 +113,30 @@ func workWithValue(ctx context.Context, name string) {
}
}
}

type Info struct {
Name string
Age int
}

var key = Info{}

func TestWithStruct(t *testing.T) {
root := context.Background()
info := Info{
Name: "gavin",
Age: 0,
}
c1 := context.WithValue(root, key, &info)
PopulateStruct(c1)
fmt.Println(info.Age)
}

func PopulateStruct(ctx context.Context) {
if ctx.Value(key) == nil {
fmt.Println("nil")
return
}
info := ctx.Value(key).(*Info)
info.Age = 10
}
Loading

0 comments on commit 43eaae8

Please sign in to comment.