| // Copyright 2020 The Chromium OS Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| package genparams |
| |
| import ( |
| "fmt" |
| "io/ioutil" |
| "os" |
| "testing" |
| |
| "github.com/google/go-cmp/cmp" |
| "github.com/kylelemons/godebug/diff" |
| |
| "chromiumos/tast/testutil" |
| ) |
| |
| // fakeTestingT is a fake implementation of TestingT. |
| // The zero value of fakeTestingT is ready to use. |
| type fakeTestingT struct { |
| // Errors is a list of error messages reported so far. |
| Errors []string |
| } |
| |
| func (t *fakeTestingT) Helper() {} |
| |
| func (t *fakeTestingT) Logf(format string, args ...interface{}) {} |
| |
| func (t *fakeTestingT) Errorf(format string, args ...interface{}) { |
| t.Errors = append(t.Errors, fmt.Sprintf(format, args...)) |
| } |
| |
| func (t *fakeTestingT) Fatalf(format string, args ...interface{}) { |
| t.Errorf(format, args...) |
| panic("fakeTestingT.Fatalf called") |
| } |
| |
| // callEnsure is a helper function to call Ensure. |
| // It calls Ensure twice, without TAST_GENERATE_UPDATE and with |
| // TAST_GENERATE_UPDATE. It returns errors reported from the first call and |
| // generated code from the second call. |
| func callEnsure(t *testing.T, code, params string) (errors []string, newCode string) { |
| // Create a temporary dir and chdir to it to make error messages deterministic. |
| wd, err := os.Getwd() |
| if err != nil { |
| t.Fatal(err) |
| } |
| td := testutil.TempDir(t) |
| defer os.RemoveAll(td) |
| os.Chdir(td) |
| defer os.Chdir(wd) |
| |
| const filename = "code.go" |
| if err := testutil.WriteFiles(td, map[string]string{ |
| filename: code, |
| }); err != nil { |
| t.Fatal(t) |
| } |
| |
| origEnv := os.Getenv(envName) |
| defer os.Setenv(envName, origEnv) |
| |
| var ft0 fakeTestingT |
| // Return errors even if ft0.Fatalf is called. |
| defer func() { |
| if recover() != nil { |
| errors = ft0.Errors |
| } |
| }() |
| |
| // First, call Ensure in the check mode. |
| os.Setenv(envName, "") |
| Ensure(&ft0, filename, params) |
| |
| // Second, call Ensure in the update mode. |
| var ft1 fakeTestingT |
| os.Setenv(envName, "1") |
| Ensure(&ft1, filename, params) |
| if len(ft1.Errors) > 0 { |
| t.Errorf("Ensure failed: %v", ft1.Errors) |
| } |
| |
| newBytes, err := ioutil.ReadFile(filename) |
| if err != nil { |
| t.Fatal(err) |
| } |
| return ft0.Errors, string(newBytes) |
| } |
| |
| const ( |
| testCode = `package example |
| |
| import "chromiumos/tast/testing" |
| |
| func init() { |
| testing.AddTest(&testing.Test{ |
| Name: "Test", |
| Params: []testing.Param{ |
| // Parameters generated by params_test.go. DO NOT EDIT. |
| {Name: "a", Val: 1}, |
| {Name: "b", Val: 2}, |
| }, |
| }) |
| } |
| ` |
| testParams = `{Name: "a", Val: 1}, |
| {Name: "b", Val: 2}, |
| ` |
| ) |
| |
| func TestEnsureNoChange(t *testing.T) { |
| errors, newCode := callEnsure(t, testCode, testParams) |
| if diff := cmp.Diff(errors, []string(nil)); diff != "" { |
| t.Errorf("Errors mismatch (-got +want):\n%s", diff) |
| } |
| if diff := diff.Diff(newCode, testCode); diff != "" { |
| t.Errorf("Generated code mismatch (-got +want):\n%s", diff) |
| } |
| } |
| |
| func TestEnsureChange(t *testing.T) { |
| const oldCode = `package example |
| |
| import "chromiumos/tast/testing" |
| |
| func init() { |
| testing.AddTest(&testing.Test{ |
| Name: "Test", |
| Params: []testing.Param{ |
| {Name: "x", Val: 28}, |
| }, |
| }) |
| } |
| ` |
| errors, newCode := callEnsure(t, oldCode, testParams) |
| wantErrors := []string{ |
| `code.go: Params is stale; run the following command to update: |
| TAST_GENERATE_UPDATE=1 ~/trunk/src/platform/tast/tools/go.sh test -count=1 chromiumos/tast/common/genparams`, |
| } |
| if diff := cmp.Diff(errors, wantErrors); diff != "" { |
| t.Errorf("Errors mismatch (-got +want):\n%s", diff) |
| } |
| if diff := diff.Diff(newCode, testCode); diff != "" { |
| t.Errorf("Generated code mismatch (-got +want):\n%s", diff) |
| } |
| } |
| |
| func TestEnsureMissingParams(t *testing.T) { |
| const oldCode = `package example |
| |
| import "chromiumos/tast/testing" |
| |
| func init() { |
| testing.AddTest(&testing.Test{ |
| Name: "Test", |
| }) |
| } |
| ` |
| errors, newCode := callEnsure(t, oldCode, testParams) |
| wantErrors := []string{ |
| `code.go: Params is stale; run the following command to update: |
| TAST_GENERATE_UPDATE=1 ~/trunk/src/platform/tast/tools/go.sh test -count=1 chromiumos/tast/common/genparams`, |
| } |
| if diff := cmp.Diff(errors, wantErrors); diff != "" { |
| t.Errorf("Errors mismatch (-got +want):\n%s", diff) |
| } |
| if diff := diff.Diff(newCode, testCode); diff != "" { |
| t.Errorf("Generated code mismatch (-got +want):\n%s", diff) |
| } |
| } |
| |
| func TestEnsureNoRegistration(t *testing.T) { |
| const oldCode = `package example |
| |
| func init() { |
| setUpSomething() |
| } |
| ` |
| errors, _ := callEnsure(t, oldCode, testParams) |
| wantErrors := []string{ |
| "code.go: found 0 testing.AddTest calls; want 1", |
| } |
| if diff := cmp.Diff(errors, wantErrors); diff != "" { |
| t.Errorf("Errors mismatch (-got +want):\n%s", diff) |
| } |
| } |
| |
| func TestEnsureDuplicatedRegistration(t *testing.T) { |
| const oldCode = `package example |
| |
| func init() { |
| testing.AddTest(&testing.Test{ |
| Name: "Test1", |
| }) |
| testing.AddTest(&testing.Test{ |
| Name: "Test2", |
| }) |
| } |
| ` |
| errors, _ := callEnsure(t, oldCode, testParams) |
| wantErrors := []string{ |
| "code.go: found 2 testing.AddTest calls; want 1", |
| } |
| if diff := cmp.Diff(errors, wantErrors); diff != "" { |
| t.Errorf("Errors mismatch (-got +want):\n%s", diff) |
| } |
| } |
| |
| func TestEnsureTestingAlias(t *testing.T) { |
| const oldCode = `package example |
| |
| import mytesting "chromiumos/tast/testing" |
| |
| func init() { |
| mytesting.AddTest(&mytesting.Test{ |
| Name: "Test", |
| }) |
| } |
| ` |
| errors, _ := callEnsure(t, oldCode, testParams) |
| wantErrors := []string{ |
| "chromiumos/tast/testing must be imported without alias", |
| } |
| if diff := cmp.Diff(errors, wantErrors); diff != "" { |
| t.Errorf("Errors mismatch (-got +want):\n%s", diff) |
| } |
| } |