Skip to content

Commit 1f93bdf

Browse files
committed
Add integ test for http server
This fixes #40 Signed-off-by: Bennet Huber <[email protected]>
1 parent 49c1933 commit 1f93bdf

File tree

9 files changed

+862
-8
lines changed

9 files changed

+862
-8
lines changed

README.md

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,17 +73,22 @@ First, enable the HTTP server from the command line,
7373
GOFAIL_HTTP="127.0.0.1:1234" ./cmd
7474
```
7575

76-
77-
Activate a failpoint with curl,
76+
Activate a single failpoint with curl,
7877

7978
```sh
8079
$ curl http://127.0.0.1:1234/SomeFuncString -XPUT -d'return("hello")'
8180
```
8281

82+
Activate multiple failpoints atomically with the special `/failpoints` endpoint. The payload is the same as for `GOFAIL_FAILPOINTS` above:
83+
84+
```sh
85+
$ curl http://127.0.0.1:1234/failpoints -XPUT -d'failpoint1=return("hello");failpoint2=sleep(10)'
86+
```
87+
8388
List the failpoints,
8489

8590
```sh
86-
$ curl http://127.0.0.1:1234/SomeFuncString=return("hello")
91+
$ curl http://127.0.0.1:1234/SomeFuncString
8792
```
8893

8994
Retrieve the execution count of a failpoint,

examples/cmd/cmd.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,16 +27,18 @@ GOFAIL_HTTP=:22381 go run cmd.go
2727
curl -L http://localhost:22381
2828
2929
curl \
30-
-L http://localhost:22381/github.com/coreos/gofail/examples/ExampleLabels \
30+
-L http://localhost:22381/ExampleLabels \
3131
-X PUT -d'return'
3232
3333
curl \
34-
-L http://localhost:22381/github.com/coreos/gofail/examples/ExampleLabels \
34+
-L http://localhost:22381/ExampleLabels \
3535
-X DELETE
3636
*/
3737

3838
func main() {
3939
for {
40+
log.Println(examples.ExampleFunc())
41+
log.Println(examples.ExampleOneLineFunc())
4042
log.Println(examples.ExampleLabelsFunc())
4143
time.Sleep(time.Second)
4244
}

integration/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Integration Tests
22

33
Each directory contains a scenario
4-
5-
- sleep: the enabling and disabling of a failpoint won't be delayed due to an ongoing sleep() action
4+
* sleep: the enabling and disabling of a failpoint won't be delayed due to an ongoing sleep() action
5+
* server: exercises the HTTP failpoint control API and checks basic functionality

integration/makefile.mk

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ run-all-integration-tests:
88
# we compile and execute all integration tests
99
# add new integration test targets here
1010
$(MAKE) run-integration-test-sleep
11+
$(MAKE) run-integration-test-server
1112

1213
# we disable all failpoints
1314
$(MAKE) gofail-disable
@@ -19,10 +20,17 @@ clean-all-integration-tests: clean-integration-test-sleep gofail-disable
1920
.PHONY: gofail-enable
2021
gofail-enable: build-gofail
2122
$(GOFAIL_BINARY) enable ./integration/sleep/failpoints
23+
$(GOFAIL_BINARY) enable ./integration/server/failpoints
2224

2325
.PHONY: gofail-disable
2426
gofail-disable: build-gofail
25-
${GOFAIL_BINARY} disable ./integration/sleep/failpoints
27+
$(GOFAIL_BINARY) disable ./integration/sleep/failpoints
28+
$(GOFAIL_BINARY) disable ./integration/server/failpoints
29+
30+
# run integration test - server
31+
.PHONY: run-integration-test-server
32+
run-integration-test-server:
33+
cd ./integration/server && go test -v .
2634

2735
# run integration test - sleep
2836
.PHONY: run-integration-test-sleep
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package failpoints
2+
3+
func ExampleFunc() string {
4+
// gofail: var ExampleString string
5+
// return ExampleString
6+
return "example"
7+
}
8+
9+
func ExampleOneLineFunc() string {
10+
// gofail: var ExampleOneLine struct{}
11+
return "abc"
12+
}
13+
14+
func ExampleLabelsFunc() string {
15+
i := 0
16+
s := ""
17+
// gofail: myLabel:
18+
for i < 5 {
19+
s = s + "i"
20+
i++
21+
for j := 0; j < 5; j++ {
22+
s = s + "j"
23+
// gofail: var ExampleLabels struct{}
24+
// continue myLabel
25+
}
26+
}
27+
return s
28+
}

integration/server/go.mod

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
module go.etcd.io/gofail/integration/server
2+
3+
go 1.22
4+
5+
toolchain go1.22.10
6+
7+
require github.com/stretchr/testify v1.10.0
8+
9+
require (
10+
github.com/davecgh/go-spew v1.1.1 // indirect
11+
github.com/pmezard/go-difflib v1.0.0 // indirect
12+
go.etcd.io/gofail v0.1.1-0.20240328162059-93c579a86c46 // indirect
13+
gopkg.in/yaml.v3 v3.0.1 // indirect
14+
)
15+
16+
replace go.etcd.io/gofail => ./../../

integration/server/go.sum

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
2+
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
3+
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
4+
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
5+
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
6+
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
7+
go.etcd.io/gofail v0.1.1-0.20240328162059-93c579a86c46 h1:q2duvcm+tRj5lNb5RcDQ6QTs6n9Ou0L0p/74jEJwQaE=
8+
go.etcd.io/gofail v0.1.1-0.20240328162059-93c579a86c46/go.mod h1:UD5kxjMWxJacjLWHSqGM3zn4a9ItpE06Eg7ttpm0Lhs=
9+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
10+
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
11+
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

integration/server/main.go

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
package main
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
"go.etcd.io/gofail/integration/server/failpoints"
7+
"log"
8+
"net/http"
9+
"os"
10+
"reflect"
11+
"strings"
12+
)
13+
14+
var funcMap = map[string]interface{}{
15+
"ExampleFunc": failpoints.ExampleFunc,
16+
"ExampleOneLineFunc": failpoints.ExampleOneLineFunc,
17+
"ExampleLabelsFunc": failpoints.ExampleLabelsFunc,
18+
}
19+
20+
func callFuncByName(name string, args []string) (interface{}, error) {
21+
fn, exists := funcMap[name]
22+
if !exists {
23+
return nil, fmt.Errorf("function %s does not exist", name)
24+
}
25+
26+
fnValue := reflect.ValueOf(fn)
27+
expectedNArgs := fnValue.Type().NumIn()
28+
gotNArgs := len(args)
29+
if expectedNArgs != gotNArgs {
30+
return nil, fmt.Errorf("wrong number of arguments for function %s. "+
31+
"Expected %d, got %d", name, expectedNArgs, gotNArgs)
32+
}
33+
34+
in := make([]reflect.Value, len(args))
35+
for i, arg := range args {
36+
in[i] = reflect.ValueOf(arg)
37+
}
38+
39+
result := fnValue.Call(in)
40+
if len(result) == 0 {
41+
return nil, nil
42+
}
43+
return result[0].Interface(), nil
44+
}
45+
46+
func handler(w http.ResponseWriter, r *http.Request) {
47+
log.Printf("received request: %v", r)
48+
pathParts := strings.Split(r.URL.Path, "/")
49+
if len(pathParts) < 3 {
50+
http.Error(w, "invalid URL path", http.StatusBadRequest)
51+
return
52+
}
53+
funcName := pathParts[2]
54+
args := r.URL.Query()["args"]
55+
56+
result, err := callFuncByName(funcName, args)
57+
if err != nil {
58+
http.Error(w, err.Error(), http.StatusBadRequest)
59+
return
60+
}
61+
62+
response, err := json.Marshal(result)
63+
if err != nil {
64+
http.Error(w, "failed to marshal response", http.StatusInternalServerError)
65+
return
66+
}
67+
68+
w.Header().Set("Content-Type", "application/json")
69+
_, err = w.Write(response)
70+
if err != nil {
71+
http.Error(w, "failed to write response", http.StatusInternalServerError)
72+
}
73+
}
74+
75+
func main() {
76+
if len(os.Args) < 2 {
77+
log.Fatal("Port number is required as a command line argument")
78+
}
79+
port := os.Args[1]
80+
81+
http.HandleFunc("/call/", handler)
82+
log.Printf("Starting server on :%s", port)
83+
log.Fatal(http.ListenAndServe(":"+port, nil))
84+
}

0 commit comments

Comments
 (0)