diff --git a/README.md b/README.md index 212c6a8..c44aba9 100644 --- a/README.md +++ b/README.md @@ -27,8 +27,8 @@ DONE- Wir wollen folgendes unterstützen * Also rein nur Zuweisungen und Aufrüfe DONE + Blöcke löschen, daher DONE * if, else if und else branches leeren - + Condition Terme löschen vom ersten Condition level wenn mehr als ein Term da ist, für - * ifs und elseifs +DONE + Condition Terme löschen vom ersten Condition level wenn mehr als ein Term da ist, für +DONE * ifs und elseifs DONE - Jede Art von "Mutator" ist ein "Plugin" DONE- CMD DONE + Kann wie Golint auf alles mögliche angewendet werden: einzelne Dateien, Ordner, Packages, mit Patterns diff --git a/cmd/go-mutesting/main.go b/cmd/go-mutesting/main.go index c0765ee..2233f0f 100644 --- a/cmd/go-mutesting/main.go +++ b/cmd/go-mutesting/main.go @@ -21,6 +21,7 @@ import ( "github.com/zimmski/go-mutesting/importing" "github.com/zimmski/go-mutesting/mutator" _ "github.com/zimmski/go-mutesting/mutator/branch" + _ "github.com/zimmski/go-mutesting/mutator/expression" ) const ( diff --git a/mutator/expression/remove.go b/mutator/expression/remove.go new file mode 100644 index 0000000..bfa4b7c --- /dev/null +++ b/mutator/expression/remove.go @@ -0,0 +1,97 @@ +package expression + +import ( + "go/ast" + "go/token" + + "github.com/zimmski/go-mutesting/mutator" +) + +// MutatorRemoveTerm implements a mutator to remove expression terms +type MutatorRemoveTerm struct{} + +// NewMutatorRemoveTerm returns a new instance of a MutatorRemoveTerm mutator +func NewMutatorRemoveTerm() *MutatorRemoveTerm { + return &MutatorRemoveTerm{} +} + +func init() { + mutator.Register(MutatorRemoveTerm{}.String(), func() mutator.Mutator { + return NewMutatorRemoveTerm() + }) +} + +func (m *MutatorRemoveTerm) check(node ast.Node) (*ast.BinaryExpr, bool) { + n, ok := node.(*ast.BinaryExpr) + if !ok { + return nil, false + } + + _, xBinary := n.X.(*ast.BinaryExpr) + _, xParen := n.X.(*ast.ParenExpr) + _, yBinary := n.Y.(*ast.BinaryExpr) + _, yParen := n.Y.(*ast.ParenExpr) + if (!xBinary && !xParen) || (!yBinary && !yParen) { + return nil, false + } + + return n, true +} + +// Check validates how often a node can be mutated by a mutator +func (m *MutatorRemoveTerm) Check(node ast.Node) uint { + _, ok := m.check(node) + if !ok { + return 0 + } + + return 2 +} + +// Mutate mutates a given node if it can be mutated by the mutator. +// It first checks if the given node can be mutated by the mutator. If the node cannot be mutated, false is send into the given control channel and the method returns. If the node can be mutated, the current state of the node is saved. Afterwards the node is mutated, true is send into the given control channel and the method waits on the channel to continue the process. After receiving a value from the channel the original state of the node is restored, true is send into the given control channel and the method waits on the channel to continue the process. After receiving a value from the channel the method returns which finishes the mutation process. +func (m *MutatorRemoveTerm) Mutate(node ast.Node, changed chan bool) { + n, ok := m.check(node) + if !ok { + changed <- false + + return + } + + var r *ast.Ident + + switch n.Op { + case token.LAND: + r = ast.NewIdent("true") + case token.LOR: + r = ast.NewIdent("false") + } + + x := n.X + y := n.Y + + n.X = r + + changed <- true + <-changed + + n.X = x + + changed <- true + <-changed + + n.Y = r + + changed <- true + <-changed + + n.Y = y + + changed <- true + <-changed +} + +// String implements the String method of the Stringer interface +func (m MutatorRemoveTerm) String() string { + return "expression/remove" +} diff --git a/mutator/expression/remove_test.go b/mutator/expression/remove_test.go new file mode 100644 index 0000000..c5e072c --- /dev/null +++ b/mutator/expression/remove_test.go @@ -0,0 +1,22 @@ +package expression + +import ( + "testing" + + . "github.com/stretchr/testify/assert" + + "github.com/zimmski/go-mutesting/test" +) + +func TestMutateElse(t *testing.T) { + m := NewMutatorRemoveTerm() + NotNil(t, m) + + test.Mutator( + t, + "../../testdata/expression/remove.go", + "../../testdata/expression/remove.go", + m, + 6, + ) +} diff --git a/testdata/expression/remove.go b/testdata/expression/remove.go new file mode 100644 index 0000000..582507a --- /dev/null +++ b/testdata/expression/remove.go @@ -0,0 +1,23 @@ +// +build example-main + +package main + +import ( + "fmt" +) + +func main() { + i := 1 + + for i != 4 { + if i >= 1 && i <= 1 { + fmt.Println(i) + } else if (i >= 2 && i <= 2) || i == 2 { + fmt.Println(i * 2) + } else { + + } + + i++ + } +} diff --git a/testdata/expression/remove.go.0.go b/testdata/expression/remove.go.0.go new file mode 100644 index 0000000..e0b062f --- /dev/null +++ b/testdata/expression/remove.go.0.go @@ -0,0 +1,23 @@ +// +build example-main + +package main + +import ( + "fmt" +) + +func main() { + i := 1 + + for i != 4 { + if true && i <= 1 { + fmt.Println(i) + } else if (i >= 2 && i <= 2) || i == 2 { + fmt.Println(i * 2) + } else { + + } + + i++ + } +} diff --git a/testdata/expression/remove.go.1.go b/testdata/expression/remove.go.1.go new file mode 100644 index 0000000..41c67d3 --- /dev/null +++ b/testdata/expression/remove.go.1.go @@ -0,0 +1,23 @@ +// +build example-main + +package main + +import ( + "fmt" +) + +func main() { + i := 1 + + for i != 4 { + if i >= 1 && true { + fmt.Println(i) + } else if (i >= 2 && i <= 2) || i == 2 { + fmt.Println(i * 2) + } else { + + } + + i++ + } +} diff --git a/testdata/expression/remove.go.2.go b/testdata/expression/remove.go.2.go new file mode 100644 index 0000000..85125e3 --- /dev/null +++ b/testdata/expression/remove.go.2.go @@ -0,0 +1,23 @@ +// +build example-main + +package main + +import ( + "fmt" +) + +func main() { + i := 1 + + for i != 4 { + if i >= 1 && i <= 1 { + fmt.Println(i) + } else if false || i == 2 { + fmt.Println(i * 2) + } else { + + } + + i++ + } +} diff --git a/testdata/expression/remove.go.3.go b/testdata/expression/remove.go.3.go new file mode 100644 index 0000000..894ec39 --- /dev/null +++ b/testdata/expression/remove.go.3.go @@ -0,0 +1,23 @@ +// +build example-main + +package main + +import ( + "fmt" +) + +func main() { + i := 1 + + for i != 4 { + if i >= 1 && i <= 1 { + fmt.Println(i) + } else if (i >= 2 && i <= 2) || false { + fmt.Println(i * 2) + } else { + + } + + i++ + } +} diff --git a/testdata/expression/remove.go.4.go b/testdata/expression/remove.go.4.go new file mode 100644 index 0000000..accf243 --- /dev/null +++ b/testdata/expression/remove.go.4.go @@ -0,0 +1,23 @@ +// +build example-main + +package main + +import ( + "fmt" +) + +func main() { + i := 1 + + for i != 4 { + if i >= 1 && i <= 1 { + fmt.Println(i) + } else if (true && i <= 2) || i == 2 { + fmt.Println(i * 2) + } else { + + } + + i++ + } +} diff --git a/testdata/expression/remove.go.5.go b/testdata/expression/remove.go.5.go new file mode 100644 index 0000000..47640df --- /dev/null +++ b/testdata/expression/remove.go.5.go @@ -0,0 +1,23 @@ +// +build example-main + +package main + +import ( + "fmt" +) + +func main() { + i := 1 + + for i != 4 { + if i >= 1 && i <= 1 { + fmt.Println(i) + } else if (i >= 2 && true) || i == 2 { + fmt.Println(i * 2) + } else { + + } + + i++ + } +}