// Copyright 2013 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // This program is processed by the cover command, and then testAll is called. // The test driver in main.go can then compare the coverage statistics with expectation. // The word LINE is replaced by the line number in this file. When the file is executed, // the coverage processing has changed the line numbers, so we can't use runtime.Caller. package main import _ "unsafe" // for go:linkname //go:linkname some_name some_name var some_name int const anything = 1e9 // Just some unlikely value that means "we got here, don't care how often" func testAll() { testSimple() testBlockRun() testIf() testFor() testRange() testSwitch() testTypeSwitch() testSelect1() testSelect2() testPanic() testEmptySwitches() testFunctionLiteral() testGoto() } // The indexes of the counters in testPanic are known to main.go const panicIndex = 3 // This test appears first because the index of its counters is known to main.go func testPanic() { defer func() { recover() }() check(LINE, 1) panic("should not get next line") check(LINE, 0) // this is GoCover.Count[panicIndex] // The next counter is in testSimple and it will be non-zero. // If the panic above does not trigger a counter, the test will fail // because GoCover.Count[panicIndex] will be the one in testSimple. } func testSimple() { check(LINE, 1) } func testIf() { if true { check(LINE, 1) } else { check(LINE, 0) } if false { check(LINE, 0) } else { check(LINE, 1) } for i := 0; i < 3; i++ { if checkVal(LINE, 3, i) <= 2 { check(LINE, 3) } if checkVal(LINE, 3, i) <= 1 { check(LINE, 2) } if checkVal(LINE, 3, i) <= 0 { check(LINE, 1) } } for i := 0; i < 3; i++ { if checkVal(LINE, 3, i) <= 1 { check(LINE, 2) } else { check(LINE, 1) } } for i := 0; i < 3; i++ { if checkVal(LINE, 3, i) <= 0 { check(LINE, 1) } else if checkVal(LINE, 2, i) <= 1 { check(LINE, 1) } else if checkVal(LINE, 1, i) <= 2 { check(LINE, 1) } else if checkVal(LINE, 0, i) <= 3 { check(LINE, 0) } } if func(a, b int) bool { return a < b }(3, 4) { check(LINE, 1) } } func testFor() { for i := 0; i < 10; func() { i++; check(LINE, 10) }() { check(LINE, 10) } } func testRange() { for _, f := range []func(){ func() { check(LINE, 1) }, } { f() check(LINE, 1) } } func testBlockRun() { check(LINE, 1) { check(LINE, 1) } { check(LINE, 1) } check(LINE, 1) { check(LINE, 1) } { check(LINE, 1) } check(LINE, 1) } func testSwitch() { for i := 0; i < 5; func() { i++; check(LINE, 5) }() { goto label2 label1: goto label1 label2: switch i { case 0: check(LINE, 1) case 1: check(LINE, 1) case 2: check(LINE, 1) default: check(LINE, 2) } } } func testTypeSwitch() { var x = []any{1, 2.0, "hi"} for _, v := range x { switch func() { check(LINE, 3) }(); v.(type) { case int: check(LINE, 1) case float64: check(LINE, 1) case string: check(LINE, 1) case complex128: check(LINE, 0) default: check(LINE, 0) } } } func testSelect1() { c := make(chan int) go func() { for i := 0; i < 1000; i++ { c <- i } }() for { select { case <-c: check(LINE, anything) case <-c: check(LINE, anything) default: check(LINE, 1) return } } } func testSelect2() { c1 := make(chan int, 1000) c2 := make(chan int, 1000) for i := 0; i < 1000; i++ { c1 <- i c2 <- i } for { select { case <-c1: check(LINE, 1000) case <-c2: check(LINE, 1000) default: check(LINE, 1) return } } } // Empty control statements created syntax errors. This function // is here just to be sure that those are handled correctly now. func testEmptySwitches() { check(LINE, 1) switch 3 { } check(LINE, 1) switch i := (any)(3).(int); i { } check(LINE, 1) c := make(chan int) go func() { check(LINE, 1) c <- 1 select {} }() <-c check(LINE, 1) } func testFunctionLiteral() { a := func(f func()) error { f() f() return nil } b := func(f func()) bool { f() f() return true } check(LINE, 1) a(func() { check(LINE, 2) }) if err := a(func() { check(LINE, 2) }); err != nil { } switch b(func() { check(LINE, 2) }) { } x := 2 switch x { case func() int { check(LINE, 1); return 1 }(): check(LINE, 0) panic("2=1") case func() int { check(LINE, 1); return 2 }(): check(LINE, 1) case func() int { check(LINE, 0); return 3 }(): check(LINE, 0) panic("2=3") } } func testGoto() { for i := 0; i < 2; i++ { if i == 0 { goto Label } check(LINE, 1) Label: check(LINE, 2) } // Now test that we don't inject empty statements // between a label and a loop. loop: for { check(LINE, 1) break loop } } // This comment didn't appear in generated go code. func haha() { // Needed for cover to add counter increment here. _ = 42 } // Some someFunction. // //go:nosplit func someFunction() { }