blob: 233cc9b19f10811021f3c650e57502c6d2fef41d [file] [log] [blame]
// Copyright 2020 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 cmd
import (
"bufio"
"bytes"
"context"
"fmt"
"io/ioutil"
"os"
"path"
"path/filepath"
goruntime "runtime"
"strings"
"testing"
"github.com/rogpeppe/go-internal/goproxytest"
"github.com/rogpeppe/go-internal/gotooltest"
"github.com/rogpeppe/go-internal/testscript"
"github.com/rogpeppe/go-internal/txtar"
"cuelang.org/go/cue/errors"
"cuelang.org/go/cue/parser"
"cuelang.org/go/internal/cuetest"
)
const (
homeDirName = ".user-home"
)
// TestLatest checks that the examples match the latest language standard,
// even if still valid in backwards compatibility mode.
func TestLatest(t *testing.T) {
root := filepath.Join("testdata", "script")
filepath.Walk(root, func(fullpath string, info os.FileInfo, err error) error {
if !strings.HasSuffix(fullpath, ".txt") ||
strings.HasPrefix(filepath.Base(fullpath), "fix") {
return nil
}
a, err := txtar.ParseFile(fullpath)
if err != nil {
t.Error(err)
return nil
}
if bytes.HasPrefix(a.Comment, []byte("!")) {
return nil
}
for _, f := range a.Files {
t.Run(path.Join(fullpath, f.Name), func(t *testing.T) {
if !strings.HasSuffix(f.Name, ".cue") {
return
}
v := parser.FromVersion(parser.Latest)
_, err := parser.ParseFile(f.Name, f.Data, v)
if err != nil {
w := &bytes.Buffer{}
fmt.Fprintf(w, "\n%s:\n", fullpath)
errors.Print(w, err, nil)
t.Error(w.String())
}
})
}
return nil
})
}
func TestScript(t *testing.T) {
srv, err := goproxytest.NewServer(filepath.Join("testdata", "mod"), "")
if err != nil {
t.Fatalf("cannot start proxy: %v", err)
}
p := testscript.Params{
Dir: filepath.Join("testdata", "script"),
UpdateScripts: cuetest.UpdateGoldenFiles,
Setup: func(e *testscript.Env) error {
// Set up a home dir within work dir with a . prefix so that the
// Go/CUE pattern ./... does not descend into it.
home := filepath.Join(e.WorkDir, homeDirName)
if err := os.Mkdir(home, 0777); err != nil {
return err
}
e.Vars = append(e.Vars,
"GOPROXY="+srv.URL,
"GONOSUMDB=*", // GOPROXY is a private proxy
homeEnvName()+"="+home,
)
return nil
},
Condition: cuetest.Condition,
}
if err := gotooltest.Setup(&p); err != nil {
t.Fatal(err)
}
testscript.Run(t, p)
}
// TestScriptDebug takes a single testscript file and then runs it within the
// same process so it can be used for debugging. It runs the first cue command
// it finds.
//
// Usage Comment out t.Skip() and set file to test.
func TestX(t *testing.T) {
t.Skip()
const path = "./testdata/script/eval_e.txt"
check := func(err error) {
t.Helper()
if err != nil {
t.Fatal(err)
}
}
tmpdir, err := ioutil.TempDir("", "cue-script")
check(err)
defer os.Remove(tmpdir)
a, err := txtar.ParseFile(filepath.FromSlash(path))
check(err)
for _, f := range a.Files {
name := filepath.Join(tmpdir, f.Name)
check(os.MkdirAll(filepath.Dir(name), 0777))
check(ioutil.WriteFile(name, f.Data, 0666))
}
cwd, err := os.Getwd()
check(err)
defer func() { _ = os.Chdir(cwd) }()
_ = os.Chdir(tmpdir)
for s := bufio.NewScanner(bytes.NewReader(a.Comment)); s.Scan(); {
cmd := s.Text()
cmd = strings.TrimLeft(cmd, "! ")
if strings.HasPrefix(cmd, "exec ") {
cmd = cmd[len("exec "):]
}
if !strings.HasPrefix(cmd, "cue ") {
continue
}
// TODO: Ugly hack to get args. Do more principled parsing.
var args []string
for _, a := range strings.Split(cmd, " ")[1:] {
args = append(args, strings.Trim(a, "'"))
}
c, err := New(args)
check(err)
b := &bytes.Buffer{}
c.SetOutput(b)
err = c.Run(context.Background())
// Always create an error to show
t.Error(err, "\n", b.String())
return
}
t.Fatal("NO COMMAND FOUND")
}
func TestMain(m *testing.M) {
// Setting inTest causes filenames printed in error messages
// to be normalized so the output looks the same on Unix
// as Windows.
os.Exit(testscript.RunMain(m, map[string]func() int{
"cue": MainTest,
}))
}
// homeEnvName extracts the logic from os.UserHomeDir to get the
// name of the environment variable that should be used when
// seting the user's home directory
func homeEnvName() string {
switch goruntime.GOOS {
case "windows":
return "USERPROFILE"
case "plan9":
return "home"
default:
return "HOME"
}
}