You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@skywalking.apache.org by ke...@apache.org on 2021/10/12 06:31:43 UTC

[skywalking-infra-e2e] branch main updated: Support reusing `verify.cases` (#53)

This is an automated email from the ASF dual-hosted git repository.

kezhenxu94 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/skywalking-infra-e2e.git


The following commit(s) were added to refs/heads/main by this push:
     new 7cedc9f  Support reusing `verify.cases` (#53)
7cedc9f is described below

commit 7cedc9f23f71cf59a589e67f3968b5026f71cdca
Author: mrproliu <74...@qq.com>
AuthorDate: Tue Oct 12 14:31:38 2021 +0800

    Support reusing `verify.cases` (#53)
---
 docs/en/setup/Configuration-File.md          | 18 +++++-
 examples/compose/e2e.yaml                    |  4 +-
 examples/kind/e2e.yaml                       |  4 +-
 examples/reusing_cases/base-compose.yml      | 57 +++++++++++++++++
 examples/reusing_cases/docker-compose.yml    | 41 ++++++++++++
 examples/{compose => reusing_cases}/e2e.yaml | 23 ++-----
 examples/reusing_cases/simple-cases.yaml     | 20 ++++++
 internal/config/e2eConfig.go                 | 11 +++-
 internal/config/globalConfig.go              | 56 ++++++++++++++++
 internal/util/config_test.go                 | 95 ++++++++++++++++++++++++++++
 10 files changed, 302 insertions(+), 27 deletions(-)

diff --git a/docs/en/setup/Configuration-File.md b/docs/en/setup/Configuration-File.md
index 67ae11f..eefc5d8 100644
--- a/docs/en/setup/Configuration-File.md
+++ b/docs/en/setup/Configuration-File.md
@@ -108,12 +108,14 @@ After the `Trigger` step is finished, running test cases.
 verify:
   retry:            # verify with retry strategy
     count: 10       # max retry count
-    interval: 10s   # the duration between two attempts, e.g. 10s, 1m.
+    interval: 10s   # the interval between two attempts, e.g. 10s, 1m.
   cases:            # verify test cases
     - actual: path/to/actual.yaml       # verify by actual file path
       expected: path/to/expected.yaml   # excepted content file path
     - query: echo 'foo'                 # verify by command execute output
       expected: path/to/expected.yaml   # excepted content file path
+    - includes:      # including cases
+        - path/to/cases.yaml            # cases file path
 ```
 
 The test cases are executed in the order of declaration from top to bottom, If the execution fails, and the retry strategy is exceeded, the process is deemed to have failed.
@@ -177,6 +179,20 @@ In order to make the program easier for users to read and use, some code convers
 |-------|------------|-------|------|
 |b64enc|Base64 encode|{{ b64enc "Foo" }}|Zm9v|
 
+### Reuse cases
+
+You could include multiple cases into one single E2E verify, It's helpful for reusing the same verify cases.
+
+Here is the reused verify cases, and using `includes` configuration item to include this into E2E config.
+
+```yaml
+cases:
+   - actual: path/to/actual.yaml       # verify by actual file path
+     expected: path/to/expected.yaml   # excepted content file path
+   - query: echo 'foo'                 # verify by command execute output
+     expected: path/to/expected.yaml   # excepted content file path
+```
+
 ## Cleanup
 
 After the E2E finished, how to clean up the environment.
diff --git a/examples/compose/e2e.yaml b/examples/compose/e2e.yaml
index 7eaaed2..7b2b159 100644
--- a/examples/compose/e2e.yaml
+++ b/examples/compose/e2e.yaml
@@ -49,8 +49,8 @@ verify:
   retry:
     # max retry count
     count: 10
-    # the interval between two retries, in millisecond.
-    interval: 10000
+    # the interval between two attempts, e.g. 10s, 1m.
+    interval: 10s
   cases:
     - actual: ../../test/verify/1.actual.yaml
       expected: ../../test/verify/1.expected.yaml
diff --git a/examples/kind/e2e.yaml b/examples/kind/e2e.yaml
index 107ffea..dfa017e 100644
--- a/examples/kind/e2e.yaml
+++ b/examples/kind/e2e.yaml
@@ -60,8 +60,8 @@ verify:
   retry:
     # max retry count
     count: 10
-    # the interval between two retries, in millisecond.
-    interval: 10000
+    # the interval between two attempts, e.g. 10s, 1m.
+    interval: 10s
   cases:
     - actual: ../../test/verify/1.actual.yaml
       expected: ../../test/verify/1.expected.yaml
diff --git a/examples/reusing_cases/base-compose.yml b/examples/reusing_cases/base-compose.yml
new file mode 100644
index 0000000..bb8ddc1
--- /dev/null
+++ b/examples/reusing_cases/base-compose.yml
@@ -0,0 +1,57 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You 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.
+
+version: '2.1'
+
+services:
+  oap:
+    image: apache/skywalking-oap-server:8.5.0-es6
+    expose:
+      - 11800
+      - 12800
+      - 10051
+      - 5005
+    networks:
+      - e2e
+    restart: on-failure
+    environment:
+      SW_CLUSTER_ZK_HOST_PORT: zk:2181
+      SW_STORAGE_ES_CLUSTER_NODES: es:9200
+      SW_JDBC_URL: jdbc:mysql://mysql:3306/swtest
+      SW_STORAGE_INFLUXDB_URL: http://influxdb:8086
+      JAVA_OPTS: >-
+        -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005
+    healthcheck:
+      test: ["CMD", "sh", "-c", "nc -zn 127.0.0.1 11800"]
+      interval: 5s
+      timeout: 60s
+      retries: 120
+
+  ui:
+    image: apache/skywalking-ui:8.5.0
+    expose:
+      - 8080
+    networks:
+      - e2e
+    environment:
+      - SW_OAP_ADDRESS=oap:12800
+    healthcheck:
+      test: [ "CMD", "sh", "-c", "nc -zn 127.0.0.1 8080" ]
+      interval: 5s
+      timeout: 60s
+      retries: 120
+
+networks:
+  e2e:
diff --git a/examples/reusing_cases/docker-compose.yml b/examples/reusing_cases/docker-compose.yml
new file mode 100644
index 0000000..56310c0
--- /dev/null
+++ b/examples/reusing_cases/docker-compose.yml
@@ -0,0 +1,41 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You 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.
+
+version: '2.1'
+
+services:
+
+  oap:
+    extends:
+      file: base-compose.yml
+      service: oap
+    ports:
+      - 12800
+    environment:
+      SW_STORAGE: h2
+      SW_SEARCHABLE_ALARM_TAG_KEYS: level,receivers
+
+  ui:
+    extends:
+      file: base-compose.yml
+      service: ui
+    ports:
+      - 8080
+    depends_on:
+      oap:
+        condition: service_healthy
+
+networks:
+  e2e:
diff --git a/examples/compose/e2e.yaml b/examples/reusing_cases/e2e.yaml
similarity index 60%
copy from examples/compose/e2e.yaml
copy to examples/reusing_cases/e2e.yaml
index 7eaaed2..2b3a0c1 100644
--- a/examples/compose/e2e.yaml
+++ b/examples/reusing_cases/e2e.yaml
@@ -19,19 +19,6 @@ setup:
   env: compose
   file: docker-compose.yml
   timeout: 1200
-  init-system-environment: env
-  steps:
-    - name: install yq
-      command: |
-        if ! type "yq" > /dev/null; then
-          mkdir -p /tmp/skywalking-infra-e2e/bin && cd /tmp/skywalking-infra-e2e
-          mkdir yq && cd yq
-          wget -O yq.tar.gz https://github.com/mikefarah/yq/archive/v4.11.1.tar.gz
-          tar -zxf yq.tar.gz --strip=1
-          go install && go build -ldflags -s && mv yq ../bin/yq
-          export PATH="$PATH:/tmp/skywalking-infra-e2e/bin"
-          echo "success to install yq"
-        fi
 
 cleanup:
   # always never success failure
@@ -49,12 +36,10 @@ verify:
   retry:
     # max retry count
     count: 10
-    # the interval between two retries, in millisecond.
-    interval: 10000
+    # the interval between two attempts, e.g. 10s, 1m.
+    interval: 10s
   cases:
-    - actual: ../../test/verify/1.actual.yaml
-      expected: ../../test/verify/1.expected.yaml
-    - actual: ../../test/verify/2.actual.yaml
-      expected: ../../test/verify/2.expected.yaml
+    - includes:
+        - simple-cases.yaml
     - query: swctl --display yaml --base-url=http://127.0.0.1:${oap_12800}/graphql service ls
       expected: ../../test/verify/3.expected.yaml
\ No newline at end of file
diff --git a/examples/reusing_cases/simple-cases.yaml b/examples/reusing_cases/simple-cases.yaml
new file mode 100644
index 0000000..5d245ef
--- /dev/null
+++ b/examples/reusing_cases/simple-cases.yaml
@@ -0,0 +1,20 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You 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.
+
+cases:
+  - actual: ../../test/verify/1.actual.yaml
+    expected: ../../test/verify/1.expected.yaml
+  - actual: ../../test/verify/2.actual.yaml
+    expected: ../../test/verify/2.expected.yaml
\ No newline at end of file
diff --git a/internal/config/e2eConfig.go b/internal/config/e2eConfig.go
index 60084e1..6b8b974 100644
--- a/internal/config/e2eConfig.go
+++ b/internal/config/e2eConfig.go
@@ -84,9 +84,10 @@ type Trigger struct {
 }
 
 type VerifyCase struct {
-	Query    string `yaml:"query"`
-	Actual   string `yaml:"actual"`
-	Expected string `yaml:"expected"`
+	Query    string   `yaml:"query"`
+	Actual   string   `yaml:"actual"`
+	Expected string   `yaml:"expected"`
+	Includes []string `yaml:"includes"`
 }
 
 type VerifyRetryStrategy struct {
@@ -94,6 +95,10 @@ type VerifyRetryStrategy struct {
 	Interval interface{} `yaml:"interval"`
 }
 
+type ReusingCases struct {
+	Cases []VerifyCase `yaml:"cases"`
+}
+
 // GetActual resolves the absolute file path of the actual data file.
 func (v *VerifyCase) GetActual() string {
 	return util.ResolveAbs(v.Actual)
diff --git a/internal/config/globalConfig.go b/internal/config/globalConfig.go
index 07be475..1eaf198 100644
--- a/internal/config/globalConfig.go
+++ b/internal/config/globalConfig.go
@@ -63,6 +63,62 @@ func ReadGlobalConfigFile() {
 		return
 	}
 
+	// convert verify
+	if err := convertVerify(&GlobalConfig.E2EConfig.Verify); err != nil {
+		GlobalConfig.Error = err
+		return
+	}
+
 	GlobalConfig.Error = nil
 	logger.Log.Info("load the e2e config successfully")
 }
+
+func convertVerify(verify *Verify) error {
+	// convert cases
+	result := make([]VerifyCase, 0)
+	for _, c := range verify.Cases {
+		cases, err := convertSingleCase(c)
+		if err != nil {
+			return err
+		}
+		result = append(result, cases...)
+	}
+	verify.Cases = result
+	return nil
+}
+
+func convertSingleCase(verifyCase VerifyCase) ([]VerifyCase, error) {
+	if len(verifyCase.Includes) > 0 && (verifyCase.Expected != "" || verifyCase.Query != "") {
+		return nil, fmt.Errorf("include and query/expected only support selecting one of them in a case")
+	}
+	if len(verifyCase.Includes) == 0 {
+		return []VerifyCase{verifyCase}, nil
+	}
+	result := make([]VerifyCase, 0)
+	for _, include := range verifyCase.Includes {
+		includePath := util.ResolveAbs(include)
+
+		if !util.PathExist(includePath) {
+			return nil, fmt.Errorf("reuse case config file %s not exist", includePath)
+		}
+
+		data, err := ioutil.ReadFile(includePath)
+		if err != nil {
+			return nil, fmt.Errorf("reuse case config file %s error: %s", includePath, err)
+		}
+
+		r := &ReusingCases{}
+		if err := yaml.Unmarshal(data, r); err != nil {
+			return nil, fmt.Errorf("unmarshal reuse case config file %s error: %s", includePath, err)
+		}
+
+		for _, c := range r.Cases {
+			cases, err := convertSingleCase(c)
+			if err != nil {
+				return nil, err
+			}
+			result = append(result, cases...)
+		}
+	}
+	return result, nil
+}
diff --git a/internal/util/config_test.go b/internal/util/config_test.go
new file mode 100644
index 0000000..bfb9464
--- /dev/null
+++ b/internal/util/config_test.go
@@ -0,0 +1,95 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you 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 util
+
+import (
+	"fmt"
+	"path/filepath"
+	"testing"
+)
+
+func TestResolveAbs(t *testing.T) {
+	configAbsPath, _ := filepath.Abs("config.go")
+	tests := []struct {
+		CfgPath string
+		Path    string
+		Exists  bool
+	}{
+		{
+			configAbsPath,
+			"./config.go",
+			true,
+		},
+		{
+			"not_exist/e2e.yaml",
+			configAbsPath,
+			true,
+		},
+		{
+			"config.go",
+			"./config.go",
+			true,
+		},
+		{
+			"./config.go",
+			"config.go",
+			true,
+		},
+		{
+			"./config.go",
+			"go.mod",
+			false,
+		},
+		{
+			"./config.go",
+			"",
+			false,
+		},
+		{
+			"../../examples/compose/e2e.yaml",
+			"env",
+			true,
+		},
+		{
+			"../../examples/compose/e2e.yaml",
+			"./env",
+			true,
+		},
+		{
+			"not_exists/e2e.yaml",
+			"./config.go",
+			false,
+		},
+		{
+			"not_exists/e2e.yaml",
+			"config.go",
+			false,
+		},
+	}
+
+	for _, tt := range tests {
+		t.Run(fmt.Sprintf("cfg path: %s, verify path: %s", tt.CfgPath, tt.Path), func(t *testing.T) {
+			CfgFile = tt.CfgPath
+			result := ResolveAbs(tt.Path)
+			if PathExist(result) != tt.Exists {
+				t.Errorf("path %s not exists", result)
+			}
+		})
+	}
+}