Go语言context test源码分析详情

Go语言context test源码分析详情

目录

1.测试例子分析

2.单元测试

1.测试例子分析

example_test.go,展示了With-系列的4个例子

func ExampleWithCancel() {   gen := func(ctx context.Context) <-chan int {     dst := make(chan int)     n := 1     go func() {       for {         select {         case <-ctx.Done():           return // returning not to leak the goroutine         case dst <- n:           n++         }       }     }()     return dst   }   ctx, cancel := context.WithCancel(context.Background())   defer cancel() // cancel when we are finished consuming integers   for n := range gen(ctx) {     fmt.Println(n)     if n == 5 {       break     }   }   // Output:   // 1   // 2   // 3   // 4   // 5 }

结构分析,gen是一个函数,返回值是一个信道, for range channel是有特殊意义的, for会循环从channel读数据,直到channel被close(),不然就是无限循环.

gen内部的协程就是典型的闭包,for range会不断触发读,gen内部的for select 会不断触发写,主协程读5次之后,会结束main函数,会触发defer函数, 也就是取消操作对应的回调,此时done信道会被close,gen内部的协程会正常退出.

这个例子是测试支持取消信号的上下文,取消函数的调用放在了maindefer函数中.

const shortDuration = 1 * time.Millisecond func ExampleWithDeadline() {   d := time.Now().Add(shortDuration)   ctx, cancel := context.WithDeadline(context.Background(), d)   // Even though ctx will be expired, it is good practice to call its   // cancellation function in any case. Failure to do so may keep the   // context and its parent alive longer than necessary.   defer cancel()   select {   case <-time.After(1 * time.Second):     fmt.Println("overslept")   case <-ctx.Done():     fmt.Println(ctx.Err())   }   // Output:   // context deadline exceeded }

deadline的这个例子,在maindefer中也有主动调用取消函数的. 实际上通过打印可以显示deadline是否按预期工作.

func ExampleWithTimeout() {   ctx, cancel := context.WithTimeout(context.Background(), shortDuration)   defer cancel()   select {   case <-time.After(1 * time.Second):     fmt.Println("overslept")   case <-ctx.Done():     fmt.Println(ctx.Err()) // prints "context deadline exceeded"   }   // Output:   // context deadline exceeded }

timeout只是deadline的一种简写.

func ExampleWithValue() {   type favContextKey string   f := func(ctx context.Context, k favContextKey) {     if v := ctx.Value(k); v != nil {       fmt.Println("found value:", v)       return     }     fmt.Println("key not found:", k)   }   k := favContextKey("language")   ctx := context.WithValue(context.Background(), k, "Go")   f(ctx, k)   f(ctx, favContextKey("color"))   // Output:   // found value: Go   // key not found: color }

context.WithValueContext.Value()是存取操作, 取的时候,如果key没找到,会返回nil.

2.单元测试

context_text.go,x_test.go是单元测试, example_test.go是示例,benchmark_test.go是基准测试, net_test.go展示了deadline对net包的支持.

先看单元测试的context_text.go.

type testingT interface {} type otherContext struct {} func quiescent(t testingT) time.Duration {} func XTestBackground(t testingT) {} func XTestTODO(t testingT) {} func XTestWithCancel(t testingT) {} func contains(m map[canceler]struct{}, key canceler) bool {} func XTestParentFinishesChild(t testingT) {} func XTestChildFinishesFirst(t testingT) {} func testDeadline(c Context, name string, t testingT) {} func XTestDeadline(t testingT) {} func XTestTimeout(t testingT) {} func XTestCanceledTimeout(t testingT) {} func XTestValues(t testingT) {} func XTestAllocs(t testingT, testingShort func() bool, testingAllocsPerRun func(int, func()) float64) {} func XTestSimultaneousCancels(t testingT) {} func XTestInterlockedCancels(t testingT) {} func XTestLayersCancel(t testingT) {} func XTestLayersTimeout(t testingT) {} func XTestCancelRemoves(t testingT) {} func XTestWithCancelCanceledParent(t testingT) {} func XTestWithValueChecksKey(t testingT) {} func XTestInvalidDerivedFail(t testingT) {} func recoveredValue(fn func()) (v interface{}) {} func XTestDeadlineExceededSupportsTimeout(t testingT) {} type myCtx struct {} type myDoneCtx struct {} func (d *myDoneCtx) Done() <-chan struct{} {} func XTestCustomContextGoroutines(t testingT) {}

这暴露的大多测试函数的参数类型是testingT接口类型,但这个源文件中没有实现testingT接口的,

func TestBackground(t *testing.T)                      { XTestBackground(t) } func TestTODO(t *testing.T)                            { XTestTODO(t) } func TestWithCancel(t *testing.T)                      { XTestWithCancel(t) } func TestParentFinishesChild(t *testing.T)             { XTestParentFinishesChild(t) } func TestChildFinishesFirst(t *testing.T)              { XTestChildFinishesFirst(t) } func TestDeadline(t *testing.T)                        { XTestDeadline(t) } func TestTimeout(t *testing.T)                         { XTestTimeout(t) } func TestCanceledTimeout(t *testing.T)                 { XTestCanceledTimeout(t) } func TestValues(t *testing.T)                          { XTestValues(t) } func TestAllocs(t *testing.T)                          { XTestAllocs(t, testing.Short, testing.AllocsPerRun) } func TestSimultaneousCancels(t *testing.T)             { XTestSimultaneousCancels(t) } func TestInterlockedCancels(t *testing.T)              { XTestInterlockedCancels(t) } func TestLayersCancel(t *testing.T)                    { XTestLayersCancel(t) } func TestLayersTimeout(t *testing.T)                   { XTestLayersTimeout(t) } func TestCancelRemoves(t *testing.T)                   { XTestCancelRemoves(t) } func TestWithCancelCanceledParent(t *testing.T)        { XTestWithCancelCanceledParent(t) } func TestWithValueChecksKey(t *testing.T)              { XTestWithValueChecksKey(t) } func TestInvalidDerivedFail(t *testing.T)              { XTestInvalidDerivedFail(t) } func TestDeadlineExceededSupportsTimeout(t *testing.T) { XTestDeadlineExceededSupportsTimeout(t) } func TestCustomContextGoroutines(t *testing.T)         { XTestCustomContextGoroutines(t) }

这是x_test.go的内容,直接是用testing.T类型来实现testingT接口.

那先分析一下testing.T对testingT接口的实现.

type T struct {   common   isParallel bool   context    *testContext } func (t *T) Deadline() (deadline time.Time, ok bool) {   deadline = t.context.deadline   return deadline, !deadline.IsZero() }

注意:testing.T.context不是context.Context的实现类型, Deadline()返回了t.context中存储的deadline信息.

testing.T内嵌了testing.common,大部分方法集都来至common:

Error(args ...interface{}) Errorf(format string, args ...interface{}) Fail() FailNow() Failed() bool Fatal(args ...interface{}) Fatalf(format string, args ...interface{}) Helper() Log(args ...interface{}) Logf(format string, args ...interface{}) Name() string Skip(args ...interface{}) SkipNow() Skipf(format string, args ...interface{}) Skipped() bool

Parallel()是由testing.T实现,某个测试用例多次重复执行时, 可启用并发参数.

到此这篇关于Go语言context test源码分析详情的文章就介绍到这了,更多相关Go语言context test源码分析内容请搜索易知道(ezd.cc)以前的文章或继续浏览下面的相关文章希望大家以后多多支持易知道(ezd.cc)!

推荐阅读

    探探语言设置|探探怎么设置语言

    探探语言设置|探探怎么设置语言,,1. 探探怎么设置语言打开探探软件,然后就有消息提示的红点,点开就行了!其实这些软件都是挺简单的操作的,都是

    git设置编码|git语言设置

    git设置编码|git语言设置,,git设置编码点击cap4j搜索从git直接链接上拉代码。git语言设置Git是一个开源的分布式版本控制系统,可以有效、高

    区域语言设置|区域语言设置工具

    区域语言设置|区域语言设置工具,,区域语言设置工具你好,大致的方法如下,可以参考:1、按下键盘的windows 图标,再开始菜单中单击“设置”;出现的

    苹果手机10参数配置详情

    苹果手机10参数配置详情,苹果,手机,本文目录苹果手机10参数配置详情iphone10是什么手机苹果10手机多少钱苹果手机10多少钱iphone10怎么开

    c4d语言设置|c4d汉语设置

    c4d语言设置|c4d汉语设置,,1. c4d汉语设置mac版的C4D是这样的,中文字体是有的,但是是以拼音的形式存在,比如黑体就是ht。中文字体以拼音方式

    电脑宣传语|电脑宣传语言

    电脑宣传语|电脑宣传语言,,1. 电脑宣传语言1.我做好了与你过一辈子的打算,也做好了你随时要走的准备,2.每段青春都会苍老,但我希望记忆里的你

    office语言设置|微软office语言设置

    office语言设置|微软office语言设置,,微软office语言设置一、首先点击桌面左下角“WIN键”。二、弹出选项内点击“所有程序”。三、接着点

    小米设置日语|小米设置日语语言

    小米设置日语|小米设置日语语言,,1. 小米设置日语语言MIUI系统文字目前只支持简体中文、繁体中文、英文、藏文和维吾尔文,不支持日文 2. 小