mirror of https://github.com/istio/istio.io.git
129 lines
4.6 KiB
Go
129 lines
4.6 KiB
Go
// Copyright Istio Authors
|
|
//
|
|
// 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 istioio
|
|
|
|
import (
|
|
"regexp"
|
|
"strings"
|
|
"text/scanner"
|
|
"unicode"
|
|
)
|
|
|
|
const (
|
|
tokenVerifierKey = "token"
|
|
)
|
|
|
|
// verifier for output of a shell command.
|
|
type verifier func(ctx Context, name, expectedOutput, actualOutput string)
|
|
|
|
// verifiers supported by in the command scripts.
|
|
var verifiers = map[string]verifier{
|
|
tokenVerifierKey: verifyTokens,
|
|
"contains": verifyContains,
|
|
"notContains": verifyNotContains,
|
|
"lineRegex": verifyLineRegex,
|
|
}
|
|
|
|
// verifyTokens tokenizes the output and compares against the tokens from the given file.
|
|
func verifyTokens(ctx Context, name, expectedOutput, actualOutput string) {
|
|
// Tokenize the content and the file.
|
|
expectedTokenLines := tokenize(expectedOutput)
|
|
actualTokenLines := tokenize(actualOutput)
|
|
|
|
if len(expectedTokenLines) != len(actualTokenLines) {
|
|
ctx.Fatalf("verification failed for command %s: line count: (expected %d, found %d). Expected:\n%s\nto match:\n%s",
|
|
name, len(expectedTokenLines), len(actualTokenLines), actualOutput, expectedOutput)
|
|
}
|
|
|
|
for lineIndex := 0; lineIndex < len(expectedTokenLines); lineIndex++ {
|
|
expectedTokens := expectedTokenLines[lineIndex]
|
|
actualTokens := actualTokenLines[lineIndex]
|
|
|
|
if len(expectedTokens) != len(actualTokens) {
|
|
ctx.Fatalf("verification failed for command %s [line %d]: token count (expected %d, found %d). Expected:\n%s\nto match:\n%s",
|
|
name, lineIndex, len(expectedTokens), len(actualTokens), actualOutput, expectedOutput)
|
|
}
|
|
|
|
for tokenIndex := 0; tokenIndex < len(expectedTokens); tokenIndex++ {
|
|
expectedToken := expectedTokens[tokenIndex]
|
|
if expectedToken == "?" {
|
|
// The value was a wildcard, matches anything.
|
|
continue
|
|
}
|
|
|
|
actualToken := actualTokens[tokenIndex]
|
|
if expectedToken != actualToken {
|
|
ctx.Fatalf("verification failed for command %s [line %d]: token %d (expected %s, found %s). Expected:\n%s\nto match:\n%s",
|
|
name, lineIndex, tokenIndex, expectedToken, actualToken, actualOutput, expectedOutput)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func tokenize(content string) [][]string {
|
|
inputLines := strings.Split(strings.TrimSpace(content), "\n")
|
|
tokenLines := make([][]string, 0)
|
|
|
|
for _, inputLine := range inputLines {
|
|
tokens := make([]string, 0)
|
|
|
|
var s scanner.Scanner
|
|
|
|
// Configure the token characters.
|
|
s.IsIdentRune = func(ch rune, i int) bool {
|
|
return ch == '_' || ch == '-' || ch == '.' || unicode.IsLetter(ch) || unicode.IsDigit(ch)
|
|
}
|
|
|
|
s.Init(strings.NewReader(inputLine))
|
|
for tok := s.Scan(); tok != scanner.EOF; tok = s.Scan() {
|
|
tokens = append(tokens, s.TokenText())
|
|
}
|
|
tokenLines = append(tokenLines, tokens)
|
|
}
|
|
return tokenLines
|
|
}
|
|
|
|
func verifyContains(ctx Context, name, expectedOutput, actualOutput string) {
|
|
if !strings.Contains(actualOutput, expectedOutput) {
|
|
ctx.Fatalf("verification failed for command %s: output does not contain expected text.\nExpected:\n%s\nOutput:\n%s",
|
|
name, expectedOutput, actualOutput)
|
|
}
|
|
}
|
|
|
|
func verifyNotContains(ctx Context, name, expectedOutput, actualOutput string) {
|
|
if strings.Contains(actualOutput, expectedOutput) {
|
|
ctx.Fatalf("verification failed for command %s: output contains not expected text.\nNot Expected:\n%s\nOutput:\n%s",
|
|
name, expectedOutput, actualOutput)
|
|
}
|
|
}
|
|
|
|
func verifyLineRegex(ctx Context, name, expectedOutput, actualOutput string) {
|
|
expectedOutputLines := strings.Split(strings.TrimSpace(expectedOutput), "\n")
|
|
actualOutputLines := strings.Split(strings.TrimSpace(actualOutput), "\n")
|
|
|
|
if len(expectedOutputLines) != len(actualOutputLines) {
|
|
ctx.Fatalf("verification failed for command %s: line count: (expected %d, found %d). Expected:\n%s\nto match:\n%s",
|
|
name, len(expectedOutputLines), len(actualOutputLines), actualOutput, expectedOutput)
|
|
}
|
|
|
|
for lineIndex := 0; lineIndex < len(expectedOutputLines); lineIndex++ {
|
|
if match, _ := regexp.MatchString(expectedOutputLines[lineIndex], actualOutputLines[lineIndex]); !match {
|
|
ctx.Fatalf("verification failed for command %s: output does not match expected regex.\nExpected:\n%s\nOutput:\n%s",
|
|
name, expectedOutputLines[lineIndex], actualOutputLines[lineIndex])
|
|
return
|
|
}
|
|
}
|
|
}
|