How to use checkCalls method of main Package

Best Syzkaller code snippet using main.checkCalls

lint.go

Source:lint.go Github

copy

Full Screen

...549 "regexp.MustCompile": CallRule{Arguments: []ArgumentRule{ValidRegexp{argumentRule{idx: 0}}}},550 "regexp.Compile": CallRule{Arguments: []ArgumentRule{ValidRegexp{argumentRule{idx: 0}}}},551}552func (c *Checker) CheckRegexps(f *lint.File) {553 c.checkCalls(f, checkRegexpRules)554}555func (c *Checker) CheckTemplate(f *lint.File) {556 fn := func(node ast.Node) bool {557 call, ok := node.(*ast.CallExpr)558 if !ok {559 return true560 }561 var kind string562 if isFunctionCallName(f, call, "(*text/template.Template).Parse") {563 kind = "text"564 } else if isFunctionCallName(f, call, "(*html/template.Template).Parse") {565 kind = "html"566 } else {567 return true568 }569 sel := call.Fun.(*ast.SelectorExpr)570 if !isFunctionCallName(f, sel.X, "text/template.New") &&571 !isFunctionCallName(f, sel.X, "html/template.New") {572 // TODO(dh): this is a cheap workaround for templates with573 // different delims. A better solution with less false574 // negatives would use data flow analysis to see where the575 // template comes from and where it has been576 return true577 }578 s, ok := constantString(f, call.Args[0])579 if !ok {580 return true581 }582 var err error583 switch kind {584 case "text":585 _, err = texttemplate.New("").Parse(s)586 case "html":587 _, err = htmltemplate.New("").Parse(s)588 }589 if err != nil {590 // TODO(dominikh): whitelist other parse errors, if any591 if strings.Contains(err.Error(), "unexpected") {592 f.Errorf(call.Args[0], "%s", err)593 }594 }595 return true596 }597 f.Walk(fn)598}599var checkTimeParseRules = map[string]CallRule{600 "time.Parse": CallRule{Arguments: []ArgumentRule{ValidTimeLayout{argumentRule: argumentRule{idx: 0}}}},601}602func (c *Checker) CheckTimeParse(f *lint.File) {603 c.checkCalls(f, checkTimeParseRules)604}605var checkEncodingBinaryRules = map[string]CallRule{606 "encoding/binary.Write": CallRule{Arguments: []ArgumentRule{CanBinaryMarshal{argumentRule: argumentRule{idx: 2}}}},607}608func (c *Checker) CheckEncodingBinary(f *lint.File) {609 c.checkCalls(f, checkEncodingBinaryRules)610}611func (c *Checker) CheckTimeSleepConstant(f *lint.File) {612 fn := func(node ast.Node) bool {613 call, ok := node.(*ast.CallExpr)614 if !ok {615 return true616 }617 if !isFunctionCallName(f, call, "time.Sleep") {618 return true619 }620 lit, ok := call.Args[0].(*ast.BasicLit)621 if !ok {622 return true623 }624 n, err := strconv.Atoi(lit.Value)625 if err != nil {626 return true627 }628 if n == 0 || n > 120 {629 // time.Sleep(0) is a seldomly used pattern in concurrency630 // tests. >120 might be intentional. 120 was chosen631 // because the user could've meant 2 minutes.632 return true633 }634 recommendation := "time.Sleep(time.Nanosecond)"635 if n != 1 {636 recommendation = fmt.Sprintf("time.Sleep(%d * time.Nanosecond)", n)637 }638 f.Errorf(call.Args[0], "sleeping for %d nanoseconds is probably a bug. Be explicit if it isn't: %s", n, recommendation)639 return true640 }641 f.Walk(fn)642}643func (c *Checker) CheckWaitgroupAdd(f *lint.File) {644 fn := func(node ast.Node) bool {645 g, ok := node.(*ast.GoStmt)646 if !ok {647 return true648 }649 fun, ok := g.Call.Fun.(*ast.FuncLit)650 if !ok {651 return true652 }653 if len(fun.Body.List) == 0 {654 return true655 }656 stmt, ok := fun.Body.List[0].(*ast.ExprStmt)657 if !ok {658 return true659 }660 call, ok := stmt.X.(*ast.CallExpr)661 if !ok {662 return true663 }664 sel, ok := call.Fun.(*ast.SelectorExpr)665 if !ok {666 return true667 }668 fn, ok := f.Pkg.TypesInfo.ObjectOf(sel.Sel).(*types.Func)669 if !ok {670 return true671 }672 if fn.FullName() == "(*sync.WaitGroup).Add" {673 f.Errorf(sel, "should call %s before starting the goroutine to avoid a race",674 f.Render(stmt))675 }676 return true677 }678 f.Walk(fn)679}680func (c *Checker) CheckInfiniteEmptyLoop(f *lint.File) {681 fn := func(node ast.Node) bool {682 loop, ok := node.(*ast.ForStmt)683 if !ok || len(loop.Body.List) != 0 || loop.Cond != nil || loop.Init != nil {684 return true685 }686 f.Errorf(loop, "should not use an infinite empty loop. It will spin. Consider select{} instead.")687 return true688 }689 f.Walk(fn)690}691func (c *Checker) CheckDeferInInfiniteLoop(f *lint.File) {692 fn := func(node ast.Node) bool {693 mightExit := false694 var defers []ast.Stmt695 loop, ok := node.(*ast.ForStmt)696 if !ok || loop.Cond != nil {697 return true698 }699 fn2 := func(node ast.Node) bool {700 switch stmt := node.(type) {701 case *ast.ReturnStmt:702 mightExit = true703 case *ast.BranchStmt:704 // TODO(dominikh): if this sees a break in a switch or705 // select, it doesn't check if it breaks the loop or706 // just the select/switch. This causes some false707 // negatives.708 if stmt.Tok == token.BREAK {709 mightExit = true710 }711 case *ast.DeferStmt:712 defers = append(defers, stmt)713 case *ast.FuncLit:714 // Don't look into function bodies715 return false716 }717 return true718 }719 ast.Inspect(loop.Body, fn2)720 if mightExit {721 return true722 }723 for _, stmt := range defers {724 f.Errorf(stmt, "defers in this infinite loop will never run")725 }726 return true727 }728 f.Walk(fn)729}730func (c *Checker) CheckDubiousDeferInChannelRangeLoop(f *lint.File) {731 fn := func(node ast.Node) bool {732 loop, ok := node.(*ast.RangeStmt)733 if !ok {734 return true735 }736 typ := f.Pkg.TypesInfo.TypeOf(loop.X)737 _, ok = typ.Underlying().(*types.Chan)738 if !ok {739 return true740 }741 fn2 := func(node ast.Node) bool {742 switch stmt := node.(type) {743 case *ast.DeferStmt:744 f.Errorf(stmt, "defers in this range loop won't run unless the channel gets closed")745 case *ast.FuncLit:746 // Don't look into function bodies747 return false748 }749 return true750 }751 ast.Inspect(loop.Body, fn2)752 return true753 }754 f.Walk(fn)755}756func (c *Checker) CheckTestMainExit(f *lint.File) {757 fn := func(node ast.Node) bool {758 if !IsTestMain(f, node) {759 return true760 }761 arg := f.Pkg.TypesInfo.ObjectOf(node.(*ast.FuncDecl).Type.Params.List[0].Names[0])762 callsRun := false763 fn2 := func(node ast.Node) bool {764 call, ok := node.(*ast.CallExpr)765 if !ok {766 return true767 }768 sel, ok := call.Fun.(*ast.SelectorExpr)769 if !ok {770 return true771 }772 ident, ok := sel.X.(*ast.Ident)773 if !ok {774 return true775 }776 if arg != f.Pkg.TypesInfo.ObjectOf(ident) {777 return true778 }779 if sel.Sel.Name == "Run" {780 callsRun = true781 return false782 }783 return true784 }785 ast.Inspect(node.(*ast.FuncDecl).Body, fn2)786 callsExit := false787 fn3 := func(node ast.Node) bool {788 if isFunctionCallName(f, node, "os.Exit") {789 callsExit = true790 return false791 }792 return true793 }794 ast.Inspect(node.(*ast.FuncDecl).Body, fn3)795 if !callsExit && callsRun {796 f.Errorf(node, "TestMain should call os.Exit to set exit code")797 }798 return true799 }800 f.Walk(fn)801}802func IsTestMain(f *lint.File, node ast.Node) bool {803 decl, ok := node.(*ast.FuncDecl)804 if !ok {805 return false806 }807 if decl.Name.Name != "TestMain" {808 return false809 }810 if len(decl.Type.Params.List) != 1 {811 return false812 }813 arg := decl.Type.Params.List[0]814 if len(arg.Names) != 1 {815 return false816 }817 typ := f.Pkg.TypesInfo.TypeOf(arg.Type)818 return typ != nil && typ.String() == "*testing.M"819}820func (c *Checker) CheckExec(f *lint.File) {821 fn := func(node ast.Node) bool {822 call, ok := node.(*ast.CallExpr)823 if !ok {824 return true825 }826 if !isFunctionCallName(f, call, "os/exec.Command") {827 return true828 }829 val, ok := constantString(f, call.Args[0])830 if !ok {831 return true832 }833 if !strings.Contains(val, " ") || strings.Contains(val, `\`) {834 return true835 }836 f.Errorf(call.Args[0], "first argument to exec.Command looks like a shell command, but a program name or path are expected")837 return true838 }839 f.Walk(fn)840}841func (c *Checker) CheckLoopEmptyDefault(f *lint.File) {842 fn := func(node ast.Node) bool {843 loop, ok := node.(*ast.ForStmt)844 if !ok || len(loop.Body.List) != 1 || loop.Cond != nil || loop.Init != nil {845 return true846 }847 sel, ok := loop.Body.List[0].(*ast.SelectStmt)848 if !ok {849 return true850 }851 for _, c := range sel.Body.List {852 if comm, ok := c.(*ast.CommClause); ok && comm.Comm == nil && len(comm.Body) == 0 {853 f.Errorf(comm, "should not have an empty default case in a for+select loop. The loop will spin.")854 }855 }856 return true857 }858 f.Walk(fn)859}860func (c *Checker) CheckLhsRhsIdentical(f *lint.File) {861 fn := func(node ast.Node) bool {862 op, ok := node.(*ast.BinaryExpr)863 if !ok {864 return true865 }866 switch op.Op {867 case token.EQL, token.NEQ:868 if basic, ok := f.Pkg.TypesInfo.TypeOf(op.X).(*types.Basic); ok {869 if kind := basic.Kind(); kind == types.Float32 || kind == types.Float64 {870 // f == f and f != f might be used to check for NaN871 return true872 }873 }874 case token.SUB, token.QUO, token.AND, token.REM, token.OR, token.XOR, token.AND_NOT,875 token.LAND, token.LOR, token.LSS, token.GTR, token.LEQ, token.GEQ:876 default:877 // For some ops, such as + and *, it can make sense to878 // have identical operands879 return true880 }881 if f.Render(op.X) != f.Render(op.Y) {882 return true883 }884 f.Errorf(op, "identical expressions on the left and right side of the '%s' operator", op.Op)885 return true886 }887 f.Walk(fn)888}889func (c *Checker) CheckScopedBreak(f *lint.File) {890 fn := func(node ast.Node) bool {891 loop, ok := node.(*ast.ForStmt)892 if !ok {893 return true894 }895 for _, stmt := range loop.Body.List {896 var blocks [][]ast.Stmt897 switch stmt := stmt.(type) {898 case *ast.SwitchStmt:899 for _, c := range stmt.Body.List {900 blocks = append(blocks, c.(*ast.CaseClause).Body)901 }902 case *ast.SelectStmt:903 for _, c := range stmt.Body.List {904 blocks = append(blocks, c.(*ast.CommClause).Body)905 }906 default:907 continue908 }909 for _, body := range blocks {910 if len(body) == 0 {911 continue912 }913 lasts := []ast.Stmt{body[len(body)-1]}914 // TODO(dh): unfold all levels of nested block915 // statements, not just a single level if statement916 if ifs, ok := lasts[0].(*ast.IfStmt); ok {917 if len(ifs.Body.List) == 0 {918 continue919 }920 lasts[0] = ifs.Body.List[len(ifs.Body.List)-1]921 if block, ok := ifs.Else.(*ast.BlockStmt); ok {922 if len(block.List) != 0 {923 lasts = append(lasts, block.List[len(block.List)-1])924 }925 }926 }927 for _, last := range lasts {928 branch, ok := last.(*ast.BranchStmt)929 if !ok || branch.Tok != token.BREAK || branch.Label != nil {930 continue931 }932 f.Errorf(branch, "ineffective break statement. Did you mean to break out of the outer loop?")933 }934 }935 }936 return true937 }938 f.Walk(fn)939}940func (c *Checker) CheckUnsafePrintf(f *lint.File) {941 fn := func(node ast.Node) bool {942 call, ok := node.(*ast.CallExpr)943 if !ok {944 return true945 }946 if !isFunctionCallNameAny(f, call, "fmt.Printf", "fmt.Sprintf", "log.Printf") {947 return true948 }949 if len(call.Args) != 1 {950 return true951 }952 switch call.Args[0].(type) {953 case *ast.CallExpr, *ast.Ident:954 default:955 return true956 }957 f.Errorf(call.Args[0], "printf-style function with dynamic first argument and no further arguments should use print-style function instead")958 return true959 }960 f.Walk(fn)961}962var checkURLsRules = map[string]CallRule{963 "net/url.Parse": CallRule{Arguments: []ArgumentRule{ValidURL{argumentRule: argumentRule{idx: 0}}}},964}965func (c *Checker) CheckURLs(f *lint.File) {966 c.checkCalls(f, checkURLsRules)967}968func (c *Checker) CheckEarlyDefer(f *lint.File) {969 fn := func(node ast.Node) bool {970 block, ok := node.(*ast.BlockStmt)971 if !ok {972 return true973 }974 if len(block.List) < 2 {975 return true976 }977 for i, stmt := range block.List {978 if i == len(block.List)-1 {979 break980 }981 assign, ok := stmt.(*ast.AssignStmt)982 if !ok {983 continue984 }985 if len(assign.Rhs) != 1 {986 continue987 }988 if len(assign.Lhs) < 2 {989 continue990 }991 if lhs, ok := assign.Lhs[len(assign.Lhs)-1].(*ast.Ident); ok && lhs.Name == "_" {992 continue993 }994 call, ok := assign.Rhs[0].(*ast.CallExpr)995 if !ok {996 continue997 }998 sig, ok := f.Pkg.TypesInfo.TypeOf(call.Fun).(*types.Signature)999 if !ok {1000 continue1001 }1002 if sig.Results().Len() < 2 {1003 continue1004 }1005 last := sig.Results().At(sig.Results().Len() - 1)1006 // FIXME(dh): check that it's error from universe, not1007 // another type of the same name1008 if last.Type().String() != "error" {1009 continue1010 }1011 lhs, ok := assign.Lhs[0].(*ast.Ident)1012 if !ok {1013 continue1014 }1015 def, ok := block.List[i+1].(*ast.DeferStmt)1016 if !ok {1017 continue1018 }1019 sel, ok := def.Call.Fun.(*ast.SelectorExpr)1020 if !ok {1021 continue1022 }1023 ident, ok := selectorX(sel).(*ast.Ident)1024 if !ok {1025 continue1026 }1027 if ident.Obj != lhs.Obj {1028 continue1029 }1030 if sel.Sel.Name != "Close" {1031 continue1032 }1033 f.Errorf(def, "should check returned error before deferring %s", f.Render(def.Call))1034 }1035 return true1036 }1037 f.Walk(fn)1038}1039func selectorX(sel *ast.SelectorExpr) ast.Node {1040 switch x := sel.X.(type) {1041 case *ast.SelectorExpr:1042 return selectorX(x)1043 default:1044 return x1045 }1046}1047var checkDubiousSyncPoolPointersRules = map[string]CallRule{1048 "(*sync.Pool).Put": CallRule{1049 Arguments: []ArgumentRule{1050 Pointer{1051 argumentRule: argumentRule{1052 idx: 0,1053 Message: "non-pointer type put into sync.Pool",1054 },1055 },1056 },1057 },1058}1059func (c *Checker) CheckDubiousSyncPoolPointers(f *lint.File) {1060 c.checkCalls(f, checkDubiousSyncPoolPointersRules)1061}1062func (c *Checker) CheckEmptyCriticalSection(f *lint.File) {1063 mutexParams := func(s ast.Stmt) (x ast.Expr, funcName string, ok bool) {1064 expr, ok := s.(*ast.ExprStmt)1065 if !ok {1066 return nil, "", false1067 }1068 call, ok := expr.X.(*ast.CallExpr)1069 if !ok {1070 return nil, "", false1071 }1072 sel, ok := call.Fun.(*ast.SelectorExpr)1073 if !ok {1074 return nil, "", false1075 }1076 fn, ok := f.Pkg.TypesInfo.ObjectOf(sel.Sel).(*types.Func)1077 if !ok {1078 return nil, "", false1079 }1080 sig := fn.Type().(*types.Signature)1081 if sig.Params().Len() != 0 || sig.Results().Len() != 0 {1082 return nil, "", false1083 }1084 return sel.X, fn.Name(), true1085 }1086 fn := func(node ast.Node) bool {1087 block, ok := node.(*ast.BlockStmt)1088 if !ok {1089 return true1090 }1091 if len(block.List) < 2 {1092 return true1093 }1094 for i := range block.List[:len(block.List)-1] {1095 sel1, method1, ok1 := mutexParams(block.List[i])1096 sel2, method2, ok2 := mutexParams(block.List[i+1])1097 if !ok1 || !ok2 || f.Render(sel1) != f.Render(sel2) {1098 continue1099 }1100 if (method1 == "Lock" && method2 == "Unlock") ||1101 (method1 == "RLock" && method2 == "RUnlock") {1102 f.Errorf(block.List[i+1], "empty critical section")1103 }1104 }1105 return true1106 }1107 f.Walk(fn)1108}1109func (c *Checker) CheckIneffectiveCopy(f *lint.File) {1110 fn := func(node ast.Node) bool {1111 if unary, ok := node.(*ast.UnaryExpr); ok {1112 if _, ok := unary.X.(*ast.StarExpr); ok && unary.Op == token.AND {1113 f.Errorf(unary, "&*x will be simplified to x. It will not copy x.")1114 }1115 }1116 if star, ok := node.(*ast.StarExpr); ok {1117 if unary, ok := star.X.(*ast.UnaryExpr); ok && unary.Op == token.AND {1118 f.Errorf(star, "*&x will be simplified to x. It will not copy x.")1119 }1120 }1121 return true1122 }1123 f.Walk(fn)1124}1125func (c *Checker) CheckDiffSizeComparison(f *lint.File) {1126 for _, ssafn := range c.funcsForFile(f) {1127 for _, b := range ssafn.Blocks {1128 for _, ins := range b.Instrs {1129 binop, ok := ins.(*ssa.BinOp)1130 if !ok {1131 continue1132 }1133 if binop.Op != token.EQL && binop.Op != token.NEQ {1134 continue1135 }1136 _, ok1 := binop.X.(*ssa.Slice)1137 _, ok2 := binop.Y.(*ssa.Slice)1138 if !ok1 && !ok2 {1139 continue1140 }1141 r := c.funcDescs.Get(ssafn).Ranges1142 r1, ok1 := r.Get(binop.X).(vrp.StringInterval)1143 r2, ok2 := r.Get(binop.Y).(vrp.StringInterval)1144 if !ok1 || !ok2 {1145 continue1146 }1147 if r1.Length.Intersection(r2.Length).Empty() {1148 f.Errorf(binop, "comparing strings of different sizes for equality will always return false")1149 }1150 }1151 }1152 }1153}1154func (c *Checker) CheckCanonicalHeaderKey(f *lint.File) {1155 fn := func(node ast.Node) bool {1156 assign, ok := node.(*ast.AssignStmt)1157 if ok {1158 // TODO(dh): This risks missing some Header reads, for1159 // example in `h1["foo"] = h2["foo"]` – these edge1160 // cases are probably rare enough to ignore for now.1161 for _, expr := range assign.Lhs {1162 op, ok := expr.(*ast.IndexExpr)1163 if !ok {1164 continue1165 }1166 if hasType(f, op.X, "net/http.Header") {1167 return false1168 }1169 }1170 return true1171 }1172 op, ok := node.(*ast.IndexExpr)1173 if !ok {1174 return true1175 }1176 if !hasType(f, op.X, "net/http.Header") {1177 return true1178 }1179 s, ok := constantString(f, op.Index)1180 if !ok {1181 return true1182 }1183 if s == http.CanonicalHeaderKey(s) {1184 return true1185 }1186 f.Errorf(op, "keys in http.Header are canonicalized, %q is not canonical; fix the constant or use http.CanonicalHeaderKey", s)1187 return true1188 }1189 f.Walk(fn)1190}1191func (c *Checker) CheckBenchmarkN(f *lint.File) {1192 fn := func(node ast.Node) bool {1193 assign, ok := node.(*ast.AssignStmt)1194 if !ok {1195 return true1196 }1197 if len(assign.Lhs) != 1 || len(assign.Rhs) != 1 {1198 return true1199 }1200 sel, ok := assign.Lhs[0].(*ast.SelectorExpr)1201 if !ok {1202 return true1203 }1204 if sel.Sel.Name != "N" {1205 return true1206 }1207 if !hasType(f, sel.X, "*testing.B") {1208 return true1209 }1210 f.Errorf(assign, "should not assign to %s", f.Render(sel))1211 return true1212 }1213 f.Walk(fn)1214}1215func (c *Checker) CheckIneffecitiveFieldAssignments(f *lint.File) {1216 for _, ssafn := range c.funcsForFile(f) {1217 if f.Fset.File(f.File.Pos()) != f.Fset.File(ssafn.Pos()) {1218 continue1219 }1220 if ssafn.Signature.Recv() == nil {1221 continue1222 }1223 if len(ssafn.Blocks) == 0 {1224 // External function1225 continue1226 }1227 reads := map[*ssa.BasicBlock]map[ssa.Value]bool{}1228 writes := map[*ssa.BasicBlock]map[ssa.Value]bool{}1229 recv := ssafn.Params[0]1230 if _, ok := recv.Type().Underlying().(*types.Struct); !ok {1231 continue1232 }1233 recvPtrs := map[ssa.Value]bool{1234 recv: true,1235 }1236 if len(ssafn.Locals) == 0 || ssafn.Locals[0].Heap {1237 continue1238 }1239 blocks := ssafn.DomPreorder()1240 for _, block := range blocks {1241 if writes[block] == nil {1242 writes[block] = map[ssa.Value]bool{}1243 }1244 if reads[block] == nil {1245 reads[block] = map[ssa.Value]bool{}1246 }1247 for _, ins := range block.Instrs {1248 switch ins := ins.(type) {1249 case *ssa.Store:1250 if recvPtrs[ins.Val] {1251 recvPtrs[ins.Addr] = true1252 }1253 fa, ok := ins.Addr.(*ssa.FieldAddr)1254 if !ok {1255 continue1256 }1257 if !recvPtrs[fa.X] {1258 continue1259 }1260 writes[block][fa] = true1261 case *ssa.UnOp:1262 if ins.Op != token.MUL {1263 continue1264 }1265 if recvPtrs[ins.X] {1266 reads[block][ins] = true1267 continue1268 }1269 fa, ok := ins.X.(*ssa.FieldAddr)1270 if !ok {1271 continue1272 }1273 if !recvPtrs[fa.X] {1274 continue1275 }1276 reads[block][fa] = true1277 }1278 }1279 }1280 for block, writes := range writes {1281 seen := map[*ssa.BasicBlock]bool{}1282 var hasRead func(block *ssa.BasicBlock, write *ssa.FieldAddr) bool1283 hasRead = func(block *ssa.BasicBlock, write *ssa.FieldAddr) bool {1284 seen[block] = true1285 for read := range reads[block] {1286 switch ins := read.(type) {1287 case *ssa.FieldAddr:1288 if ins.Field == write.Field && read.Pos() > write.Pos() {1289 return true1290 }1291 case *ssa.UnOp:1292 if ins.Pos() >= write.Pos() {1293 return true1294 }1295 }1296 }1297 for _, succ := range block.Succs {1298 if !seen[succ] {1299 if hasRead(succ, write) {1300 return true1301 }1302 }1303 }1304 return false1305 }1306 for write := range writes {1307 fa := write.(*ssa.FieldAddr)1308 if !hasRead(block, fa) {1309 name := recv.Type().Underlying().(*types.Struct).Field(fa.Field).Name()1310 f.Errorf(fa, "ineffective assignment to field %s", name)1311 }1312 }1313 }1314 }1315}1316func (c *Checker) CheckUnreadVariableValues(f *lint.File) {1317 fn := func(node ast.Node) bool {1318 fn, ok := node.(*ast.FuncDecl)1319 if !ok {1320 return true1321 }1322 ssafn := c.nodeFns[fn]1323 if ssafn == nil {1324 return true1325 }1326 ast.Inspect(fn, func(node ast.Node) bool {1327 assign, ok := node.(*ast.AssignStmt)1328 if !ok {1329 return true1330 }1331 if len(assign.Lhs) != len(assign.Rhs) {1332 return true1333 }1334 for i, lhs := range assign.Lhs {1335 rhs := assign.Rhs[i]1336 if ident, ok := lhs.(*ast.Ident); !ok || ok && ident.Name == "_" {1337 continue1338 }1339 val, _ := ssafn.ValueForExpr(rhs)1340 if val == nil {1341 continue1342 }1343 refs := val.Referrers()1344 if refs == nil {1345 // TODO investigate why refs can be nil1346 return true1347 }1348 if len(filterDebug(*val.Referrers())) == 0 {1349 f.Errorf(node, "this value of %s is never used", lhs)1350 }1351 }1352 return true1353 })1354 return true1355 }1356 f.Walk(fn)1357}1358func (c *Checker) CheckPredeterminedBooleanExprs(f *lint.File) {1359 for _, ssafn := range c.funcsForFile(f) {1360 for _, block := range ssafn.Blocks {1361 for _, ins := range block.Instrs {1362 ssabinop, ok := ins.(*ssa.BinOp)1363 if !ok {1364 continue1365 }1366 switch ssabinop.Op {1367 case token.GTR, token.LSS, token.EQL, token.NEQ, token.LEQ, token.GEQ:1368 default:1369 continue1370 }1371 xs, ok1 := consts(ssabinop.X, nil, nil)1372 ys, ok2 := consts(ssabinop.Y, nil, nil)1373 if !ok1 || !ok2 || len(xs) == 0 || len(ys) == 0 {1374 continue1375 }1376 trues := 01377 for _, x := range xs {1378 for _, y := range ys {1379 if x.Value == nil {1380 if y.Value == nil {1381 trues++1382 }1383 continue1384 }1385 if constant.Compare(x.Value, ssabinop.Op, y.Value) {1386 trues++1387 }1388 }1389 }1390 b := trues != 01391 if trues == 0 || trues == len(xs)*len(ys) {1392 f.Errorf(ssabinop, "binary expression is always %t for all possible values (%s %s %s)",1393 b, xs, ssabinop.Op, ys)1394 }1395 }1396 }1397 }1398}1399func (c *Checker) CheckNilMaps(f *lint.File) {1400 for _, ssafn := range c.funcsForFile(f) {1401 for _, block := range ssafn.Blocks {1402 for _, ins := range block.Instrs {1403 mu, ok := ins.(*ssa.MapUpdate)1404 if !ok {1405 continue1406 }1407 c, ok := mu.Map.(*ssa.Const)1408 if !ok {1409 continue1410 }1411 if c.Value != nil {1412 continue1413 }1414 f.Errorf(mu, "assignment to nil map")1415 }1416 }1417 }1418}1419func (c *Checker) CheckUnsignedComparison(f *lint.File) {1420 fn := func(node ast.Node) bool {1421 expr, ok := node.(*ast.BinaryExpr)1422 if !ok {1423 return true1424 }1425 tx := f.Pkg.TypesInfo.TypeOf(expr.X)1426 basic, ok := tx.Underlying().(*types.Basic)1427 if !ok {1428 return true1429 }1430 if (basic.Info() & types.IsUnsigned) == 0 {1431 return true1432 }1433 lit, ok := expr.Y.(*ast.BasicLit)1434 if !ok || lit.Value != "0" {1435 return true1436 }1437 switch expr.Op {1438 case token.GEQ:1439 f.Errorf(expr, "unsigned values are always >= 0")1440 case token.LSS:1441 f.Errorf(expr, "unsigned values are never < 0")1442 case token.LEQ:1443 f.Errorf(expr, "'x <= 0' for unsigned values of x is the same as 'x == 0'")1444 }1445 return true1446 }1447 f.Walk(fn)1448}1449func filterDebug(instr []ssa.Instruction) []ssa.Instruction {1450 var out []ssa.Instruction1451 for _, ins := range instr {1452 if _, ok := ins.(*ssa.DebugRef); !ok {1453 out = append(out, ins)1454 }1455 }1456 return out1457}1458func consts(val ssa.Value, out []*ssa.Const, visitedPhis map[string]bool) ([]*ssa.Const, bool) {1459 if visitedPhis == nil {1460 visitedPhis = map[string]bool{}1461 }1462 var ok bool1463 switch val := val.(type) {1464 case *ssa.Phi:1465 if visitedPhis[val.Name()] {1466 break1467 }1468 visitedPhis[val.Name()] = true1469 vals := val.Operands(nil)1470 for _, phival := range vals {1471 out, ok = consts(*phival, out, visitedPhis)1472 if !ok {1473 return nil, false1474 }1475 }1476 case *ssa.Const:1477 out = append(out, val)1478 case *ssa.Convert:1479 out, ok = consts(val.X, out, visitedPhis)1480 if !ok {1481 return nil, false1482 }1483 default:1484 return nil, false1485 }1486 if len(out) < 2 {1487 return out, true1488 }1489 uniq := []*ssa.Const{out[0]}1490 for _, val := range out[1:] {1491 if val.Value == uniq[len(uniq)-1].Value {1492 continue1493 }1494 uniq = append(uniq, val)1495 }1496 return uniq, true1497}1498func (c *Checker) CheckLoopCondition(f *lint.File) {1499 fn := func(node ast.Node) bool {1500 loop, ok := node.(*ast.ForStmt)1501 if !ok {1502 return true1503 }1504 if loop.Init == nil || loop.Cond == nil || loop.Post == nil {1505 return true1506 }1507 init, ok := loop.Init.(*ast.AssignStmt)1508 if !ok || len(init.Lhs) != 1 || len(init.Rhs) != 1 {1509 return true1510 }1511 cond, ok := loop.Cond.(*ast.BinaryExpr)1512 if !ok {1513 return true1514 }1515 x, ok := cond.X.(*ast.Ident)1516 if !ok {1517 return true1518 }1519 lhs, ok := init.Lhs[0].(*ast.Ident)1520 if !ok {1521 return true1522 }1523 if x.Obj != lhs.Obj {1524 return true1525 }1526 if _, ok := loop.Post.(*ast.IncDecStmt); !ok {1527 return true1528 }1529 ssafn := f.EnclosingSSAFunction(cond)1530 if ssafn == nil {1531 return true1532 }1533 v, isAddr := ssafn.ValueForExpr(cond.X)1534 if v == nil || isAddr {1535 return true1536 }1537 switch v := v.(type) {1538 case *ssa.Phi:1539 ops := v.Operands(nil)1540 if len(ops) != 2 {1541 return true1542 }1543 _, ok := (*ops[0]).(*ssa.Const)1544 if !ok {1545 return true1546 }1547 sigma, ok := (*ops[1]).(*ssa.Sigma)1548 if !ok {1549 return true1550 }1551 if sigma.X != v {1552 return true1553 }1554 case *ssa.UnOp:1555 return true1556 }1557 f.Errorf(cond, "variable in loop condition never changes")1558 return true1559 }1560 f.Walk(fn)1561}1562func (c *Checker) CheckArgOverwritten(f *lint.File) {1563 fn := func(node ast.Node) bool {1564 fn, ok := node.(*ast.FuncDecl)1565 if !ok {1566 return true1567 }1568 if fn.Body == nil {1569 return true1570 }1571 ssafn := c.nodeFns[fn]1572 if ssafn == nil {1573 return true1574 }1575 if len(fn.Type.Params.List) == 0 {1576 return true1577 }1578 for _, field := range fn.Type.Params.List {1579 for _, arg := range field.Names {1580 obj := f.Pkg.TypesInfo.ObjectOf(arg)1581 var ssaobj *ssa.Parameter1582 for _, param := range ssafn.Params {1583 if param.Object() == obj {1584 ssaobj = param1585 break1586 }1587 }1588 if ssaobj == nil {1589 continue1590 }1591 refs := ssaobj.Referrers()1592 if refs == nil {1593 continue1594 }1595 if len(filterDebug(*refs)) != 0 {1596 continue1597 }1598 assigned := false1599 ast.Inspect(fn.Body, func(node ast.Node) bool {1600 assign, ok := node.(*ast.AssignStmt)1601 if !ok {1602 return true1603 }1604 for _, lhs := range assign.Lhs {1605 ident, ok := lhs.(*ast.Ident)1606 if !ok {1607 continue1608 }1609 if f.Pkg.TypesInfo.ObjectOf(ident) == obj {1610 assigned = true1611 return false1612 }1613 }1614 return true1615 })1616 if assigned {1617 f.Errorf(arg, "argument %s is overwritten before first use", arg)1618 }1619 }1620 }1621 return true1622 }1623 f.Walk(fn)1624}1625func (c *Checker) CheckIneffectiveLoop(f *lint.File) {1626 // This check detects some, but not all unconditional loop exits.1627 // We give up in the following cases:1628 //1629 // - a goto anywhere in the loop. The goto might skip over our1630 // return, and we don't check that it doesn't.1631 //1632 // - any nested, unlabelled continue, even if it is in another1633 // loop or closure.1634 fn := func(node ast.Node) bool {1635 fn, ok := node.(*ast.FuncDecl)1636 if !ok {1637 return true1638 }1639 if fn.Body == nil {1640 return true1641 }1642 labels := map[*ast.Object]ast.Stmt{}1643 ast.Inspect(fn.Body, func(node ast.Node) bool {1644 label, ok := node.(*ast.LabeledStmt)1645 if !ok {1646 return true1647 }1648 labels[label.Label.Obj] = label.Stmt1649 return true1650 })1651 ast.Inspect(fn.Body, func(node ast.Node) bool {1652 var loop ast.Node1653 var body *ast.BlockStmt1654 switch node := node.(type) {1655 case *ast.ForStmt:1656 body = node.Body1657 loop = node1658 case *ast.RangeStmt:1659 typ := f.Pkg.TypesInfo.TypeOf(node.X)1660 if _, ok := typ.Underlying().(*types.Map); ok {1661 // looping once over a map is a valid pattern for1662 // getting an arbitrary element.1663 return true1664 }1665 body = node.Body1666 loop = node1667 default:1668 return true1669 }1670 if len(body.List) < 2 {1671 // avoid flagging the somewhat common pattern of using1672 // a range loop to get the first element in a slice,1673 // or the first rune in a string.1674 return true1675 }1676 var unconditionalExit ast.Node1677 hasBranching := false1678 for _, stmt := range body.List {1679 switch stmt := stmt.(type) {1680 case *ast.BranchStmt:1681 switch stmt.Tok {1682 case token.BREAK:1683 if stmt.Label == nil || labels[stmt.Label.Obj] == loop {1684 unconditionalExit = stmt1685 }1686 case token.CONTINUE:1687 if stmt.Label == nil || labels[stmt.Label.Obj] == loop {1688 unconditionalExit = nil1689 return false1690 }1691 }1692 case *ast.ReturnStmt:1693 unconditionalExit = stmt1694 case *ast.IfStmt, *ast.ForStmt, *ast.RangeStmt, *ast.SwitchStmt, *ast.SelectStmt:1695 hasBranching = true1696 }1697 }1698 if unconditionalExit == nil || !hasBranching {1699 return false1700 }1701 ast.Inspect(body, func(node ast.Node) bool {1702 if branch, ok := node.(*ast.BranchStmt); ok {1703 switch branch.Tok {1704 case token.GOTO:1705 unconditionalExit = nil1706 return false1707 case token.CONTINUE:1708 if branch.Label != nil && labels[branch.Label.Obj] != loop {1709 return true1710 }1711 unconditionalExit = nil1712 return false1713 }1714 }1715 return true1716 })1717 if unconditionalExit != nil {1718 f.Errorf(unconditionalExit, "the surrounding loop is unconditionally terminated")1719 }1720 return true1721 })1722 return true1723 }1724 f.Walk(fn)1725}1726var checkRegexpFindAllCallRule = CallRule{1727 Arguments: []ArgumentRule{1728 NotIntValue{1729 argumentRule: argumentRule{1730 idx: 1,1731 Message: "calling a FindAll method with n == 0 will return no results, did you mean -1?",1732 },1733 Not: vrp.NewZ(0),1734 },1735 },1736}1737var checkRegexpFindAllRules = map[string]CallRule{1738 "(*regexp.Regexp).FindAll": checkRegexpFindAllCallRule,1739 "(*regexp.Regexp).FindAllIndex": checkRegexpFindAllCallRule,1740 "(*regexp.Regexp).FindAllString": checkRegexpFindAllCallRule,1741 "(*regexp.Regexp).FindAllStringIndex": checkRegexpFindAllCallRule,1742 "(*regexp.Regexp).FindAllStringSubmatch": checkRegexpFindAllCallRule,1743 "(*regexp.Regexp).FindAllStringSubmatchIndex": checkRegexpFindAllCallRule,1744 "(*regexp.Regexp).FindAllSubmatch": checkRegexpFindAllCallRule,1745 "(*regexp.Regexp).FindAllSubmatchIndex": checkRegexpFindAllCallRule,1746}1747func (c *Checker) CheckRegexpFindAll(f *lint.File) {1748 c.checkCalls(f, checkRegexpFindAllRules)1749}1750var checkUTF8CutsetCallRule = CallRule{Arguments: []ArgumentRule{ValidUTF8{argumentRule: argumentRule{idx: 1}}}}1751var checkUTF8CutsetRules = map[string]CallRule{1752 "strings.IndexAny": checkUTF8CutsetCallRule,1753 "strings.LastIndexAny": checkUTF8CutsetCallRule,1754 "strings.ContainsAny": checkUTF8CutsetCallRule,1755 "strings.Trim": checkUTF8CutsetCallRule,1756 "strings.TrimLeft": checkUTF8CutsetCallRule,1757 "strings.TrimRight": checkUTF8CutsetCallRule,1758}1759func (c *Checker) CheckUTF8Cutset(f *lint.File) {1760 c.checkCalls(f, checkUTF8CutsetRules)1761}1762func (c *Checker) CheckNilContext(f *lint.File) {1763 fn := func(node ast.Node) bool {1764 call, ok := node.(*ast.CallExpr)1765 if !ok {1766 return true1767 }1768 if len(call.Args) == 0 {1769 return true1770 }1771 if typ, ok := f.Pkg.TypesInfo.TypeOf(call.Args[0]).(*types.Basic); !ok || typ.Kind() != types.UntypedNil {1772 return true1773 }1774 sig, ok := f.Pkg.TypesInfo.TypeOf(call.Fun).(*types.Signature)1775 if !ok {1776 return true1777 }1778 if sig.Params().Len() == 0 {1779 return true1780 }1781 if types.TypeString(sig.Params().At(0).Type(), nil) != "context.Context" {1782 return true1783 }1784 f.Errorf(call.Args[0],1785 "do not pass a nil Context, even if a function permits it; pass context.TODO if you are unsure about which Context to use")1786 return true1787 }1788 f.Walk(fn)1789}1790func (c *Checker) CheckSeeker(f *lint.File) {1791 fn := func(node ast.Node) bool {1792 call, ok := node.(*ast.CallExpr)1793 if !ok {1794 return true1795 }1796 sel, ok := call.Fun.(*ast.SelectorExpr)1797 if !ok {1798 return true1799 }1800 if sel.Sel.Name != "Seek" {1801 return true1802 }1803 if len(call.Args) != 2 {1804 return true1805 }1806 arg0, ok := call.Args[0].(*ast.SelectorExpr)1807 if !ok {1808 return true1809 }1810 switch arg0.Sel.Name {1811 case "SeekStart", "SeekCurrent", "SeekEnd":1812 default:1813 return true1814 }1815 pkg, ok := arg0.X.(*ast.Ident)1816 if !ok {1817 return true1818 }1819 if pkg.Name != "io" {1820 return true1821 }1822 f.Errorf(call, "the first argument of io.Seeker is the offset, but an io.Seek* constant is being used instead")1823 return true1824 }1825 f.Walk(fn)1826}1827func (c *Checker) CheckIneffectiveAppend(f *lint.File) {1828 fn := func(node ast.Node) bool {1829 assign, ok := node.(*ast.AssignStmt)1830 if !ok || len(assign.Lhs) != 1 || len(assign.Rhs) != 1 {1831 return true1832 }1833 ident, ok := assign.Lhs[0].(*ast.Ident)1834 if !ok || ident.Name == "_" {1835 return true1836 }1837 call, ok := assign.Rhs[0].(*ast.CallExpr)1838 if !ok {1839 return true1840 }1841 if callIdent, ok := call.Fun.(*ast.Ident); !ok || callIdent.Name != "append" {1842 // XXX check that it's the built-in append1843 return true1844 }1845 ssafn := f.EnclosingSSAFunction(assign)1846 if ssafn == nil {1847 return true1848 }1849 tfn, ok := ssafn.Object().(*types.Func)1850 if ok {1851 res := tfn.Type().(*types.Signature).Results()1852 for i := 0; i < res.Len(); i++ {1853 if res.At(i) == f.Pkg.TypesInfo.ObjectOf(ident) {1854 // Don't flag appends assigned to named return arguments1855 return true1856 }1857 }1858 }1859 isAppend := func(ins ssa.Value) bool {1860 call, ok := ins.(*ssa.Call)1861 if !ok {1862 return false1863 }1864 if call.Call.IsInvoke() {1865 return false1866 }1867 if builtin, ok := call.Call.Value.(*ssa.Builtin); !ok || builtin.Name() != "append" {1868 return false1869 }1870 return true1871 }1872 isUsed := false1873 visited := map[ssa.Instruction]bool{}1874 var walkRefs func(refs []ssa.Instruction)1875 walkRefs = func(refs []ssa.Instruction) {1876 loop:1877 for _, ref := range refs {1878 if visited[ref] {1879 continue1880 }1881 visited[ref] = true1882 if _, ok := ref.(*ssa.DebugRef); ok {1883 continue1884 }1885 switch ref := ref.(type) {1886 case *ssa.Phi:1887 walkRefs(*ref.Referrers())1888 case ssa.Value:1889 if !isAppend(ref) {1890 isUsed = true1891 } else {1892 walkRefs(*ref.Referrers())1893 }1894 case ssa.Instruction:1895 isUsed = true1896 break loop1897 }1898 }1899 }1900 expr, _ := ssafn.ValueForExpr(call)1901 if expr == nil {1902 return true1903 }1904 refs := expr.Referrers()1905 if refs == nil {1906 return true1907 }1908 walkRefs(*refs)1909 if !isUsed {1910 f.Errorf(assign, "this result of append is never used, except maybe in other appends")1911 }1912 return true1913 }1914 f.Walk(fn)1915}1916func (c *Checker) CheckConcurrentTesting(f *lint.File) {1917 for _, ssafn := range c.funcsForFile(f) {1918 for _, block := range ssafn.Blocks {1919 for _, ins := range block.Instrs {1920 gostmt, ok := ins.(*ssa.Go)1921 if !ok {1922 continue1923 }1924 var fn *ssa.Function1925 switch val := gostmt.Call.Value.(type) {1926 case *ssa.Function:1927 fn = val1928 case *ssa.MakeClosure:1929 fn = val.Fn.(*ssa.Function)1930 default:1931 continue1932 }1933 if fn.Blocks == nil {1934 continue1935 }1936 for _, block := range fn.Blocks {1937 for _, ins := range block.Instrs {1938 call, ok := ins.(*ssa.Call)1939 if !ok {1940 continue1941 }1942 if call.Call.IsInvoke() {1943 continue1944 }1945 callee := call.Call.StaticCallee()1946 if callee == nil {1947 continue1948 }1949 recv := callee.Signature.Recv()1950 if recv == nil {1951 continue1952 }1953 if types.TypeString(recv.Type(), nil) != "*testing.common" {1954 continue1955 }1956 fn, ok := call.Call.StaticCallee().Object().(*types.Func)1957 if !ok {1958 continue1959 }1960 name := fn.Name()1961 switch name {1962 case "FailNow", "Fatal", "Fatalf", "SkipNow", "Skip", "Skipf":1963 default:1964 continue1965 }1966 f.Errorf(gostmt, "the goroutine calls T.%s, which must be called in the same goroutine as the test", name)1967 }1968 }1969 }1970 }1971 }1972}1973func (c *Checker) CheckCyclicFinalizer(f *lint.File) {1974 for _, ssafn := range c.funcsForFile(f) {1975 for _, b := range ssafn.Blocks {1976 for _, ins := range b.Instrs {1977 call, ok := ins.(*ssa.Call)1978 if !ok {1979 continue1980 }1981 callee := call.Common().StaticCallee()1982 if callee == nil {1983 continue1984 }1985 obj, ok := callee.Object().(*types.Func)1986 if !ok {1987 continue1988 }1989 if obj.FullName() != "runtime.SetFinalizer" {1990 continue1991 }1992 arg0 := call.Common().Args[0]1993 if iface, ok := arg0.(*ssa.MakeInterface); ok {1994 arg0 = iface.X1995 }1996 unop, ok := arg0.(*ssa.UnOp)1997 if !ok {1998 continue1999 }2000 v, ok := unop.X.(*ssa.Alloc)2001 if !ok {2002 continue2003 }2004 arg1 := call.Common().Args[1]2005 if iface, ok := arg1.(*ssa.MakeInterface); ok {2006 arg1 = iface.X2007 }2008 mc, ok := arg1.(*ssa.MakeClosure)2009 if !ok {2010 continue2011 }2012 for _, b := range mc.Bindings {2013 if b == v {2014 pos := f.Fset.Position(mc.Fn.Pos())2015 f.Errorf(call, "the finalizer closes over the object, preventing the finalizer from ever running (at %s)", pos)2016 }2017 }2018 }2019 }2020 }2021}2022func (c *Checker) CheckSliceOutOfBounds(f *lint.File) {2023 for _, ssafn := range c.funcsForFile(f) {2024 for _, block := range ssafn.Blocks {2025 for _, ins := range block.Instrs {2026 ia, ok := ins.(*ssa.IndexAddr)2027 if !ok {2028 continue2029 }2030 if _, ok := ia.X.Type().Underlying().(*types.Slice); !ok {2031 continue2032 }2033 sr, ok1 := c.funcDescs.Get(ssafn).Ranges[ia.X].(vrp.SliceInterval)2034 idxr, ok2 := c.funcDescs.Get(ssafn).Ranges[ia.Index].(vrp.IntInterval)2035 if !ok1 || !ok2 || !sr.IsKnown() || !idxr.IsKnown() || sr.Length.Empty() || idxr.Empty() {2036 continue2037 }2038 if idxr.Lower.Cmp(sr.Length.Upper) >= 0 {2039 f.Errorf(ia, "index out of bounds")2040 }2041 }2042 }2043 }2044}2045func (c *Checker) CheckDeferLock(f *lint.File) {2046 fn := func(node ast.Node) bool {2047 block, ok := node.(*ast.BlockStmt)2048 if !ok {2049 return true2050 }2051 if len(block.List) < 2 {2052 return true2053 }2054 for i, stmt := range block.List[:len(block.List)-1] {2055 expr, ok := stmt.(*ast.ExprStmt)2056 if !ok {2057 continue2058 }2059 call, ok := expr.X.(*ast.CallExpr)2060 if !ok {2061 continue2062 }2063 sel, ok := call.Fun.(*ast.SelectorExpr)2064 if !ok || (sel.Sel.Name != "Lock" && sel.Sel.Name != "RLock") || len(call.Args) != 0 {2065 continue2066 }2067 d, ok := block.List[i+1].(*ast.DeferStmt)2068 if !ok || len(d.Call.Args) != 0 {2069 continue2070 }2071 dsel, ok := d.Call.Fun.(*ast.SelectorExpr)2072 if !ok || dsel.Sel.Name != sel.Sel.Name || f.Render(dsel.X) != f.Render(sel.X) {2073 continue2074 }2075 unlock := "Unlock"2076 if sel.Sel.Name[0] == 'R' {2077 unlock = "RUnlock"2078 }2079 f.Errorf(d, "deferring %s right after having locked already; did you mean to defer %s?", sel.Sel.Name, unlock)2080 }2081 return true2082 }2083 f.Walk(fn)2084}2085func (c *Checker) CheckNaNComparison(f *lint.File) {2086 isNaN := func(x ast.Expr) bool {2087 return isFunctionCallName(f, x, "math.NaN")2088 }2089 fn := func(node ast.Node) bool {2090 op, ok := node.(*ast.BinaryExpr)2091 if !ok {2092 return true2093 }2094 if isNaN(op.X) || isNaN(op.Y) {2095 f.Errorf(op, "no value is equal to NaN, not even NaN itself")2096 }2097 return true2098 }2099 f.Walk(fn)2100}2101func (c *Checker) CheckInfiniteRecursion(f *lint.File) {2102 for _, ssafn := range c.funcsForFile(f) {2103 for _, block := range ssafn.Blocks {2104 for _, ins := range block.Instrs {2105 call, ok := ins.(*ssa.Call)2106 if !ok {2107 continue2108 }2109 if call.Common().IsInvoke() {2110 continue2111 }2112 subfn, ok := call.Common().Value.(*ssa.Function)2113 if !ok || subfn != ssafn {2114 continue2115 }2116 canReturn := false2117 for _, b := range subfn.Blocks {2118 if block.Dominates(b) {2119 continue2120 }2121 if len(b.Instrs) == 0 {2122 continue2123 }2124 if _, ok := b.Instrs[len(b.Instrs)-1].(*ssa.Return); ok {2125 canReturn = true2126 break2127 }2128 }2129 if canReturn {2130 continue2131 }2132 f.Errorf(call, "infinite recursive call")2133 }2134 }2135 }2136}2137func objectName(obj types.Object) string {2138 if obj == nil {2139 return "<nil>"2140 }2141 var name string2142 if obj.Pkg() != nil && obj.Pkg().Scope().Lookup(obj.Name()) == obj {2143 var s string2144 s = obj.Pkg().Path()2145 if s != "" {2146 name += s + "."2147 }2148 }2149 name += obj.Name()2150 return name2151}2152func isName(f *lint.File, expr ast.Expr, name string) bool {2153 var obj types.Object2154 switch expr := expr.(type) {2155 case *ast.Ident:2156 obj = f.Pkg.TypesInfo.ObjectOf(expr)2157 case *ast.SelectorExpr:2158 obj = f.Pkg.TypesInfo.ObjectOf(expr.Sel)2159 }2160 return objectName(obj) == name2161}2162func isFunctionCallName(f *lint.File, node ast.Node, name string) bool {2163 call, ok := node.(*ast.CallExpr)2164 if !ok {2165 return false2166 }2167 sel, ok := call.Fun.(*ast.SelectorExpr)2168 if !ok {2169 return false2170 }2171 fn, ok := f.Pkg.TypesInfo.ObjectOf(sel.Sel).(*types.Func)2172 return ok && fn.FullName() == name2173}2174func isFunctionCallNameAny(f *lint.File, node ast.Node, names ...string) bool {2175 for _, name := range names {2176 if isFunctionCallName(f, node, name) {2177 return true2178 }2179 }2180 return false2181}2182var checkUnmarshalPointerRules = map[string]CallRule{2183 "encoding/xml.Unmarshal": CallRule{2184 Arguments: []ArgumentRule{2185 Pointer{2186 argumentRule: argumentRule{2187 idx: 1,2188 Message: "xml.Unmarshal expects to unmarshal into a pointer, but the provided value is not a pointer",2189 },2190 },2191 },2192 },2193 "(*encoding/xml.Decoder).Decode": CallRule{2194 Arguments: []ArgumentRule{2195 Pointer{2196 argumentRule: argumentRule{2197 idx: 0,2198 Message: "Decode expects to unmarshal into a pointer, but the provided value is not a pointer",2199 },2200 },2201 },2202 },2203 "encoding/json.Unmarshal": CallRule{2204 Arguments: []ArgumentRule{2205 Pointer{2206 argumentRule: argumentRule{2207 idx: 1,2208 Message: "json.Unmarshal expects to unmarshal into a pointer, but the provided value is not a pointer",2209 },2210 },2211 },2212 },2213 "(*encoding/json.Decoder).Decode": CallRule{2214 Arguments: []ArgumentRule{2215 Pointer{2216 argumentRule: argumentRule{2217 idx: 0,2218 Message: "Decode expects to unmarshal into a pointer, but the provided value is not a pointer",2219 },2220 },2221 },2222 },2223}2224func (c *Checker) CheckUnmarshalPointer(f *lint.File) {2225 c.checkCalls(f, checkUnmarshalPointerRules)2226}2227func (c *Checker) CheckLeakyTimeTick(f *lint.File) {2228 if f.IsMain() || f.IsTest() {2229 return2230 }2231 var flowTerminates func(start, b *ssa.BasicBlock, seen map[*ssa.BasicBlock]bool) bool2232 flowTerminates = func(start, b *ssa.BasicBlock, seen map[*ssa.BasicBlock]bool) bool {2233 if seen == nil {2234 seen = map[*ssa.BasicBlock]bool{}2235 }2236 if seen[b] {2237 return false2238 }2239 seen[b] = true2240 for _, ins := range b.Instrs {2241 if _, ok := ins.(*ssa.Return); ok {2242 return true2243 }2244 }2245 if b == start {2246 if flowTerminates(start, b.Succs[0], seen) {2247 return true2248 }2249 } else {2250 for _, succ := range b.Succs {2251 if flowTerminates(start, succ, seen) {2252 return true2253 }2254 }2255 }2256 return false2257 }2258 fn := func(node ast.Node) bool {2259 if !isFunctionCallName(f, node, "time.Tick") {2260 return true2261 }2262 ssafn := c.nodeFns[node]2263 if ssafn == nil {2264 return false2265 }2266 if c.funcDescs.Get(ssafn).Infinite {2267 return true2268 }2269 f.Errorf(node, "using time.Tick leaks the underlying ticker, consider using it only in endless functions, tests and the main package, and use time.NewTicker here")2270 return true2271 }2272 f.Walk(fn)2273}2274func (c *Checker) CheckDoubleNegation(f *lint.File) {2275 fn := func(node ast.Node) bool {2276 unary1, ok := node.(*ast.UnaryExpr)2277 if !ok {2278 return true2279 }2280 unary2, ok := unary1.X.(*ast.UnaryExpr)2281 if !ok {2282 return true2283 }2284 if unary1.Op != token.NOT || unary2.Op != token.NOT {2285 return true2286 }2287 f.Errorf(unary1, "negating a boolean twice has no effect; is this a typo?")2288 return true2289 }2290 f.Walk(fn)2291}2292func (c *Checker) CheckRepeatedIfElse(f *lint.File) {2293 seen := map[ast.Node]bool{}2294 var collectConds func(ifstmt *ast.IfStmt, inits []ast.Stmt, conds []ast.Expr) ([]ast.Stmt, []ast.Expr)2295 collectConds = func(ifstmt *ast.IfStmt, inits []ast.Stmt, conds []ast.Expr) ([]ast.Stmt, []ast.Expr) {2296 seen[ifstmt] = true2297 if ifstmt.Init != nil {2298 inits = append(inits, ifstmt.Init)2299 }2300 conds = append(conds, ifstmt.Cond)2301 if elsestmt, ok := ifstmt.Else.(*ast.IfStmt); ok {2302 return collectConds(elsestmt, inits, conds)2303 }2304 return inits, conds2305 }2306 isDynamic := func(node ast.Node) bool {2307 dynamic := false2308 ast.Inspect(node, func(node ast.Node) bool {2309 switch node := node.(type) {2310 case *ast.CallExpr:2311 dynamic = true2312 return false2313 case *ast.UnaryExpr:2314 if node.Op == token.ARROW {2315 dynamic = true2316 return false2317 }2318 }2319 return true2320 })2321 return dynamic2322 }2323 fn := func(node ast.Node) bool {2324 ifstmt, ok := node.(*ast.IfStmt)2325 if !ok {2326 return true2327 }2328 if seen[ifstmt] {2329 return true2330 }2331 inits, conds := collectConds(ifstmt, nil, nil)2332 if len(inits) > 0 {2333 return true2334 }2335 for _, cond := range conds {2336 if isDynamic(cond) {2337 return true2338 }2339 }2340 counts := map[string]int{}2341 for _, cond := range conds {2342 s := f.Render(cond)2343 counts[s]++2344 if counts[s] == 2 {2345 f.Errorf(cond, "this condition occurs multiple times in this if/else if chain")2346 }2347 }2348 return true2349 }2350 f.Walk(fn)2351}2352var checkUnbufferedSignalChanRules = map[string]CallRule{2353 "os/signal.Notify": CallRule{2354 Arguments: []ArgumentRule{2355 BufferedChannel{2356 argumentRule: argumentRule{2357 idx: 0,2358 Message: "the channel used with signal.Notify should be buffered",2359 },2360 },2361 },2362 },2363}2364func (c *Checker) CheckUnbufferedSignalChan(f *lint.File) {2365 c.checkCalls(f, checkUnbufferedSignalChanRules)2366}2367var checkMathIntRules = map[string]CallRule{2368 "math.Ceil": CallRule{2369 Arguments: []ArgumentRule{2370 NotConvertedInt{2371 argumentRule: argumentRule{2372 idx: 0,2373 Message: "calling math.Ceil on a converted integer is pointless",2374 },2375 },2376 },2377 },2378 "math.Floor": CallRule{2379 Arguments: []ArgumentRule{2380 NotConvertedInt{2381 argumentRule: argumentRule{2382 idx: 0,2383 Message: "calling math.Floor on a converted integer is pointless",2384 },2385 },2386 },2387 },2388 "math.IsNaN": CallRule{2389 Arguments: []ArgumentRule{2390 NotConvertedInt{2391 argumentRule: argumentRule{2392 idx: 0,2393 Message: "calling math.IsNaN on a converted integer is pointless",2394 },2395 },2396 },2397 },2398 "math.Trunc": CallRule{2399 Arguments: []ArgumentRule{2400 NotConvertedInt{2401 argumentRule: argumentRule{2402 idx: 0,2403 Message: "calling math.Trunc on a converted integer is pointless",2404 },2405 },2406 },2407 },2408 "math.IsInf": CallRule{2409 Arguments: []ArgumentRule{2410 NotConvertedInt{2411 argumentRule: argumentRule{2412 idx: 0,2413 Message: "calling math.IsInf on a converted integer is pointless",2414 },2415 },2416 },2417 },2418}2419func (c *Checker) CheckMathInt(f *lint.File) {2420 c.checkCalls(f, checkMathIntRules)2421}2422func (c *Checker) CheckSillyBitwiseOps(f *lint.File) {2423 fn := func(node ast.Node) bool {2424 expr, ok := node.(*ast.BinaryExpr)2425 if !ok {2426 return true2427 }2428 // We check for a literal 0, not a constant expression2429 // evaluating to 0. The latter tend to be false positives due2430 // to system-dependent constants.2431 if !lint.IsZero(expr.Y) {2432 return true2433 }2434 switch expr.Op {2435 case token.AND:2436 f.Errorf(expr, "x & 0 always equals 0")2437 case token.OR, token.XOR:2438 f.Errorf(expr, "x %s 0 always equals x", expr.Op)2439 case token.SHL, token.SHR:2440 // we do not flag shifts because too often, x<<0 is part2441 // of a pattern, x<<0, x<<8, x<<16, ...2442 }2443 return true2444 }2445 f.Walk(fn)2446}2447func (c *Checker) CheckNonOctalFileMode(f *lint.File) {2448 fn := func(node ast.Node) bool {2449 call, ok := node.(*ast.CallExpr)2450 if !ok {2451 return true2452 }2453 sig, ok := f.Pkg.TypesInfo.TypeOf(call.Fun).(*types.Signature)2454 if !ok {2455 return true2456 }2457 n := sig.Params().Len()2458 var args []int2459 for i := 0; i < n; i++ {2460 typ := sig.Params().At(i).Type()2461 if types.TypeString(typ, nil) == "os.FileMode" {2462 args = append(args, i)2463 }2464 }2465 for _, i := range args {2466 lit, ok := call.Args[i].(*ast.BasicLit)2467 if !ok {2468 continue2469 }2470 if len(lit.Value) == 3 &&2471 lit.Value[0] != '0' &&2472 lit.Value[0] >= '0' && lit.Value[0] <= '7' &&2473 lit.Value[1] >= '0' && lit.Value[1] <= '7' &&2474 lit.Value[2] >= '0' && lit.Value[2] <= '7' {2475 v, err := strconv.ParseInt(lit.Value, 10, 64)2476 if err != nil {2477 continue2478 }2479 f.Errorf(call.Args[i], "file mode '%s' evaluates to %#o; did you mean '0%s'?", lit.Value, v, lit.Value)2480 }2481 }2482 return true2483 }2484 f.Walk(fn)2485}2486var checkStringsReplaceZeroRules = map[string]CallRule{2487 "strings.Replace": CallRule{2488 Arguments: []ArgumentRule{2489 NotIntValue{2490 argumentRule: argumentRule{2491 idx: 3,2492 Message: "calling strings.Replace with n == 0 will do nothing, did you mean -1?",2493 },2494 Not: vrp.NewZ(0),2495 },2496 },2497 },2498 "bytes.Replace": CallRule{2499 Arguments: []ArgumentRule{2500 NotIntValue{2501 argumentRule: argumentRule{2502 idx: 3,2503 Message: "calling bytes.Replace with n == 0 will do nothing, did you mean -1?",2504 },2505 Not: vrp.NewZ(0),2506 },2507 },2508 },2509}2510func (c *Checker) CheckStringsReplaceZero(f *lint.File) {2511 c.checkCalls(f, checkStringsReplaceZeroRules)2512}2513func (c *Checker) CheckPureFunctions(f *lint.File) {2514 for _, ssafn := range c.funcsForFile(f) {2515 for _, b := range ssafn.Blocks {2516 for _, ins := range b.Instrs {2517 ins, ok := ins.(*ssa.Call)2518 if !ok {2519 continue2520 }2521 refs := ins.Referrers()2522 if refs == nil || len(filterDebug(*refs)) > 0 {2523 continue2524 }2525 callee := ins.Common().StaticCallee()2526 if callee == nil {2527 continue2528 }2529 if c.funcDescs.Get(callee).Pure {2530 f.Errorf(ins, "%s is a pure function but its return value is ignored", callee.Name())2531 continue2532 }2533 }2534 }2535 }2536}2537func enclosingFunction(f *lint.File, node ast.Node) *ast.FuncDecl {2538 path, _ := astutil.PathEnclosingInterval(f.File, node.Pos(), node.Pos())2539 for _, e := range path {2540 fn, ok := e.(*ast.FuncDecl)2541 if !ok {2542 continue2543 }2544 if fn.Name == nil {2545 continue2546 }2547 return fn2548 }2549 return nil2550}2551func (c *Checker) isDeprecated(f *lint.File, ident *ast.Ident) (bool, string) {2552 obj := f.Pkg.TypesInfo.ObjectOf(ident)2553 if obj.Pkg() == nil {2554 return false, ""2555 }2556 alt := c.deprecatedObjs[obj]2557 return alt != "", alt2558}2559func (c *Checker) CheckDeprecated(f *lint.File) {2560 fn := func(node ast.Node) bool {2561 sel, ok := node.(*ast.SelectorExpr)2562 if !ok {2563 return true2564 }2565 if fn := enclosingFunction(f, sel); fn != nil {2566 if ok, _ := c.isDeprecated(f, fn.Name); ok {2567 // functions that are deprecated may use deprecated2568 // symbols2569 return true2570 }2571 }2572 obj := f.Pkg.TypesInfo.ObjectOf(sel.Sel)2573 if obj.Pkg() == nil {2574 return true2575 }2576 if f.Pkg.PkgInfo.Pkg == obj.Pkg() || obj.Pkg().Path()+"_test" == f.Pkg.PkgInfo.Pkg.Path() {2577 // Don't flag stuff in our own package2578 return true2579 }2580 if ok, alt := c.isDeprecated(f, sel.Sel); ok {2581 f.Errorf(sel, "%s is deprecated: %s", f.Render(sel), alt)2582 return true2583 }2584 return true2585 }2586 f.Walk(fn)2587}2588func (c *Checker) checkCalls(f *lint.File, rules map[string]CallRule) {2589 for _, ssafn := range c.funcsForFile(f) {2590 for _, b := range ssafn.Blocks {2591 insLoop:2592 for _, ins := range b.Instrs {2593 ssacall, ok := ins.(*ssa.Call)2594 if !ok {2595 continue2596 }2597 callee := ssacall.Common().StaticCallee()2598 if callee == nil {2599 continue2600 }2601 obj, ok := callee.Object().(*types.Func)2602 if !ok {2603 continue2604 }2605 r := rules[obj.FullName()]2606 if len(r.Arguments) == 0 {2607 continue2608 }2609 type argError struct {2610 arg lint.Positioner2611 err error2612 }2613 errs := make([]*argError, len(r.Arguments))2614 for i, ar := range r.Arguments {2615 idx := ar.Index()2616 if ssacall.Common().Signature().Recv() != nil {2617 idx++2618 }2619 arg := ssacall.Common().Args[idx]2620 if iarg, ok := arg.(*ssa.MakeInterface); ok {2621 arg = iarg.X2622 }2623 err := ar.Validate(arg, ssafn, c)2624 if err != nil {2625 path, _ := astutil.PathEnclosingInterval(f.File, ssacall.Pos(), ssacall.Pos())2626 if len(path) < 2 {2627 continue insLoop2628 }2629 call, ok := path[0].(*ast.CallExpr)2630 if !ok {2631 continue insLoop2632 }2633 errs[i] = &argError{call.Args[ar.Index()], err}2634 }2635 }2636 switch r.Mode {2637 case InvalidIndependent:2638 for _, err := range errs {2639 if err != nil {2640 f.Errorf(err.arg, "%s", err.err)2641 }2642 }2643 case InvalidIfAny:2644 for _, err := range errs {2645 if err == nil {2646 continue insLoop2647 }2648 f.Errorf(ssacall, "%s", err.err)2649 continue2650 }2651 case InvalidIfAll:2652 var first error2653 for _, err := range errs {2654 if err == nil {2655 continue insLoop2656 }2657 if first == nil {2658 first = err.err2659 }2660 }2661 f.Errorf(ssacall, "%s", first)2662 }2663 }2664 }2665 }2666}2667var checkListenAddressRules = map[string]CallRule{2668 "net/http.ListenAndServe": CallRule{Arguments: []ArgumentRule{ValidHostPort{argumentRule{idx: 0}}}},2669 "net/http.ListenAndServeTLS": CallRule{Arguments: []ArgumentRule{ValidHostPort{argumentRule{idx: 0}}}},2670}2671func (c *Checker) CheckListenAddress(f *lint.File) {2672 c.checkCalls(f, checkListenAddressRules)2673}2674var checkBytesEqualIPRules = map[string]CallRule{2675 "bytes.Equal": CallRule{2676 Arguments: []ArgumentRule{2677 NotChangedTypeFrom{2678 argumentRule{2679 idx: 0,2680 Message: "use net.IP.Equal to compare net.IPs, not bytes.Equal",2681 },2682 "net.IP",2683 },2684 NotChangedTypeFrom{2685 argumentRule{2686 idx: 1,2687 Message: "use net.IP.Equal to compare net.IPs, not bytes.Equal",2688 },2689 "net.IP",2690 },2691 },2692 Mode: InvalidIfAll,2693 },2694}2695func (c *Checker) CheckBytesEqualIP(f *lint.File) {2696 c.checkCalls(f, checkBytesEqualIPRules)2697}...

Full Screen

Full Screen

environdestroy_test.go

Source:environdestroy_test.go Github

copy

Full Screen

1// Copyright 2012-2015 Canonical Ltd.2// Licensed under the AGPLv3, see LICENCE file for details.3package common_test4import (5 "fmt"6 "github.com/juju/errors"7 "github.com/juju/names"8 jc "github.com/juju/testing/checkers"9 gc "gopkg.in/check.v1"10 "github.com/juju/1.25-upgrade/juju1/apiserver/client"11 "github.com/juju/1.25-upgrade/juju1/apiserver/common"12 commontesting "github.com/juju/1.25-upgrade/juju1/apiserver/common/testing"13 apiservertesting "github.com/juju/1.25-upgrade/juju1/apiserver/testing"14 "github.com/juju/1.25-upgrade/juju1/environs"15 "github.com/juju/1.25-upgrade/juju1/instance"16 "github.com/juju/1.25-upgrade/juju1/juju/testing"17 "github.com/juju/1.25-upgrade/juju1/provider/dummy"18 "github.com/juju/1.25-upgrade/juju1/state"19 jujutesting "github.com/juju/1.25-upgrade/juju1/testing"20 "github.com/juju/1.25-upgrade/juju1/testing/factory"21 jtesting "github.com/juju/testing"22)23type destroyEnvironmentSuite struct {24 testing.JujuConnSuite25 commontesting.BlockHelper26 metricSender *testMetricSender27}28var _ = gc.Suite(&destroyEnvironmentSuite{})29func (s *destroyEnvironmentSuite) SetUpTest(c *gc.C) {30 s.JujuConnSuite.SetUpTest(c)31 s.BlockHelper = commontesting.NewBlockHelper(s.APIState)32 s.AddCleanup(func(*gc.C) { s.BlockHelper.Close() })33 s.metricSender = &testMetricSender{}34 s.PatchValue(common.SendMetrics, s.metricSender.SendMetrics)35}36// setUpManual adds "manually provisioned" machines to state:37// one manager machine, and one non-manager.38func (s *destroyEnvironmentSuite) setUpManual(c *gc.C) (m0, m1 *state.Machine) {39 m0, err := s.State.AddMachine("precise", state.JobManageEnviron)40 c.Assert(err, jc.ErrorIsNil)41 err = m0.SetProvisioned(instance.Id("manual:0"), "manual:0:fake_nonce", nil)42 c.Assert(err, jc.ErrorIsNil)43 m1, err = s.State.AddMachine("precise", state.JobHostUnits)44 c.Assert(err, jc.ErrorIsNil)45 err = m1.SetProvisioned(instance.Id("manual:1"), "manual:1:fake_nonce", nil)46 c.Assert(err, jc.ErrorIsNil)47 return m0, m148}49// setUpInstances adds machines to state backed by instances:50// one manager machine, one non-manager, and a container in the51// non-manager.52func (s *destroyEnvironmentSuite) setUpInstances(c *gc.C) (m0, m1, m2 *state.Machine) {53 m0, err := s.State.AddMachine("precise", state.JobManageEnviron)54 c.Assert(err, jc.ErrorIsNil)55 inst, _ := testing.AssertStartInstance(c, s.Environ, m0.Id())56 err = m0.SetProvisioned(inst.Id(), "fake_nonce", nil)57 c.Assert(err, jc.ErrorIsNil)58 m1, err = s.State.AddMachine("precise", state.JobHostUnits)59 c.Assert(err, jc.ErrorIsNil)60 inst, _ = testing.AssertStartInstance(c, s.Environ, m1.Id())61 err = m1.SetProvisioned(inst.Id(), "fake_nonce", nil)62 c.Assert(err, jc.ErrorIsNil)63 m2, err = s.State.AddMachineInsideMachine(state.MachineTemplate{64 Series: "precise",65 Jobs: []state.MachineJob{state.JobHostUnits},66 }, m1.Id(), instance.LXC)67 c.Assert(err, jc.ErrorIsNil)68 err = m2.SetProvisioned("container0", "fake_nonce", nil)69 c.Assert(err, jc.ErrorIsNil)70 return m0, m1, m271}72func (s *destroyEnvironmentSuite) TestDestroyEnvironmentManual(c *gc.C) {73 _, nonManager := s.setUpManual(c)74 // If there are any non-manager manual machines in state, DestroyEnvironment will75 // error. It will not set the Dying flag on the environment.76 err := common.DestroyEnvironment(s.State, s.State.EnvironTag())77 c.Assert(err, gc.ErrorMatches, fmt.Sprintf("failed to destroy environment: manually provisioned machines must first be destroyed with `juju destroy-machine %s`", nonManager.Id()))78 env, err := s.State.Environment()79 c.Assert(err, jc.ErrorIsNil)80 c.Assert(env.Life(), gc.Equals, state.Alive)81 // If we remove the non-manager machine, it should pass.82 // Manager machines will remain.83 err = nonManager.EnsureDead()84 c.Assert(err, jc.ErrorIsNil)85 err = nonManager.Remove()86 c.Assert(err, jc.ErrorIsNil)87 err = common.DestroyEnvironment(s.State, s.State.EnvironTag())88 c.Assert(err, jc.ErrorIsNil)89 err = env.Refresh()90 c.Assert(err, jc.ErrorIsNil)91 c.Assert(env.Life(), gc.Equals, state.Dying)92 s.metricSender.CheckCalls(c, []jtesting.StubCall{{FuncName: "SendMetrics"}})93}94func (s *destroyEnvironmentSuite) TestDestroyEnvironment(c *gc.C) {95 manager, nonManager, _ := s.setUpInstances(c)96 managerId, _ := manager.InstanceId()97 nonManagerId, _ := nonManager.InstanceId()98 instances, err := s.Environ.Instances([]instance.Id{managerId, nonManagerId})99 c.Assert(err, jc.ErrorIsNil)100 for _, inst := range instances {101 c.Assert(inst, gc.NotNil)102 }103 services, err := s.State.AllServices()104 c.Assert(err, jc.ErrorIsNil)105 err = common.DestroyEnvironment(s.State, s.State.EnvironTag())106 c.Assert(err, jc.ErrorIsNil)107 s.metricSender.CheckCalls(c, []jtesting.StubCall{{FuncName: "SendMetrics"}})108 // After DestroyEnvironment returns, we should have:109 // - all non-manager instances stopped110 instances, err = s.Environ.Instances([]instance.Id{managerId, nonManagerId})111 c.Assert(err, gc.Equals, environs.ErrPartialInstances)112 c.Assert(instances[0], gc.NotNil)113 c.Assert(instances[1], jc.ErrorIsNil)114 // - all services in state are Dying or Dead (or removed altogether),115 // after running the state Cleanups.116 needsCleanup, err := s.State.NeedsCleanup()117 c.Assert(err, jc.ErrorIsNil)118 c.Assert(needsCleanup, jc.IsTrue)119 err = s.State.Cleanup()120 c.Assert(err, jc.ErrorIsNil)121 for _, s := range services {122 err = s.Refresh()123 if err != nil {124 c.Assert(err, jc.Satisfies, errors.IsNotFound)125 } else {126 c.Assert(s.Life(), gc.Not(gc.Equals), state.Alive)127 }128 }129 // - environment is Dying130 env, err := s.State.Environment()131 c.Assert(err, jc.ErrorIsNil)132 c.Assert(env.Life(), gc.Equals, state.Dying)133}134func (s *destroyEnvironmentSuite) TestDestroyEnvironmentWithContainers(c *gc.C) {135 ops := make(chan dummy.Operation, 500)136 dummy.Listen(ops)137 _, nonManager, _ := s.setUpInstances(c)138 nonManagerId, _ := nonManager.InstanceId()139 err := common.DestroyEnvironment(s.State, s.State.EnvironTag())140 c.Assert(err, jc.ErrorIsNil)141 for op := range ops {142 if op, ok := op.(dummy.OpStopInstances); ok {143 c.Assert(op.Ids, jc.SameContents, []instance.Id{nonManagerId})144 break145 }146 }147 s.metricSender.CheckCalls(c, []jtesting.StubCall{{FuncName: "SendMetrics"}})148}149func (s *destroyEnvironmentSuite) TestBlockDestroyDestroyEnvironment(c *gc.C) {150 // Setup environment151 s.setUpInstances(c)152 s.BlockDestroyEnvironment(c, "TestBlockDestroyDestroyEnvironment")153 err := common.DestroyEnvironment(s.State, s.State.EnvironTag())154 s.AssertBlocked(c, err, "TestBlockDestroyDestroyEnvironment")155 s.metricSender.CheckCalls(c, []jtesting.StubCall{})156}157func (s *destroyEnvironmentSuite) TestBlockRemoveDestroyEnvironment(c *gc.C) {158 // Setup environment159 s.setUpInstances(c)160 s.BlockRemoveObject(c, "TestBlockRemoveDestroyEnvironment")161 err := common.DestroyEnvironment(s.State, s.State.EnvironTag())162 s.AssertBlocked(c, err, "TestBlockRemoveDestroyEnvironment")163 s.metricSender.CheckCalls(c, []jtesting.StubCall{})164}165func (s *destroyEnvironmentSuite) TestBlockChangesDestroyEnvironment(c *gc.C) {166 // Setup environment167 s.setUpInstances(c)168 // lock environment: can't destroy locked environment169 s.BlockAllChanges(c, "TestBlockChangesDestroyEnvironment")170 err := common.DestroyEnvironment(s.State, s.State.EnvironTag())171 s.AssertBlocked(c, err, "TestBlockChangesDestroyEnvironment")172 s.metricSender.CheckCalls(c, []jtesting.StubCall{})173}174type destroyTwoEnvironmentsSuite struct {175 testing.JujuConnSuite176 otherState *state.State177 otherEnvOwner names.UserTag178 otherEnvClient *client.Client179 metricSender *testMetricSender180}181var _ = gc.Suite(&destroyTwoEnvironmentsSuite{})182func (s *destroyTwoEnvironmentsSuite) SetUpTest(c *gc.C) {183 s.JujuConnSuite.SetUpTest(c)184 _, err := s.State.AddUser("jess", "jess", "", "test")185 c.Assert(err, jc.ErrorIsNil)186 s.otherEnvOwner = names.NewUserTag("jess")187 s.otherState = factory.NewFactory(s.State).MakeEnvironment(c, &factory.EnvParams{188 Owner: s.otherEnvOwner,189 Prepare: true,190 ConfigAttrs: jujutesting.Attrs{191 "state-server": false,192 },193 })194 s.AddCleanup(func(*gc.C) { s.otherState.Close() })195 // get the client for the other environment196 auth := apiservertesting.FakeAuthorizer{197 Tag: s.otherEnvOwner,198 EnvironManager: false,199 }200 s.otherEnvClient, err = client.NewClient(s.otherState, common.NewResources(), auth)201 c.Assert(err, jc.ErrorIsNil)202 s.metricSender = &testMetricSender{}203 s.PatchValue(common.SendMetrics, s.metricSender.SendMetrics)204}205func (s *destroyTwoEnvironmentsSuite) TestCleanupEnvironDocs(c *gc.C) {206 otherFactory := factory.NewFactory(s.otherState)207 otherFactory.MakeMachine(c, nil)208 m := otherFactory.MakeMachine(c, nil)209 otherFactory.MakeMachineNested(c, m.Id(), nil)210 err := common.DestroyEnvironment(s.otherState, s.otherState.EnvironTag())211 c.Assert(err, jc.ErrorIsNil)212 _, err = s.otherState.Environment()213 c.Assert(errors.IsNotFound(err), jc.IsTrue)214 _, err = s.State.Environment()215 c.Assert(err, jc.ErrorIsNil)216 c.Assert(s.otherState.EnsureEnvironmentRemoved(), jc.ErrorIsNil)217 s.metricSender.CheckCalls(c, []jtesting.StubCall{{FuncName: "SendMetrics"}})218}219func (s *destroyTwoEnvironmentsSuite) TestDifferentStateEnv(c *gc.C) {220 otherFactory := factory.NewFactory(s.otherState)221 otherFactory.MakeMachine(c, nil)222 m := otherFactory.MakeMachine(c, nil)223 otherFactory.MakeMachineNested(c, m.Id(), nil)224 // NOTE: pass in the main test State instance, which is 'bound'225 // to the state server environment.226 err := common.DestroyEnvironment(s.State, s.otherState.EnvironTag())227 c.Assert(err, jc.ErrorIsNil)228 _, err = s.otherState.Environment()229 c.Assert(errors.IsNotFound(err), jc.IsTrue)230 _, err = s.State.Environment()231 c.Assert(err, jc.ErrorIsNil)232 c.Assert(s.otherState.EnsureEnvironmentRemoved(), jc.ErrorIsNil)233 s.metricSender.CheckCalls(c, []jtesting.StubCall{{FuncName: "SendMetrics"}})234}235func (s *destroyTwoEnvironmentsSuite) TestDestroyStateServerAfterNonStateServerIsDestroyed(c *gc.C) {236 err := common.DestroyEnvironment(s.State, s.State.EnvironTag())237 c.Assert(err, gc.ErrorMatches, "failed to destroy environment: hosting 1 other environments")238 err = common.DestroyEnvironment(s.State, s.otherState.EnvironTag())239 c.Assert(err, jc.ErrorIsNil)240 err = common.DestroyEnvironment(s.State, s.State.EnvironTag())241 c.Assert(err, jc.ErrorIsNil)242 s.metricSender.CheckCalls(c, []jtesting.StubCall{{FuncName: "SendMetrics"}, {FuncName: "SendMetrics"}})243}244func (s *destroyTwoEnvironmentsSuite) TestCanDestroyNonBlockedEnv(c *gc.C) {245 bh := commontesting.NewBlockHelper(s.APIState)246 defer bh.Close()247 bh.BlockDestroyEnvironment(c, "TestBlockDestroyDestroyEnvironment")248 err := common.DestroyEnvironment(s.State, s.otherState.EnvironTag())249 c.Assert(err, jc.ErrorIsNil)250 err = common.DestroyEnvironment(s.State, s.State.EnvironTag())251 bh.AssertBlocked(c, err, "TestBlockDestroyDestroyEnvironment")252 s.metricSender.CheckCalls(c, []jtesting.StubCall{{FuncName: "SendMetrics"}})253}254type testMetricSender struct {255 jtesting.Stub256}257func (t *testMetricSender) SendMetrics(st *state.State) error {258 t.AddCall("SendMetrics")259 return nil260}...

Full Screen

Full Screen

checkCalls

Using AI Code Generation

copy

Full Screen

1func main() {2 mainObj.checkCalls()3}4func main() {5 mainObj.checkCalls()6}7func main() {8 mainObj.checkCalls()9}10func main() {11 mainObj.checkCalls()12}13func main() {14 mainObj.checkCalls()15}16func main() {17 mainObj.checkCalls()18}19func main() {20 mainObj.checkCalls()21}22func main() {23 mainObj.checkCalls()24}25func main() {26 mainObj.checkCalls()27}28func main() {29 mainObj.checkCalls()30}31func main() {32 mainObj.checkCalls()33}34func main() {35 mainObj.checkCalls()36}37func main() {38 mainObj.checkCalls()39}40func main() {41 mainObj.checkCalls()42}43func main() {

Full Screen

Full Screen

checkCalls

Using AI Code Generation

copy

Full Screen

1import (2func main() {3 fmt.Println(checkCalls(a, b, c, d, e, f, g, h, i, j, k, l))4}5import (6func main() {7 fmt.Println(checkCalls(a, b, c, d, e, f, g, h, i, j, k, l))8}9import (10func main() {11 fmt.Println(checkCalls(a, b, c, d, e, f, g

Full Screen

Full Screen

checkCalls

Using AI Code Generation

copy

Full Screen

1 func main() {2 m.checkCalls()3 }4 func main() {5 m.checkCalls()6 }7 func main() {8 m.checkCalls()9 }10 1.go:4:6: m.checkCalls undefined (type main has no field or method checkCalls)11 2.go:4:6: m.checkCalls undefined (type main has no field or method checkCalls)12 3.go:4:6: m.checkCalls undefined (type main has no field or method checkCalls)13 4.go:4:6: m.checkCalls undefined (type main has no field or method checkCalls)14 5.go:4:6: m.checkCalls undefined (type main has no field or method checkCalls)15 6.go:4:6: m.checkCalls undefined (type main has no field or method checkCalls)16 7.go:4:6: m.checkCalls undefined (type main has no field or method checkCalls)17 8.go:4:6: m.checkCalls undefined (type main has no field or method checkCalls)18 9.go:4:6: m.checkCalls undefined (type main has no field or method checkCalls)19 10.go:4:6: m.checkCalls undefined (type main has no field or method checkCalls)20 11.go:4:6: m.checkCalls undefined (type main has no field or method checkCalls)21 12.go:4:6: m.checkCalls undefined (type main has no field or method checkCalls)22 13.go:4:6: m.checkCalls undefined (type main has no field or method checkCalls)23 14.go:4:6: m.checkCalls undefined (type main has no field or method checkCalls)24 15.go:4:6: m.checkCalls undefined (type main has no field or method checkCalls)25 16.go:4:6: m.checkCalls undefined (type main has no field or method checkCalls)26 17.go:4:6: m.checkCalls undefined (type main has no field or method checkCalls)

Full Screen

Full Screen

checkCalls

Using AI Code Generation

copy

Full Screen

1import (2func main() {3 fmt.Println("a + b = ", a+b)4}5import (6func main() {7 fmt.Println("a + b = ", a+b)8}9import (10func main() {11 fmt.Println("a + b = ", a+b)12}13import (14func main() {15 fmt.Println("a + b = ", a+b)16}17import (18func main() {19 fmt.Println("a + b = ", a+b)20}21import (22func main() {23 fmt.Println("a + b = ", a+b)24}25import (26func main() {27 fmt.Println("a + b = ", a+b)28}29import (30func main() {31 fmt.Println("a + b = ", a+b)32}33import (34func main() {35 fmt.Println("a + b = ", a+b)36}37import (38func main() {

Full Screen

Full Screen

checkCalls

Using AI Code Generation

copy

Full Screen

1import (2func main() {3 fmt.Println("main package")4 myProject.CheckCalls()5}6import (7func main() {8 fmt.Println("main package")9 myProject.CheckCalls()10}11import (12func main() {13 fmt.Println("main package")14 myProject.CheckCalls()15}16import (17func CheckCalls() {18 fmt.Println("myProject package")19}20import (21func CheckCalls() {22 fmt.Println("myProject package")23}24import (25func CheckCalls() {26 fmt.Println("myProject package")27}28import (29func CheckCalls() {30 fmt.Println("myProject package")31}32import (33func CheckCalls() {34 fmt.Println("myProject package")35}36import (37func CheckCalls() {38 fmt.Println("myProject package")39}40import (41func CheckCalls() {42 fmt.Println("myProject package")43}44import (45func CheckCalls() {46 fmt.Println("myProject package")47}48import (49func CheckCalls() {50 fmt.Println("myProject package")51}52import (53func CheckCalls() {54 fmt.Println("myProject package")55}56import (57func CheckCalls() {58 fmt.Println("myProject package")59}60import (61func CheckCalls() {62 fmt.Println("myProject package")63}64import (65func CheckCalls() {66 fmt.Println("myProject package")67}68import (69func CheckCalls() {70 fmt.Println("myProject package")71}72import (73func CheckCalls() {74 fmt.Println("myProject package")75}76import (

Full Screen

Full Screen

checkCalls

Using AI Code Generation

copy

Full Screen

1import (2func main() {3 fmt.Println("before calling checkCalls, str is", str)4 str = checkCalls(str)5 fmt.Println("after calling checkCalls, str is", str)6}7func checkCalls(str string) string {8 fmt.Println("before calling checkCalls, str1 is", str1)9 str1 = checkCalls1(str1)10 fmt.Println("after calling checkCalls, str1 is", str1)11}12func checkCalls1(str1 string) string {13 fmt.Println("before calling checkCalls, str2 is", str2)14 str2 = checkCalls2(str2)15 fmt.Println("after calling checkCalls, str2 is", str2)16}17func checkCalls2(str2 string) string {18 fmt.Println("before calling checkCalls, str3 is", str3)19 str3 = checkCalls3(str3)20 fmt.Println("after calling checkCalls, str3 is", str3)21}22func checkCalls3(str3 string) string {23 fmt.Println("before calling checkCalls, str4 is", str4)24 str4 = checkCalls4(str4)25 fmt.Println("after calling checkCalls, str4 is", str4)26}27func checkCalls4(str4 string) string {28 fmt.Println("before calling checkCalls, str5 is", str5)29 str5 = checkCalls5(str5)30 fmt.Println("after calling checkCalls, str5 is", str5)31}32func checkCalls5(str5 string) string {33 fmt.Println("before calling checkCalls, str6 is", str6)34 str6 = checkCalls6(str6)35 fmt.Println("after calling checkCalls, str6 is", str6)36}37func checkCalls6(str6 string) string

Full Screen

Full Screen

checkCalls

Using AI Code Generation

copy

Full Screen

1import (2func main() {3 fmt.Println("Hello, playground")4 main.checkCalls()5}6import (7func main() {8 fmt.Println("Hello, playground")9 main.checkCalls()10}11import (12func main() {13 fmt.Println("Hello, playground")14 main.checkCalls()15}16import (17func main() {18 fmt.Println("Hello, playground")19 main.checkCalls()20}21import (22func main() {23 fmt.Println("Hello, playground")24 main.checkCalls()25}26import (27func main() {28 fmt.Println("Hello, playground")29 main.checkCalls()30}31import (

Full Screen

Full Screen

checkCalls

Using AI Code Generation

copy

Full Screen

1import (2func main() {3 fmt.Println("Hello World")4}5import (6func main() {7 fmt.Println("Hello World")8}9import (10func main() {11 fmt.Println("Hello World")12}13import (14func main() {15 fmt.Println("Hello World")16}17import (18func main() {19 fmt.Println("Hello World")20}

Full Screen

Full Screen

Automation Testing Tutorials

Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.

LambdaTest Learning Hubs:

YouTube

You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.

Run Syzkaller automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Most used method in

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful