File: cuetest.go

package info (click to toggle)
golang-github-cue-lang-cue 0.14.2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 19,644 kB
  • sloc: makefile: 20; sh: 15
file content (151 lines) | stat: -rw-r--r-- 5,169 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
// Copyright 2021 The CUE 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 testing is a helper package for test packages in the CUE project.
// As such it should only be imported in _test.go files.
package cuetest

import (
	"fmt"
	"os"
	"regexp"
	"testing"

	"cuelang.org/go/internal/tdtest"
)

const (
	envUpdate = "CUE_UPDATE"

	// envNonIssues can be set to a regular expression which indicates what
	// issues we no longer consider issues, i.e. they should have been fixed.
	// This should generally result in tests that would otherwise be skipped no
	// longer being skipped.  e.g.  CUE_NON_ISSUES=. will cause all issue
	// tracker conditions (e.g. [golang.org/issues/1234]) to be considered
	// non-issues.
	envNonIssues = "CUE_NON_ISSUES"

	envFormatTxtar = "CUE_FORMAT_TXTAR"
)

var (
	// issuesConditions is a set of regular expressions that defines the set of
	// conditions that can be used to declare links to issues in various issue
	// trackers. e.g. in testscript condition form
	//
	//     [golang.org/issues/1234]
	//     [github.com/govim/govim/issues/4321]
	issuesConditions = []*regexp.Regexp{
		regexp.MustCompile(`^golang\.org/issues?/\d+$`),
		regexp.MustCompile(`^cuelang\.org/issues?/\d+$`),
	}
)

// UpdateGoldenFiles determines whether tests should update expected
// output in test files in the event of comparison failures (for example
// after a cmp failure in a testscript-based test). It is controlled by
// setting CUE_UPDATE to a non-empty string like "1" or "true". It
// corresponds to testscript.Params.UpdateGoldenFiles; see its docs for
// details.
//
// In some cases, tests might refuse to perform some updates by default.
// The special value "force" can be used to force updates in that situation.
var UpdateGoldenFiles = os.Getenv(envUpdate) != ""

// ForceUpdateGoldenFiles determines whether tests should update
// expected output in test files even when they would not be updated
// usually (for example when there are test regressions).
var ForceUpdateGoldenFiles = os.Getenv(envUpdate) == "force"

// FormatTxtar ensures that .cue files in txtar test archives are well
// formatted, updating the archive as required prior to running a test.
// It is controlled by setting CUE_FORMAT_TXTAR to a non-empty string like "true".
var FormatTxtar = os.Getenv(envFormatTxtar) != ""

// Condition adds support for CUE-specific testscript conditions within
// testscript scripts. Supported conditions include:
//
// [golang.org/issue/N] - evaluates to true unless CUE_NON_ISSUES
// is set to a regexp that matches the condition, i.e. golang.org/issue/N
// in this case
//
// [cuelang.org/issue/N] - evaluates to true unless CUE_NON_ISSUES
// is set to a regexp that matches the condition, i.e. cuelang.org/issue/N
// in this case
func Condition(cond string) (bool, error) {
	isIssue, nonIssue, err := checkIssueCondition(cond)
	if err != nil {
		return false, err
	}
	if isIssue {
		return !nonIssue, nil
	}
	return false, fmt.Errorf("unknown condition %v", cond)
}

// T is an alias to tdtest.T
type T = tdtest.T

func init() {
	tdtest.UpdateTests = UpdateGoldenFiles
}

// Run creates a new table-driven test using the CUE testing defaults.
//
// TODO: move this wrapper out to cuetdtest. Users should either use the full
// version of tdtest directly, or use the cuetdtest wrapper.
func Run[TC any](t *testing.T, table []TC, fn func(t *T, tc *TC)) {
	tdtest.Run(t, table, fn)
}

// IssueSkip causes the test t to be skipped unless the issue identified
// by s is deemed to be a non-issue by CUE_NON_ISSUES.
func IssueSkip(t *testing.T, s string) {
	t.Helper()

	isIssue, nonIssue, err := checkIssueCondition(s)
	if err != nil {
		t.Fatal(err)
	}
	if !isIssue {
		t.Fatalf("issue %q does not match a known issue pattern", s)
	}
	if nonIssue {
		t.Skipf("issue %s", s)
	}
}

// checkIssueCondition examines s to determine whether it is an issue
// condition, in which case isIssue is true. If isIssue, then we check
// CUE_NON_ISSUES for a match, in which case nonIssue is true (a value of true
// indicates roughly that we don't believe issue s is an issue any more). In
// case of any errors err is set.
func checkIssueCondition(s string) (isIssue bool, nonIssue bool, err error) {
	var r *regexp.Regexp
	if v := os.Getenv(envNonIssues); v != "" {
		r, err = regexp.Compile(v)
		if err != nil {
			return false, false, fmt.Errorf("failed to compile regexp %q specified via %v: %v", v, envNonIssues, err)
		}
	}
	for _, c := range issuesConditions {
		if c.MatchString(s) {
			isIssue = true
		}
	}
	if !isIssue {
		return false, false, nil
	}
	return isIssue, r != nil && r.MatchString(s), nil
}