<commit_before>// Copyright 2019 The Go Cloud Development Kit 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
//
//     https://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.

// The cmdtest package simplifies testing of command-line interfaces. It
// provides a simple, cross-platform, shell-like language to express command
// execution. It can compare actual output with the expected output, and can
// also update a file with new "golden" output that is deemed correct.
//
// Start using cmdtest by writing a test file with commands and expected output,
// giving it the extension ".ct". All test files in the same directory make up a
// test suite. See the TestSuite documentation for the syntax of test files.
//
// To test, first read the suite:
//
//    ts, err := cmdtest.Read("testdata")
//
// Then configure the resulting TestSuite by adding commands or enabling
// debugging features. Lastly, call TestSuite.Run with false to compare
// or true to update. Typically, this boolean will be the value of a flag:
//
//    var update = flag.Bool("update", false, "update test files with results")
//    ...
//    err := ts.Run(*update)
package cmdtest

import (
	"bufio"
	"bytes"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
	"strings"
	"sync"
	"testing"

	"github.com/google/go-cmp/cmp"
)

// A TestSuite contains a set of test files, each of which may contain multiple
// test cases. Use Read to build a TestSuite from all the test files in a
// directory. Then configure it and call Run.
//
// Format of a test file:
//
// Before the first line starting with a '$', empty lines and lines beginning with
// "#" are ignored.
//
// A sequence of consecutive lines starting with '$' begin a test case. These lines
// are commands to execute. See below for the valid commands.
//
// Lines following the '$' lines are command output (merged stdout and stderr).
// Output is always treated literally. After the command output there should be a
// blank line. Between that blank line and the next '$' line, empty lines and lines
// beginning with '#' are ignored. (Because of these rules, cmdtest cannot
// distinguish trailing blank lines in the output.)
//
// Syntax of a line beginning with '$': A sequence of space-separated words (no
// quoting is supported). The first word is the command, the rest are its args.
// If the next-to-last word is '<', the last word is interpreted as a file and
// becomes the standard input to the command. None of the built-in commands (see
// below) support input redirection, but commands defined with Program do.
//
// By default, commands are expected to succeed, and the test will fail
// otherwise. However, commands that are expected to fail can be marked
// with a " --> FAIL" suffix.
//
// The cases of a test file are executed in order, starting in a freshly
// created temporary directory.
//
// The built-in commands (initial contents of the Commands map) are:
//<commit_msg>tweak documentation<commit_after>// Copyright 2019 The Go Cloud Development Kit 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
//
//     https://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.

// The cmdtest package simplifies testing of command-line interfaces. It
// provides a simple, cross-platform, shell-like language to express command
// execution. It can compare actual output with the expected output, and can
// also update a file with new "golden" output that is deemed correct.
//
// Start using cmdtest by writing a test file with commands and expected output,
// giving it the extension ".ct". All test files in the same directory make up a
// test suite. See the TestSuite documentation for the syntax of test files.
//
// To test, first read the suite:
//
//    ts, err := cmdtest.Read("testdata")
//
// Then configure the resulting TestSuite by adding commands or enabling
// debugging features. Lastly, call TestSuite.Run with false to compare
// or true to update. Typically, this boolean will be the value of a flag:
//
//    var update = flag.Bool("update", false, "update test files with results")
//    ...
//    err := ts.Run(t, *update)
package cmdtest

import (
	"bufio"
	"bytes"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
	"strings"
	"sync"
	"testing"

	"github.com/google/go-cmp/cmp"
)

// A TestSuite contains a set of test files, each of which may contain multiple
// test cases. Use Read to build a TestSuite from all the test files in a
// directory. Then configure it and call Run.
//
// Format of a test file:
//
// Before the first line starting with a '$', empty lines and lines beginning with
// "#" are ignored.
//
// A sequence of consecutive lines starting with '$' begins a test case. These lines
// are commands to execute. See below for the valid commands.
//
// Lines following the '$' lines are command output (merged stdout and stderr).
// Output is always treated literally. After the command output there should be a
// blank line. Between that blank line and the next '$' line, empty lines and lines
// beginning with '#' are ignored. (Because of these rules, cmdtest cannot
// distinguish trailing blank lines in the output.)
//
// Syntax of a line beginning with '$': A sequence of space-separated words (no
// quoting is supported). The first word is the command, the rest are its args.
// If the next-to-last word is '<', the last word is interpreted as a file and
// becomes the standard input to the command. None of the built-in commands (see
// below) support input redirection, but commands defined with Program do.
//
// By default, commands are expected to succeed, and the test will fail
// otherwise. However, commands that are expected to fail can be marked
// with a " --> FAIL" suffix.
//
// The cases of a test file are executed in order, starting in a freshly
// created temporary directory.
//
// The built-in commands (initial contents of the Commands map) are:
//
{'fraction_non_alphanumeric': 0.09573224203449283, 'fraction_numerical': 0.00233849751534639, 'mean_word_length': 3.263551401869159, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 2, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2670264', 'n_tokens_mistral': 1800, 'n_tokens_neox': 1767, 'n_words': 984}