| // 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 verify |
| |
| import ( |
| "fmt" |
| "time" |
| |
| "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" |
| ) |
| |
| var ( |
| query string |
| actual string |
| expected string |
| ) |
| |
| func init() { |
| Verify.Flags().StringVarP(&query, "query", "q", "", "the query to get the actual data, the result of the query should in YAML format") |
| Verify.Flags().StringVarP(&actual, "actual", "a", "", "the actual data file, only YAML file format is supported") |
| Verify.Flags().StringVarP(&expected, "expected", "e", "", "the expected data file, only YAML file format is supported") |
| } |
| |
| 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 expected != "" { |
| return verifySingleCase(expected, actual, query) |
| } |
| // If there is no given flags. |
| return DoVerifyAccordingConfig() |
| }, |
| } |
| |
| func verifySingleCase(expectedFile, actualFile, query string) error { |
| expectedData, err := util.ReadFileContent(expectedFile) |
| if err != nil { |
| return fmt.Errorf("failed to read the expected data file: %v", err) |
| } |
| |
| var actualData, sourceName string |
| if actualFile != "" { |
| sourceName = actualFile |
| actualData, err = util.ReadFileContent(actualFile) |
| if err != nil { |
| return fmt.Errorf("failed to read the actual data file: %v", err) |
| } |
| } else if query != "" { |
| sourceName = query |
| actualData, err = util.ExecuteCommand(query) |
| if err != nil { |
| return fmt.Errorf("failed to execute the query: %s, output: %s, error: %v", query, actualData, err) |
| } |
| } |
| |
| if err = verifier.Verify(actualData, expectedData); err != nil { |
| if me, ok := err.(*verifier.MismatchError); ok { |
| return fmt.Errorf("failed to verify the output: %s, error: %v", sourceName, me.Error()) |
| } |
| return fmt.Errorf("failed to verify the output: %s, error: %v", sourceName, err) |
| } |
| logger.Log.Infof("verified the output: %s\n", sourceName) |
| return nil |
| } |
| |
| // DoVerifyAccordingConfig reads cases from the config file and verifies them. |
| func DoVerifyAccordingConfig() error { |
| if config.GlobalConfig.Error != nil { |
| return config.GlobalConfig.Error |
| } |
| |
| e2eConfig := config.GlobalConfig.E2EConfig |
| |
| retryCount := e2eConfig.Verify.RetryStrategy.Count |
| if retryCount <= 0 { |
| retryCount = 1 |
| } |
| retryInterval := e2eConfig.Verify.RetryStrategy.Interval |
| if retryInterval < 0 { |
| retryInterval = 1000 |
| } |
| |
| for idx, v := range e2eConfig.Verify.Cases { |
| if v.GetExpected() == "" { |
| return fmt.Errorf("the expected data file for case[%v] is not specified", idx) |
| } |
| for current := 1; current <= retryCount; current++ { |
| if err := verifySingleCase(v.GetExpected(), v.GetActual(), v.Query); err == nil { |
| break |
| } else if current != retryCount { |
| logger.Log.Warnf("verify case failure, will continue retry, %v", err) |
| time.Sleep(time.Duration(retryInterval) * time.Millisecond) |
| } else { |
| return err |
| } |
| } |
| } |
| |
| return nil |
| } |