blob: 87f56810de01dcac0d6e6298e4631b1264dde928 [file] [log] [blame]
// Copyright 2025 The LUCI 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 lucicfg
import (
"context"
"os"
"path/filepath"
"testing"
"go.chromium.org/luci/common/testing/truth/assert"
"go.chromium.org/luci/lucicfg/pkg"
)
// TestPkg executes package tests (testdata/pkg/*, one per subdirectory).
func TestPkg(t *testing.T) {
t.Parallel()
dirs, err := os.ReadDir(filepath.Join("testdata", "pkg"))
assert.NoErr(t, err)
gotExpectationErrors := false
for _, dir := range dirs {
t.Run(dir.Name(), func(t *testing.T) {
if ok := runPkgTest(t, filepath.Join("testdata", "pkg", dir.Name())); !ok {
gotExpectationErrors = true
}
})
}
if gotExpectationErrors {
t.Errorf("\n\n"+
"========================================================\n"+
"If you want to update expectations stored in *.star run:\n"+
"$ %s=1 go test .\n"+
"========================================================", RegenEnvVar)
}
}
// runPkgTest runs main.star of some single package.
//
// Returns false if the output expectation needs to be regenerated.
func runPkgTest(t *testing.T, dir string) bool {
// Note: avoid t.Parallel() because we want the test to finish synchronously
// in TestPkg to check gotExpectationErrors.
main := filepath.Join(dir, "main.star")
ctx := context.Background()
blob, err := os.ReadFile(main)
assert.NoErr(t, err)
body := string(blob)
expectErrExct := readCommentBlock(body, expectErrorsHeader)
expectErrLike := readCommentBlock(body, expectErrorsLikeHeader)
expectCfg := readCommentBlock(body, expectConfigsHeader)
if expectErrExct != "" && expectErrLike != "" {
t.Errorf("Cannot use %q and %q at the same time", expectErrorsHeader, expectErrorsLikeHeader)
return true
}
var repoMgr pkg.RepoManager
depsDir := filepath.Join(dir, "remote")
if _, err := os.Stat(depsDir); err == nil {
repoMgr = &pkg.TestRepoManager{Root: depsDir}
}
var state *State
entry, err := pkg.EntryOnDisk(ctx, main, repoMgr)
// Verify formatter is initialized..
if err == nil && entry.Local.Formatter != nil {
err = entry.Local.Formatter.CheckValid(ctx)
if err == nil {
_, err = entry.Local.Formatter.RewriterForPath(ctx, "main.star")
}
}
if err == nil {
state, err = Generate(ctx, Inputs{
Entry: entry,
// Don't spit out "# This file is generated by lucicfg" headers.
testOmitHeader: true,
// Do not put frequently changing version string into test outputs.
testVersion: "1.1.1",
})
}
// If test was expected to fail, make sure it did, in an expected way.
if expectErrExct != "" || expectErrLike != "" {
checkExpectedErrs(t, err, expectErrExct, expectErrLike)
return true
}
// Otherwise just report all errors (if any) to Mr. T.
reportErr(t, err)
if err != nil {
return true // the error has been reported already
}
// If was expecting to see some configs, assert we did see them.
if expectCfg != "" {
return checkOrRegenExpectedOut(t, main, &state.Output, expectCfg)
}
return true
}