Skip to content

Commit

Permalink
Merge pull request #66 from henrybear327/fix/bad_type_issues
Browse files Browse the repository at this point in the history
Avoid __badType label being executed when the failpoint execution flow is not diverted and the type conversion is successful
  • Loading branch information
ahrtr authored May 14, 2024
2 parents c62db01 + 5f671c7 commit 8ce909e
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 27 deletions.
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,10 @@ The translated code looks something like,

```go
func someFunc() string {
if vSomeFuncString, __fpErr := __fp_SomeFuncString.Acquire(); __fpErr == nil { SomeFuncString, __fpTypeOK := vSomeFuncString.(string); if !__fpTypeOK { goto __badTypeSomeFuncString}
// this is called when the failpoint is triggered
return SomeFuncString; __badTypeSomeFuncString: __fp_SomeFuncString.BadType(vSomeFuncString, "string"); };
return "default"
if vSomeFuncString, __fpErr := __fp_SomeFuncString.Acquire(); __fpErr == nil { SomeFuncString, __fpTypeOK := vSomeFuncString.(string); if !__fpTypeOK { goto __badTypeSomeFuncString}
// this is called when the failpoint is triggered
return SomeFuncString; goto __nomockSomeFuncString; __badTypeSomeFuncString: __fp_SomeFuncString.BadType(vSomeFuncString, "string"); __nomockSomeFuncString: };
return "default"
}
```

Expand Down
4 changes: 2 additions & 2 deletions code/failpoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,8 @@ func (fp *Failpoint) hdr(varname string) string {
}

func (fp *Failpoint) footer() string {
return "; __badType" + fp.name + ": " +
fp.Runtime() + ".BadType(v" + fp.name + ", \"" + fp.varType + "\"); };"
return "; goto __nomock" + fp.name + "; __badType" + fp.name + ": " +
fp.Runtime() + ".BadType(v" + fp.name + ", \"" + fp.varType + "\"); __nomock" + fp.name + ": };"
}

func (fp *Failpoint) flushSingle(dst io.Writer) error {
Expand Down
4 changes: 2 additions & 2 deletions code/rewrite.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ func ToComments(wdst io.Writer, rsrc io.Reader) ([]*Failpoint, error) {
unmatchedBraces += opening - closing
if unmatchedBraces == 0 {
// strip off badType footer
lTrim = strings.Split(lTrim, "; __badType")[0]
lTrim = strings.Split(lTrim, "; goto __nomock")[0]
}
s := ws + "//" + wsPrefix(l, ws)[1:] + lTrim + "\n"
dst.WriteString(s)
Expand All @@ -114,7 +114,7 @@ func ToComments(wdst io.Writer, rsrc io.Reader) ([]*Failpoint, error) {
n := strings.Split(strings.Split(l, "__fp_")[1], ".")[0]
t := strings.Split(strings.Split(l, ".(")[1], ")")[0]
dst.WriteString(ws + pfx + " var " + n + " " + t + "\n")
if !strings.Contains(l, "; __badType") {
if !strings.Contains(l, "; goto __nomock") {
// not single liner
unmatchedBraces = 1
}
Expand Down
76 changes: 61 additions & 15 deletions code/rewrite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,20 +21,61 @@ import (
)

var examples = []struct {
code string
wfps int
code string
expectedGeneratedCode string
wfps int
}{
{"func f() {\n\t// gofail: var Test int\n\t// fmt.Println(Test)\n}", 1},
{"func f() {\n\t\t// gofail: var Test int\n\t\t// \tfmt.Println(Test)\n}", 1},
{"func f() {\n// gofail: var Test int\n// \tfmt.Println(Test)\n}", 1},
{"func f() {\n\t// gofail: var Test int\n\t// fmt.Println(Test)\n}\n", 1},
{"func f() {\n\t// gofail: var Test int\n\t// fmt.Println(Test)// return\n}\n", 1},
{"func f() {\n\t// gofail: var OneLineTest int\n}\n", 1},
{"func f() {\n\t// gofail: var Test int\n\t// fmt.Println(Test)\n\n\t// gofail: var Test2 int\n\t// fmt.Println(Test2)\n}\n", 2},
{"func f() {\n\t// gofail: var NoTypeTest struct{}\n\t// fmt.Println(`hi`)\n}\n", 1},
{"func f() {\n\t// gofail: var NoTypeTest struct{}\n}\n", 1},
{"func f() {\n\t// gofail: var NoTypeTest struct{}\n\t// fmt.Println(`hi`)\n\t// fmt.Println(`bye`)\n}\n", 1},
{`
{
"func f() {\n\t// gofail: var Test int\n\t// fmt.Println(Test)\n}",
"func f() {\n\tif vTest, __fpErr := __fp_Test.Acquire(); __fpErr == nil { Test, __fpTypeOK := vTest.(int); if !__fpTypeOK { goto __badTypeTest} \n\t\t fmt.Println(Test); goto __nomockTest; __badTypeTest: __fp_Test.BadType(vTest, \"int\"); __nomockTest: };\n}",
1,
},
{
"func f() {\n\t\t// gofail: var Test int\n\t\t// \tfmt.Println(Test)\n}",
"func f() {\n\t\tif vTest, __fpErr := __fp_Test.Acquire(); __fpErr == nil { Test, __fpTypeOK := vTest.(int); if !__fpTypeOK { goto __badTypeTest} \n\t\t\t \tfmt.Println(Test); goto __nomockTest; __badTypeTest: __fp_Test.BadType(vTest, \"int\"); __nomockTest: };\n}",
1,
},
{
"func f() {\n// gofail: var Test int\n// \tfmt.Println(Test)\n}",
"func f() {\nif vTest, __fpErr := __fp_Test.Acquire(); __fpErr == nil { Test, __fpTypeOK := vTest.(int); if !__fpTypeOK { goto __badTypeTest} \n\t \tfmt.Println(Test); goto __nomockTest; __badTypeTest: __fp_Test.BadType(vTest, \"int\"); __nomockTest: };\n}",
1,
},
{
"func f() {\n\t// gofail: var Test int\n\t// fmt.Println(Test)\n}\n",
"func f() {\n\tif vTest, __fpErr := __fp_Test.Acquire(); __fpErr == nil { Test, __fpTypeOK := vTest.(int); if !__fpTypeOK { goto __badTypeTest} \n\t\t fmt.Println(Test); goto __nomockTest; __badTypeTest: __fp_Test.BadType(vTest, \"int\"); __nomockTest: };\n}\n",
1},
{
"func f() {\n\t// gofail: var Test int\n\t// fmt.Println(Test)// return\n}\n",
"func f() {\n\tif vTest, __fpErr := __fp_Test.Acquire(); __fpErr == nil { Test, __fpTypeOK := vTest.(int); if !__fpTypeOK { goto __badTypeTest} \n\t\t fmt.Println(Test)// return; goto __nomockTest; __badTypeTest: __fp_Test.BadType(vTest, \"int\"); __nomockTest: };\n}\n",
1,
},
{
"func f() {\n\t// gofail: var OneLineTest int\n}\n",
"func f() {\n\tif vOneLineTest, __fpErr := __fp_OneLineTest.Acquire(); __fpErr == nil { _, __fpTypeOK := vOneLineTest.(int); if !__fpTypeOK { goto __badTypeOneLineTest} ; goto __nomockOneLineTest; __badTypeOneLineTest: __fp_OneLineTest.BadType(vOneLineTest, \"int\"); __nomockOneLineTest: };\n}\n",
1,
},
{
"func f() {\n\t// gofail: var Test int\n\t// fmt.Println(Test)\n\n\t// gofail: var Test2 int\n\t// fmt.Println(Test2)\n}\n",
"func f() {\n\tif vTest, __fpErr := __fp_Test.Acquire(); __fpErr == nil { Test, __fpTypeOK := vTest.(int); if !__fpTypeOK { goto __badTypeTest} \n\t\t fmt.Println(Test); goto __nomockTest; __badTypeTest: __fp_Test.BadType(vTest, \"int\"); __nomockTest: };\n\n\tif vTest2, __fpErr := __fp_Test2.Acquire(); __fpErr == nil { Test2, __fpTypeOK := vTest2.(int); if !__fpTypeOK { goto __badTypeTest2} \n\t\t fmt.Println(Test2); goto __nomockTest2; __badTypeTest2: __fp_Test2.BadType(vTest2, \"int\"); __nomockTest2: };\n}\n",
2,
},
{
"func f() {\n\t// gofail: var NoTypeTest struct{}\n\t// fmt.Println(`hi`)\n}\n",
"func f() {\n\tif vNoTypeTest, __fpErr := __fp_NoTypeTest.Acquire(); __fpErr == nil { _, __fpTypeOK := vNoTypeTest.(struct{}); if !__fpTypeOK { goto __badTypeNoTypeTest} \n\t\t fmt.Println(`hi`); goto __nomockNoTypeTest; __badTypeNoTypeTest: __fp_NoTypeTest.BadType(vNoTypeTest, \"struct{}\"); __nomockNoTypeTest: };\n}\n",
1,
},
{
"func f() {\n\t// gofail: var NoTypeTest struct{}\n}\n",
"func f() {\n\tif vNoTypeTest, __fpErr := __fp_NoTypeTest.Acquire(); __fpErr == nil { _, __fpTypeOK := vNoTypeTest.(struct{}); if !__fpTypeOK { goto __badTypeNoTypeTest} ; goto __nomockNoTypeTest; __badTypeNoTypeTest: __fp_NoTypeTest.BadType(vNoTypeTest, \"struct{}\"); __nomockNoTypeTest: };\n}\n",
1,
},
{
"func f() {\n\t// gofail: var NoTypeTest struct{}\n\t// fmt.Println(`hi`)\n\t// fmt.Println(`bye`)\n}\n",
"func f() {\n\tif vNoTypeTest, __fpErr := __fp_NoTypeTest.Acquire(); __fpErr == nil { _, __fpTypeOK := vNoTypeTest.(struct{}); if !__fpTypeOK { goto __badTypeNoTypeTest} \n\t\t fmt.Println(`hi`)\n\t\t fmt.Println(`bye`); goto __nomockNoTypeTest; __badTypeNoTypeTest: __fp_NoTypeTest.BadType(vNoTypeTest, \"struct{}\"); __nomockNoTypeTest: };\n}\n",
1,
},
{
`
func f() {
// gofail: labelTest:
for {
Expand All @@ -45,7 +86,10 @@ func f() {
}
}
}
`, 1},
`,
"\nfunc f() {\n\t/* gofail-label */ labelTest:\n\tfor {\n\t\tif g() {\n\t\t\tif vtestLabel, __fpErr := __fp_testLabel.Acquire(); __fpErr == nil { _, __fpTypeOK := vtestLabel.(struct{}); if !__fpTypeOK { goto __badTypetestLabel} \n\t\t\t\t continue labelTest; goto __nomocktestLabel; __badTypetestLabel: __fp_testLabel.BadType(vtestLabel, \"struct{}\"); __nomocktestLabel: };\n\t\t\treturn\n\t\t}\n\t}\n}\n",
1,
},
}

func TestToFailpoint(t *testing.T) {
Expand All @@ -63,6 +107,9 @@ func TestToFailpoint(t *testing.T) {
if len(strings.Split(dstOut, "\n")) != len(strings.Split(ex.code, "\n")) {
t.Fatalf("%d: bad line count %q", i, dstOut)
}
if ex.expectedGeneratedCode != dstOut {
t.Fatalf("expected generated code and actual generated code differs:\nExpected:\n%q\n\nActual:\n%q", ex.expectedGeneratedCode, dstOut)
}
}
}

Expand Down Expand Up @@ -90,5 +137,4 @@ func TestToComment(t *testing.T) {
t.Fatalf("%d: got %d failpoints but expected %d", i, len(fps), ex.wfps)
}
}

}
16 changes: 12 additions & 4 deletions doc/design.md
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ func ExampleOneLineFunc() string {
**Translated code**:
```
func ExampleOneLineFunc() string {
if vExampleOneLine, __fpErr := __fp_ExampleOneLine.Acquire(); __fpErr == nil { _, __fpTypeOK := vExampleOneLine.(struct{}); if !__fpTypeOK { goto __badTypeExampleOneLine} ; __badTypeExampleOneLine: __fp_ExampleOneLine.BadType(vExampleOneLine, "struct{}"); };
if vExampleOneLine, __fpErr := __fp_ExampleOneLine.Acquire(); __fpErr == nil { _, __fpTypeOK := vExampleOneLine.(struct{}); if !__fpTypeOK { goto __badTypeExampleOneLine} ; goto __nomockExampleOneLine; __badTypeExampleOneLine: __fp_ExampleOneLine.BadType(vExampleOneLine, "struct{}"); __nomockExampleOneLine: };
return "abc"
}
```
Expand All @@ -187,8 +187,10 @@ func ExampleOneLineFunc() string {
if !__fpTypeOK {
goto __badTypeExampleOneLine
}
goto __nomockExampleOneLine
__badTypeExampleOneLine:
__fp_ExampleOneLine.BadType(vExampleOneLine, "struct{}")
__nomockExampleOneLine:
}
return "abc"
}
Expand Down Expand Up @@ -223,7 +225,7 @@ The code `return ExampleString` is the customized code.
```
func ExampleFunc() string {
if vExampleString, __fpErr := __fp_ExampleString.Acquire(); __fpErr == nil { ExampleString, __fpTypeOK := vExampleString.(string); if !__fpTypeOK { goto __badTypeExampleString}
return ExampleString; __badTypeExampleString: __fp_ExampleString.BadType(vExampleString, "string"); };
return ExampleString; goto __nomockExampleString; __badTypeExampleString: __fp_ExampleString.BadType(vExampleString, "string"); __nomockExampleString: };
return "example"
}
```
Expand All @@ -237,8 +239,10 @@ func ExampleFunc() string {
goto __badTypeExampleString
}
return ExampleString
goto __nomockExampleString
__badTypeExampleString:
__fp_ExampleString.BadType(vExampleString, "string")
__nomockExampleString:
}
return "example"
}
Expand Down Expand Up @@ -267,7 +271,7 @@ There are two lines of customized code: `ExampleString = "Hello, " + ExampleStri
func ExampleFunc() string {
if vExampleString, __fpErr := __fp_ExampleString.Acquire(); __fpErr == nil { ExampleString, __fpTypeOK := vExampleString.(string); if !__fpTypeOK { goto __badTypeExampleString}
ExampleString = "Hello, " + ExampleString
return ExampleString; __badTypeExampleString: __fp_ExampleString.BadType(vExampleString, "string"); };
return ExampleString; goto __nomockExampleString; __badTypeExampleString: __fp_ExampleString.BadType(vExampleString, "string"); __nomockExampleString: };
return "example"
}
```
Expand All @@ -282,8 +286,10 @@ func ExampleFunc() string {
}
ExampleString = "Hello, " + ExampleString
return ExampleString
goto __nomockExampleString
__badTypeExampleString:
__fp_ExampleString.BadType(vExampleString, "string")
__nomockExampleString:
}
return "example"
}
Expand Down Expand Up @@ -326,7 +332,7 @@ func ExampleLabelsFunc() (s string) {
for j := 0; j < 5; j++ {
s = s + "j"
if vExampleLabels, __fpErr := __fp_ExampleLabels.Acquire(); __fpErr == nil { _, __fpTypeOK := vExampleLabels.(struct{}); if !__fpTypeOK { goto __badTypeExampleLabels}
continue myLabel; __badTypeExampleLabels: __fp_ExampleLabels.BadType(vExampleLabels, "struct{}"); };
continue myLabel; goto __nomockExampleLabels; __badTypeExampleLabels: __fp_ExampleLabels.BadType(vExampleLabels, "struct{}"); __nomockExampleLabels: };
}
}
return s
Expand All @@ -349,8 +355,10 @@ func ExampleLabelsFunc() (s string) {
goto __badTypeExampleLabels
}
continue myLabel
goto __nomockExampleLabels
__badTypeExampleLabels:
__fp_ExampleLabels.BadType(vExampleLabels, "struct{}")
__nomockExampleLabels:
}
}
}
Expand Down

0 comments on commit 8ce909e

Please sign in to comment.