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

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

commit 7f00f7fa19668a84aab96dfac647bba31a5f1143
Author: Hoshea <[email protected]>
AuthorDate: Tue Mar 2 21:27:19 2021 +0800

    Implement the verification of query
---
 commands/verify/verify.go                | 53 ++++++++++++++++++++++++++++----
 e2e.yaml                                 | 28 +++++++++++++++++
 internal/components/verifier/verifier.go | 50 +++++++++++++-----------------
 internal/config/globalConfig.go          |  2 ++
 internal/util/utils.go                   | 18 +++++++++++
 5 files changed, 116 insertions(+), 35 deletions(-)

diff --git a/commands/verify/verify.go b/commands/verify/verify.go
index 91f37bf..3f53183 100644
--- a/commands/verify/verify.go
+++ b/commands/verify/verify.go
@@ -18,9 +18,10 @@
 package verify
 
 import (
-       "fmt"
-
        "github.com/apache/skywalking-infra-e2e/internal/components/verifier"
+       "github.com/apache/skywalking-infra-e2e/internal/config"
+       "github.com/apache/skywalking-infra-e2e/internal/logger"
+       "github.com/apache/skywalking-infra-e2e/internal/util"
 
        "github.com/spf13/cobra"
 )
@@ -41,10 +42,50 @@ var Verify = &cobra.Command{
        Use:   "verify",
        Short: "verify if the actual data match the expected data",
        RunE: func(cmd *cobra.Command, args []string) error {
-               if actual != "" && expected != "" {
-                       return verifier.VerifyDataFile(actual, expected)
+               if expected != "" {
+                       return verifySingleCase(expected, actual, query)
                }
-               fmt.Println("Not implemented.")
-               return nil
+               // If there is no given flags.
+               return verifyAccordingConfig()
        },
 }
+
+func verifySingleCase(expectedFile, actualFile, query string) error {
+       expectedData, err := util.ReadFileContent(expectedFile)
+       if err != nil {
+               logger.Log.Error("failed to read the expected data file")
+               return err
+       }
+
+       if actualFile != "" {
+               if err = verifier.VerifyDataFile(actualFile, expectedData); err 
!= nil {
+                       logger.Log.Warnf("failed to verify the output: %s\n", 
actualFile)
+               } else {
+                       logger.Log.Infof("verified the output: %s\n", 
actualFile)
+               }
+       } else if query != "" {
+               if err = verifier.VerifyQuery(query, expectedData); err != nil {
+                       logger.Log.Warnf("failed to verify the output: %s\n", 
query)
+               } else {
+                       logger.Log.Infof("verified the output: %s\n", query)
+               }
+       }
+       return nil
+}
+
+func verifyAccordingConfig() error {
+       if config.GlobalConfig.Error != nil {
+               return config.GlobalConfig.Error
+       }
+
+       e2eConfig := config.GlobalConfig.E2EConfig
+
+       for _, v := range e2eConfig.Verify {
+               if v.Expected != "" {
+                       verifySingleCase(v.Expected, v.Actual, v.Query)
+               } else {
+                       logger.Log.Error("the expected data file is not 
specified")
+               }
+       }
+       return nil
+}
diff --git a/e2e.yaml b/e2e.yaml
new file mode 100644
index 0000000..37281fa
--- /dev/null
+++ b/e2e.yaml
@@ -0,0 +1,28 @@
+# 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.
+
+# This config file can be used to test.
+
+verify:
+  - actual: test/verify/1.actual.yaml
+    expected: test/verify/1.expected.yaml
+  - actual: test/verify/2.actual.yaml
+    expected: test/verify/2.expected.yaml
+  - actual: test/verify/1.actual.yaml
+    expected: test/verify/2.expected.yaml
+  - actual: test/verify/2.actual.yaml
+    expected: test/verify/1.expected.yaml
\ No newline at end of file
diff --git a/internal/components/verifier/verifier.go 
b/internal/components/verifier/verifier.go
index 2f4675a..ed15361 100644
--- a/internal/components/verifier/verifier.go
+++ b/internal/components/verifier/verifier.go
@@ -14,14 +14,13 @@
 // KIND, either express or implied.  See the License for the
 // specific language governing permissions and limitations
 // under the License.
+
 package verifier
 
 import (
        "bytes"
-       "errors"
        "fmt"
 
-       "github.com/apache/skywalking-infra-e2e/internal/logger"
        "github.com/apache/skywalking-infra-e2e/internal/util"
        "github.com/apache/skywalking-infra-e2e/third-party/go/template"
 
@@ -30,9 +29,10 @@ import (
 )
 
 // MismatchError is the error type returned by the verify functions.
-// Then the caller will know if there is a mismatch.
+// It contains the diff content.
 type MismatchError struct {
-       Err error
+       Err  error
+       diff string
 }
 
 func (e *MismatchError) Unwrap() error { return e.Err }
@@ -41,65 +41,57 @@ func (e *MismatchError) Error() string {
        if e == nil {
                return "<nil>"
        }
-       return "the actual data does not match the expected data"
+       return e.diff
 }
 
 // VerifyDataFile reads the actual data from the file and verifies.
-func VerifyDataFile(actualFile, expectedFile string) error {
+func VerifyDataFile(actualFile, expectedData string) error {
        actualData, err := util.ReadFileContent(actualFile)
        if err != nil {
-               logger.Log.Error("failed to read the actual data file")
-               return err
+               return fmt.Errorf("failed to read the actual data file: %v", 
err)
        }
 
-       expectedTemplate, err := util.ReadFileContent(expectedFile)
+       return verify(actualData, expectedData)
+}
+
+// VerifyQuery gets the actual data from the query and then verifies.
+func VerifyQuery(query, expectedData string) error {
+       queryResult, err := util.ExecuteCommand(query)
        if err != nil {
-               logger.Log.Error("failed to read the expected data file")
-               return err
+               return fmt.Errorf("failed to execute the query: %v", err)
        }
 
-       return verify(actualData, expectedTemplate)
-}
+       // TODO: ensure that the query result has the same format as expected 
data
 
-// VerifyQuery gets the actual data from the query and then verifies.
-func VerifyQuery(query, expectedFile string) error {
-       return errors.New("not implemented")
+       return verify(queryResult, expectedData)
 }
 
 // verify checks if the actual data match the expected template.
-// It will print the diff if the actual data does not match.
 func verify(actualData, expectedTemplate string) error {
        var actual interface{}
        if err := yaml.Unmarshal([]byte(actualData), &actual); err != nil {
-               logger.Log.Error("failed to unmarshal actual data")
-               return err
+               return fmt.Errorf("failed to unmarshal actual data: %v", err)
        }
 
        tmpl, err := 
template.New("test").Funcs(funcMap()).Parse(expectedTemplate)
        if err != nil {
-               logger.Log.Error("failed to parse template")
-               return err
+               return fmt.Errorf("failed to parse template: %v", err)
        }
 
        var b bytes.Buffer
        if err := tmpl.Execute(&b, actual); err != nil {
-               logger.Log.Error("failed to execute template")
-               return err
+               return fmt.Errorf("failed to execute template: %v", err)
        }
 
        var expected interface{}
        if err := yaml.Unmarshal(b.Bytes(), &expected); err != nil {
-               logger.Log.Error("failed to unmarshal expected data")
-               return err
+               return fmt.Errorf("failed to unmarshal expected data: %v", err)
        }
 
        if !cmp.Equal(expected, actual) {
                // TODO: use a custom Reporter (suggested by the comment of 
cmp.Diff)
                diff := cmp.Diff(expected, actual)
-               fmt.Println(diff)
-               return &MismatchError{}
+               return &MismatchError{diff: diff}
        }
-
-       logger.Log.Info("the actual data matches the expected data")
        return nil
 }
diff --git a/internal/config/globalConfig.go b/internal/config/globalConfig.go
index f8c1334..c2bf184 100644
--- a/internal/config/globalConfig.go
+++ b/internal/config/globalConfig.go
@@ -20,6 +20,7 @@ package config
 
 import (
        "fmt"
+       "github.com/apache/skywalking-infra-e2e/internal/logger"
        "io/ioutil"
 
        "gopkg.in/yaml.v2"
@@ -57,4 +58,5 @@ func ReadGlobalConfigFile(configFilePath string) {
 
        GlobalConfig.E2EConfig = e2eConfigObject
        GlobalConfig.Error = nil
+       logger.Log.Info("load the e2e config successfully")
 }
diff --git a/internal/util/utils.go b/internal/util/utils.go
index 0c2a2f0..ab97c3c 100644
--- a/internal/util/utils.go
+++ b/internal/util/utils.go
@@ -19,6 +19,7 @@
 package util
 
 import (
+       "bytes"
        "errors"
        "io/ioutil"
        "os"
@@ -52,3 +53,20 @@ func ReadFileContent(filename string) (string, error) {
        }
        return "", errors.New("the file does not exist")
 }
+
+// ExecuteCommand executes the given command and returns the result.
+// TODO: consider security issues.
+func ExecuteCommand(cmd string) (string, error) {
+       command := exec.Command(cmd)
+       outinfo := bytes.Buffer{}
+       command.Stdout = &outinfo
+
+       if err := command.Start(); err != nil {
+               return "", err
+       }
+       if err := command.Wait(); err != nil {
+               return "", err
+       } else {
+               return outinfo.String(), nil
+       }
+}

Reply via email to