blob: 3307f43f602e8bd2f4d1afbabd70a0e8833e0b1c [file] [log] [blame]
// 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", sourceName)
}
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
}
var err error
for current := 1; current <= retryCount; current++ {
for _, v := range e2eConfig.Verify.Cases {
if v.GetExpected() != "" {
if err = verifySingleCase(v.GetExpected(), v.GetActual(), v.Query); err != nil {
break
}
} else {
return fmt.Errorf("the expected data file is not specified")
}
}
if err != nil && current != retryCount {
logger.Log.Warnf("verify case failure, will continue retry, %v", err)
time.Sleep(time.Duration(retryInterval) * time.Millisecond)
} else if err == nil {
return nil
}
}
return err
}