From 9bfa0172f57d9f19989e94824f947c33f8d9a052 Mon Sep 17 00:00:00 2001 From: Anthony Romano Date: Fri, 15 Apr 2016 00:18:24 -0700 Subject: [PATCH] test, clientv3: run examples as integration tests --- clientv3/example_cluster_test.go | 2 +- clientv3/example_kv_test.go | 33 +++++++++++------- clientv3/example_lease_test.go | 21 ++++++++---- clientv3/main_test.go | 57 ++++++++++++++++++++++++++++++++ clientv3/txn_test.go | 4 --- pkg/testutil/leak_test.go | 6 +++- test | 4 ++- 7 files changed, 101 insertions(+), 26 deletions(-) create mode 100644 clientv3/main_test.go diff --git a/clientv3/example_cluster_test.go b/clientv3/example_cluster_test.go index 891bbaf8e..86076d25b 100644 --- a/clientv3/example_cluster_test.go +++ b/clientv3/example_cluster_test.go @@ -37,7 +37,7 @@ func ExampleCluster_memberList() { log.Fatal(err) } fmt.Println("members:", len(resp.Members)) - // members: 3 + // Output: members: 3 } func ExampleCluster_memberAdd() { diff --git a/clientv3/example_kv_test.go b/clientv3/example_kv_test.go index 1ee0a6060..2eb4a634c 100644 --- a/clientv3/example_kv_test.go +++ b/clientv3/example_kv_test.go @@ -33,13 +33,11 @@ func ExampleKV_put() { defer cli.Close() ctx, cancel := context.WithTimeout(context.Background(), requestTimeout) - resp, err := cli.Put(ctx, "sample_key", "sample_value") + _, err = cli.Put(ctx, "sample_key", "sample_value") cancel() if err != nil { log.Fatal(err) } - fmt.Println("current revision:", resp.Header.Revision) // revision start at 1 - // current revision: 2 } func ExampleKV_get() { @@ -66,7 +64,7 @@ func ExampleKV_get() { for _, ev := range resp.Kvs { fmt.Printf("%s : %s\n", ev.Key, ev.Value) } - // foo : bar + // Output: foo : bar } func ExampleKV_getWithRev() { @@ -79,7 +77,7 @@ func ExampleKV_getWithRev() { } defer cli.Close() - _, err = cli.Put(context.TODO(), "foo", "bar1") + presp, err := cli.Put(context.TODO(), "foo", "bar1") if err != nil { log.Fatal(err) } @@ -89,7 +87,7 @@ func ExampleKV_getWithRev() { } ctx, cancel := context.WithTimeout(context.Background(), requestTimeout) - resp, err := cli.Get(ctx, "foo", clientv3.WithRev(2)) + resp, err := cli.Get(ctx, "foo", clientv3.WithRev(presp.Header.Revision)) cancel() if err != nil { log.Fatal(err) @@ -97,7 +95,7 @@ func ExampleKV_getWithRev() { for _, ev := range resp.Kvs { fmt.Printf("%s : %s\n", ev.Key, ev.Value) } - // foo : bar1 + // Output: foo : bar1 } func ExampleKV_getSortedPrefix() { @@ -128,6 +126,7 @@ func ExampleKV_getSortedPrefix() { for _, ev := range resp.Kvs { fmt.Printf("%s : %s\n", ev.Key, ev.Value) } + // Output: // key_2 : value // key_1 : value // key_0 : value @@ -144,13 +143,23 @@ func ExampleKV_delete() { defer cli.Close() ctx, cancel := context.WithTimeout(context.Background(), requestTimeout) - resp, err := cli.Delete(ctx, "key", clientv3.WithPrefix()) - cancel() + defer cancel() + + // count keys about to be deleted + gresp, err := cli.Get(ctx, "key", clientv3.WithPrefix()) if err != nil { log.Fatal(err) } - fmt.Println("Deleted", resp.Deleted, "keys") - // Deleted n keys + + // delete the keys + dresp, err := cli.Delete(ctx, "key", clientv3.WithPrefix()) + if err != nil { + log.Fatal(err) + } + + fmt.Println("Deleted all keys:", int64(len(gresp.Kvs)) == dresp.Deleted) + // Output: + // Deleted all keys: true } func ExampleKV_compact() { @@ -215,7 +224,7 @@ func ExampleKV_txn() { for _, ev := range gresp.Kvs { fmt.Printf("%s : %s\n", ev.Key, ev.Value) } - // key : XYZ + // Output: key : XYZ } func ExampleKV_do() { diff --git a/clientv3/example_lease_test.go b/clientv3/example_lease_test.go index 4b2bcb98c..8d289a8d1 100644 --- a/clientv3/example_lease_test.go +++ b/clientv3/example_lease_test.go @@ -76,7 +76,7 @@ func ExampleLease_revoke() { log.Fatal(err) } fmt.Println("number of keys:", len(gresp.Kvs)) - // number of keys: 0 + // Output: number of keys: 0 } func ExampleLease_keepAlive() { @@ -100,10 +100,14 @@ func ExampleLease_keepAlive() { } // the key 'foo' will be kept forever - _, err = cli.KeepAlive(context.TODO(), resp.ID) - if err != nil { - log.Fatal(err) + ch, kaerr := cli.KeepAlive(context.TODO(), resp.ID) + if kaerr != nil { + log.Fatal(kaerr) } + + ka := <-ch + fmt.Println("ttl:", ka.TTL) + // Output: ttl: 5 } func ExampleLease_keepAliveOnce() { @@ -127,8 +131,11 @@ func ExampleLease_keepAliveOnce() { } // to renew the lease only once - _, err = cli.KeepAliveOnce(context.TODO(), resp.ID) - if err != nil { - log.Fatal(err) + ka, kaerr := cli.KeepAliveOnce(context.TODO(), resp.ID) + if kaerr != nil { + log.Fatal(kaerr) } + + fmt.Println("ttl:", ka.TTL) + // Output: ttl: 5 } diff --git a/clientv3/main_test.go b/clientv3/main_test.go new file mode 100644 index 000000000..896053e3a --- /dev/null +++ b/clientv3/main_test.go @@ -0,0 +1,57 @@ +// Copyright 2016 CoreOS, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package clientv3_test + +import ( + "os" + "regexp" + "strings" + "testing" + + "github.com/coreos/etcd/integration" + "github.com/coreos/etcd/pkg/testutil" +) + +// TestMain sets up an etcd cluster if running the examples. +func TestMain(m *testing.M) { + useCluster := true // default to running all tests + for _, arg := range os.Args { + if strings.HasPrefix(arg, "-test.run=") { + exp := strings.Split(arg, "=")[1] + match, err := regexp.MatchString(exp, "Example") + useCluster = (err == nil && match) || strings.Contains(exp, "Example") + break + } + } + + v := 0 + if useCluster { + cfg := integration.ClusterConfig{Size: 3} + clus := integration.NewClusterV3(nil, &cfg) + endpoints = make([]string, 3) + for i := range endpoints { + endpoints[i] = clus.Client(i).Endpoints()[0] + } + v = m.Run() + clus.Terminate(nil) + } else { + v = m.Run() + } + + if v == 0 && testutil.CheckLeakedGoroutine() { + os.Exit(1) + } + os.Exit(v) +} diff --git a/clientv3/txn_test.go b/clientv3/txn_test.go index 24fe068e2..78ca0447d 100644 --- a/clientv3/txn_test.go +++ b/clientv3/txn_test.go @@ -17,13 +17,9 @@ package clientv3 import ( "testing" "time" - - "github.com/coreos/etcd/pkg/testutil" ) func TestTxnPanics(t *testing.T) { - defer testutil.AfterTest(t) - kv := NewKV(&Client{}) errc := make(chan string) diff --git a/pkg/testutil/leak_test.go b/pkg/testutil/leak_test.go index 062e4fa55..98290788d 100644 --- a/pkg/testutil/leak_test.go +++ b/pkg/testutil/leak_test.go @@ -20,10 +20,13 @@ import ( "testing" ) +// so tests pass if given a -run that doesn't include TestSample +var ranSample = false + func TestMain(m *testing.M) { m.Run() isLeaked := CheckLeakedGoroutine() - if !isLeaked { + if ranSample && !isLeaked { fmt.Fprintln(os.Stderr, "expected leaky goroutines but none is detected") os.Exit(1) } @@ -32,6 +35,7 @@ func TestMain(m *testing.M) { func TestSample(t *testing.T) { defer AfterTest(t) + ranSample = true for range make([]struct{}, 100) { go func() { select {} diff --git a/test b/test index 3b4878301..0c2a0a16d 100755 --- a/test +++ b/test @@ -57,7 +57,8 @@ fi function unit_tests { echo "Running tests..." - go test -timeout 3m ${COVER} ${RACE} -cpu 1,2,4 $@ ${TEST} + # only -run=Test so examples can run in integration tests + go test -timeout 3m ${COVER} ${RACE} -cpu 1,2,4 -run=Test $@ ${TEST} } function integration_tests { @@ -66,6 +67,7 @@ function integration_tests { go test -timeout 15m -v -cpu 1,2,4 $@ ${REPO_PATH}/integration go test -timeout 10m -v ${RACE} -cpu 1,2,4 $@ ${REPO_PATH}/clientv3/integration go test -timeout 1m -v -cpu 1,2,4 $@ ${REPO_PATH}/contrib/raftexample + go test -timeout 1m -v ${RACE} -cpu 1,2,4 -run=Example $@ ${TEST} } function fmt_tests {