github.com/hashicorp/terraform-plugin-sdk@v1.17.2/internal/initwd/module_install_test.go (about)

     1  package initwd
     2  
     3  import (
     4  	"flag"
     5  	"fmt"
     6  	"io/ioutil"
     7  	"log"
     8  	"os"
     9  	"path/filepath"
    10  	"strings"
    11  	"testing"
    12  
    13  	"github.com/go-test/deep"
    14  	version "github.com/hashicorp/go-version"
    15  	"github.com/hashicorp/terraform-plugin-sdk/helper/logging"
    16  	"github.com/hashicorp/terraform-plugin-sdk/internal/configs"
    17  	"github.com/hashicorp/terraform-plugin-sdk/internal/configs/configload"
    18  	"github.com/hashicorp/terraform-plugin-sdk/internal/registry"
    19  	"github.com/hashicorp/terraform-plugin-sdk/internal/tfdiags"
    20  )
    21  
    22  func TestMain(m *testing.M) {
    23  	flag.Parse()
    24  	if testing.Verbose() {
    25  		// if we're verbose, use the logging requested by TF_LOG
    26  		logging.SetOutput()
    27  	} else {
    28  		// otherwise silence all logs
    29  		log.SetOutput(ioutil.Discard)
    30  	}
    31  
    32  	os.Exit(m.Run())
    33  }
    34  
    35  func TestModuleInstaller(t *testing.T) {
    36  	fixtureDir := filepath.Clean("testdata/local-modules")
    37  	dir, done := tempChdir(t, fixtureDir)
    38  	defer done()
    39  
    40  	hooks := &testInstallHooks{}
    41  
    42  	modulesDir := filepath.Join(dir, ".terraform/modules")
    43  	inst := NewModuleInstaller(modulesDir, nil)
    44  	_, diags := inst.InstallModules(".", false, hooks)
    45  	assertNoDiagnostics(t, diags)
    46  
    47  	wantCalls := []testInstallHookCall{
    48  		{
    49  			Name:        "Install",
    50  			ModuleAddr:  "child_a",
    51  			PackageAddr: "",
    52  			LocalPath:   "child_a",
    53  		},
    54  		{
    55  			Name:        "Install",
    56  			ModuleAddr:  "child_a.child_b",
    57  			PackageAddr: "",
    58  			LocalPath:   "child_a/child_b",
    59  		},
    60  	}
    61  
    62  	if assertResultDeepEqual(t, hooks.Calls, wantCalls) {
    63  		return
    64  	}
    65  
    66  	loader, err := configload.NewLoader(&configload.Config{
    67  		ModulesDir: modulesDir,
    68  	})
    69  	if err != nil {
    70  		t.Fatal(err)
    71  	}
    72  
    73  	// Make sure the configuration is loadable now.
    74  	// (This ensures that correct information is recorded in the manifest.)
    75  	config, loadDiags := loader.LoadConfig(".")
    76  	assertNoDiagnostics(t, tfdiags.Diagnostics{}.Append(loadDiags))
    77  
    78  	wantTraces := map[string]string{
    79  		"":                "in root module",
    80  		"child_a":         "in child_a module",
    81  		"child_a.child_b": "in child_b module",
    82  	}
    83  	gotTraces := map[string]string{}
    84  	config.DeepEach(func(c *configs.Config) {
    85  		path := strings.Join(c.Path, ".")
    86  		if c.Module.Variables["v"] == nil {
    87  			gotTraces[path] = "<missing>"
    88  			return
    89  		}
    90  		varDesc := c.Module.Variables["v"].Description
    91  		gotTraces[path] = varDesc
    92  	})
    93  	assertResultDeepEqual(t, gotTraces, wantTraces)
    94  }
    95  
    96  func TestModuleInstaller_error(t *testing.T) {
    97  	fixtureDir := filepath.Clean("testdata/local-module-error")
    98  	dir, done := tempChdir(t, fixtureDir)
    99  	defer done()
   100  
   101  	hooks := &testInstallHooks{}
   102  
   103  	modulesDir := filepath.Join(dir, ".terraform/modules")
   104  	inst := NewModuleInstaller(modulesDir, nil)
   105  	_, diags := inst.InstallModules(".", false, hooks)
   106  
   107  	if !diags.HasErrors() {
   108  		t.Fatal("expected error")
   109  	} else {
   110  		assertDiagnosticSummary(t, diags, "Module not found")
   111  	}
   112  }
   113  
   114  func TestModuleInstaller_invalid_version_constraint_error(t *testing.T) {
   115  	fixtureDir := filepath.Clean("testdata/invalid-version-constraint")
   116  	dir, done := tempChdir(t, fixtureDir)
   117  	defer done()
   118  
   119  	hooks := &testInstallHooks{}
   120  
   121  	modulesDir := filepath.Join(dir, ".terraform/modules")
   122  	inst := NewModuleInstaller(modulesDir, nil)
   123  	_, diags := inst.InstallModules(".", false, hooks)
   124  
   125  	if !diags.HasErrors() {
   126  		t.Fatal("expected error")
   127  	} else {
   128  		assertDiagnosticSummary(t, diags, "Invalid version constraint")
   129  	}
   130  }
   131  
   132  func TestModuleInstaller_invalidVersionConstraintGetter(t *testing.T) {
   133  	fixtureDir := filepath.Clean("testdata/invalid-version-constraint")
   134  	dir, done := tempChdir(t, fixtureDir)
   135  	defer done()
   136  
   137  	hooks := &testInstallHooks{}
   138  
   139  	modulesDir := filepath.Join(dir, ".terraform/modules")
   140  	inst := NewModuleInstaller(modulesDir, nil)
   141  	_, diags := inst.InstallModules(".", false, hooks)
   142  
   143  	if !diags.HasErrors() {
   144  		t.Fatal("expected error")
   145  	} else {
   146  		assertDiagnosticSummary(t, diags, "Invalid version constraint")
   147  	}
   148  }
   149  
   150  func TestModuleInstaller_invalidVersionConstraintLocal(t *testing.T) {
   151  	fixtureDir := filepath.Clean("testdata/invalid-version-constraint-local")
   152  	dir, done := tempChdir(t, fixtureDir)
   153  	defer done()
   154  
   155  	hooks := &testInstallHooks{}
   156  
   157  	modulesDir := filepath.Join(dir, ".terraform/modules")
   158  	inst := NewModuleInstaller(modulesDir, nil)
   159  	_, diags := inst.InstallModules(".", false, hooks)
   160  
   161  	if !diags.HasErrors() {
   162  		t.Fatal("expected error")
   163  	} else {
   164  		assertDiagnosticSummary(t, diags, "Invalid version constraint")
   165  	}
   166  }
   167  
   168  func TestModuleInstaller_symlink(t *testing.T) {
   169  	fixtureDir := filepath.Clean("testdata/local-module-symlink")
   170  	dir, done := tempChdir(t, fixtureDir)
   171  	defer done()
   172  
   173  	hooks := &testInstallHooks{}
   174  
   175  	modulesDir := filepath.Join(dir, ".terraform/modules")
   176  	inst := NewModuleInstaller(modulesDir, nil)
   177  	_, diags := inst.InstallModules(".", false, hooks)
   178  	assertNoDiagnostics(t, diags)
   179  
   180  	wantCalls := []testInstallHookCall{
   181  		{
   182  			Name:        "Install",
   183  			ModuleAddr:  "child_a",
   184  			PackageAddr: "",
   185  			LocalPath:   "child_a",
   186  		},
   187  		{
   188  			Name:        "Install",
   189  			ModuleAddr:  "child_a.child_b",
   190  			PackageAddr: "",
   191  			LocalPath:   "child_a/child_b",
   192  		},
   193  	}
   194  
   195  	if assertResultDeepEqual(t, hooks.Calls, wantCalls) {
   196  		return
   197  	}
   198  
   199  	loader, err := configload.NewLoader(&configload.Config{
   200  		ModulesDir: modulesDir,
   201  	})
   202  	if err != nil {
   203  		t.Fatal(err)
   204  	}
   205  
   206  	// Make sure the configuration is loadable now.
   207  	// (This ensures that correct information is recorded in the manifest.)
   208  	config, loadDiags := loader.LoadConfig(".")
   209  	assertNoDiagnostics(t, tfdiags.Diagnostics{}.Append(loadDiags))
   210  
   211  	wantTraces := map[string]string{
   212  		"":                "in root module",
   213  		"child_a":         "in child_a module",
   214  		"child_a.child_b": "in child_b module",
   215  	}
   216  	gotTraces := map[string]string{}
   217  	config.DeepEach(func(c *configs.Config) {
   218  		path := strings.Join(c.Path, ".")
   219  		if c.Module.Variables["v"] == nil {
   220  			gotTraces[path] = "<missing>"
   221  			return
   222  		}
   223  		varDesc := c.Module.Variables["v"].Description
   224  		gotTraces[path] = varDesc
   225  	})
   226  	assertResultDeepEqual(t, gotTraces, wantTraces)
   227  }
   228  
   229  func TestLoaderInstallModules_registry(t *testing.T) {
   230  	if os.Getenv("TF_ACC") == "" {
   231  		t.Skip("this test accesses registry.terraform.io and github.com; set TF_ACC=1 to run it")
   232  	}
   233  
   234  	fixtureDir := filepath.Clean("testdata/registry-modules")
   235  	tmpDir, done := tempChdir(t, fixtureDir)
   236  	// the module installer runs filepath.EvalSymlinks() on the destination
   237  	// directory before copying files, and the resultant directory is what is
   238  	// returned by the install hooks. Without this, tests could fail on machines
   239  	// where the default temp dir was a symlink.
   240  	dir, err := filepath.EvalSymlinks(tmpDir)
   241  	if err != nil {
   242  		t.Error(err)
   243  	}
   244  
   245  	defer done()
   246  
   247  	hooks := &testInstallHooks{}
   248  	modulesDir := filepath.Join(dir, ".terraform/modules")
   249  	inst := NewModuleInstaller(modulesDir, registry.NewClient(nil, nil))
   250  	_, diags := inst.InstallModules(dir, false, hooks)
   251  	assertNoDiagnostics(t, diags)
   252  
   253  	v := version.Must(version.NewVersion("0.0.1"))
   254  
   255  	wantCalls := []testInstallHookCall{
   256  		// the configuration builder visits each level of calls in lexicographical
   257  		// order by name, so the following list is kept in the same order.
   258  
   259  		// acctest_child_a accesses //modules/child_a directly
   260  		{
   261  			Name:        "Download",
   262  			ModuleAddr:  "acctest_child_a",
   263  			PackageAddr: "hashicorp/module-installer-acctest/aws", // intentionally excludes the subdir because we're downloading the whole package here
   264  			Version:     v,
   265  		},
   266  		{
   267  			Name:       "Install",
   268  			ModuleAddr: "acctest_child_a",
   269  			Version:    v,
   270  			LocalPath:  filepath.Join(dir, ".terraform/modules/acctest_child_a/hashicorp-terraform-aws-module-installer-acctest-853d038/modules/child_a"),
   271  		},
   272  
   273  		// acctest_child_a.child_b
   274  		// (no download because it's a relative path inside acctest_child_a)
   275  		{
   276  			Name:       "Install",
   277  			ModuleAddr: "acctest_child_a.child_b",
   278  			LocalPath:  filepath.Join(dir, ".terraform/modules/acctest_child_a/hashicorp-terraform-aws-module-installer-acctest-853d038/modules/child_b"),
   279  		},
   280  
   281  		// acctest_child_b accesses //modules/child_b directly
   282  		{
   283  			Name:        "Download",
   284  			ModuleAddr:  "acctest_child_b",
   285  			PackageAddr: "hashicorp/module-installer-acctest/aws", // intentionally excludes the subdir because we're downloading the whole package here
   286  			Version:     v,
   287  		},
   288  		{
   289  			Name:       "Install",
   290  			ModuleAddr: "acctest_child_b",
   291  			Version:    v,
   292  			LocalPath:  filepath.Join(dir, ".terraform/modules/acctest_child_b/hashicorp-terraform-aws-module-installer-acctest-853d038/modules/child_b"),
   293  		},
   294  
   295  		// acctest_root
   296  		{
   297  			Name:        "Download",
   298  			ModuleAddr:  "acctest_root",
   299  			PackageAddr: "hashicorp/module-installer-acctest/aws",
   300  			Version:     v,
   301  		},
   302  		{
   303  			Name:       "Install",
   304  			ModuleAddr: "acctest_root",
   305  			Version:    v,
   306  			LocalPath:  filepath.Join(dir, ".terraform/modules/acctest_root/hashicorp-terraform-aws-module-installer-acctest-853d038"),
   307  		},
   308  
   309  		// acctest_root.child_a
   310  		// (no download because it's a relative path inside acctest_root)
   311  		{
   312  			Name:       "Install",
   313  			ModuleAddr: "acctest_root.child_a",
   314  			LocalPath:  filepath.Join(dir, ".terraform/modules/acctest_root/hashicorp-terraform-aws-module-installer-acctest-853d038/modules/child_a"),
   315  		},
   316  
   317  		// acctest_root.child_a.child_b
   318  		// (no download because it's a relative path inside acctest_root, via acctest_root.child_a)
   319  		{
   320  			Name:       "Install",
   321  			ModuleAddr: "acctest_root.child_a.child_b",
   322  			LocalPath:  filepath.Join(dir, ".terraform/modules/acctest_root/hashicorp-terraform-aws-module-installer-acctest-853d038/modules/child_b"),
   323  		},
   324  	}
   325  
   326  	if assertResultDeepEqual(t, hooks.Calls, wantCalls) {
   327  		return
   328  	}
   329  
   330  	loader, err := configload.NewLoader(&configload.Config{
   331  		ModulesDir: modulesDir,
   332  	})
   333  	if err != nil {
   334  		t.Fatal(err)
   335  	}
   336  
   337  	// Make sure the configuration is loadable now.
   338  	// (This ensures that correct information is recorded in the manifest.)
   339  	config, loadDiags := loader.LoadConfig(".")
   340  	assertNoDiagnostics(t, tfdiags.Diagnostics{}.Append(loadDiags))
   341  
   342  	wantTraces := map[string]string{
   343  		"":                             "in local caller for registry-modules",
   344  		"acctest_root":                 "in root module",
   345  		"acctest_root.child_a":         "in child_a module",
   346  		"acctest_root.child_a.child_b": "in child_b module",
   347  		"acctest_child_a":              "in child_a module",
   348  		"acctest_child_a.child_b":      "in child_b module",
   349  		"acctest_child_b":              "in child_b module",
   350  	}
   351  	gotTraces := map[string]string{}
   352  	config.DeepEach(func(c *configs.Config) {
   353  		path := strings.Join(c.Path, ".")
   354  		if c.Module.Variables["v"] == nil {
   355  			gotTraces[path] = "<missing>"
   356  			return
   357  		}
   358  		varDesc := c.Module.Variables["v"].Description
   359  		gotTraces[path] = varDesc
   360  	})
   361  	assertResultDeepEqual(t, gotTraces, wantTraces)
   362  
   363  }
   364  
   365  func TestLoaderInstallModules_goGetter(t *testing.T) {
   366  	if os.Getenv("TF_ACC") == "" {
   367  		t.Skip("this test accesses github.com; set TF_ACC=1 to run it")
   368  	}
   369  
   370  	fixtureDir := filepath.Clean("testdata/go-getter-modules")
   371  	tmpDir, done := tempChdir(t, fixtureDir)
   372  	// the module installer runs filepath.EvalSymlinks() on the destination
   373  	// directory before copying files, and the resultant directory is what is
   374  	// returned by the install hooks. Without this, tests could fail on machines
   375  	// where the default temp dir was a symlink.
   376  	dir, err := filepath.EvalSymlinks(tmpDir)
   377  	if err != nil {
   378  		t.Error(err)
   379  	}
   380  	defer done()
   381  
   382  	hooks := &testInstallHooks{}
   383  	modulesDir := filepath.Join(dir, ".terraform/modules")
   384  	inst := NewModuleInstaller(modulesDir, registry.NewClient(nil, nil))
   385  	_, diags := inst.InstallModules(dir, false, hooks)
   386  	assertNoDiagnostics(t, diags)
   387  
   388  	wantCalls := []testInstallHookCall{
   389  		// the configuration builder visits each level of calls in lexicographical
   390  		// order by name, so the following list is kept in the same order.
   391  
   392  		// acctest_child_a accesses //modules/child_a directly
   393  		{
   394  			Name:        "Download",
   395  			ModuleAddr:  "acctest_child_a",
   396  			PackageAddr: "github.com/hashicorp/terraform-aws-module-installer-acctest?ref=v0.0.1", // intentionally excludes the subdir because we're downloading the whole repo here
   397  		},
   398  		{
   399  			Name:       "Install",
   400  			ModuleAddr: "acctest_child_a",
   401  			LocalPath:  filepath.Join(dir, ".terraform/modules/acctest_child_a/modules/child_a"),
   402  		},
   403  
   404  		// acctest_child_a.child_b
   405  		// (no download because it's a relative path inside acctest_child_a)
   406  		{
   407  			Name:       "Install",
   408  			ModuleAddr: "acctest_child_a.child_b",
   409  			LocalPath:  filepath.Join(dir, ".terraform/modules/acctest_child_a/modules/child_b"),
   410  		},
   411  
   412  		// acctest_child_b accesses //modules/child_b directly
   413  		{
   414  			Name:        "Download",
   415  			ModuleAddr:  "acctest_child_b",
   416  			PackageAddr: "github.com/hashicorp/terraform-aws-module-installer-acctest?ref=v0.0.1", // intentionally excludes the subdir because we're downloading the whole package here
   417  		},
   418  		{
   419  			Name:       "Install",
   420  			ModuleAddr: "acctest_child_b",
   421  			LocalPath:  filepath.Join(dir, ".terraform/modules/acctest_child_b/modules/child_b"),
   422  		},
   423  
   424  		// acctest_root
   425  		{
   426  			Name:        "Download",
   427  			ModuleAddr:  "acctest_root",
   428  			PackageAddr: "github.com/hashicorp/terraform-aws-module-installer-acctest?ref=v0.0.1",
   429  		},
   430  		{
   431  			Name:       "Install",
   432  			ModuleAddr: "acctest_root",
   433  			LocalPath:  filepath.Join(dir, ".terraform/modules/acctest_root"),
   434  		},
   435  
   436  		// acctest_root.child_a
   437  		// (no download because it's a relative path inside acctest_root)
   438  		{
   439  			Name:       "Install",
   440  			ModuleAddr: "acctest_root.child_a",
   441  			LocalPath:  filepath.Join(dir, ".terraform/modules/acctest_root/modules/child_a"),
   442  		},
   443  
   444  		// acctest_root.child_a.child_b
   445  		// (no download because it's a relative path inside acctest_root, via acctest_root.child_a)
   446  		{
   447  			Name:       "Install",
   448  			ModuleAddr: "acctest_root.child_a.child_b",
   449  			LocalPath:  filepath.Join(dir, ".terraform/modules/acctest_root/modules/child_b"),
   450  		},
   451  	}
   452  
   453  	if assertResultDeepEqual(t, hooks.Calls, wantCalls) {
   454  		return
   455  	}
   456  
   457  	loader, err := configload.NewLoader(&configload.Config{
   458  		ModulesDir: modulesDir,
   459  	})
   460  	if err != nil {
   461  		t.Fatal(err)
   462  	}
   463  
   464  	// Make sure the configuration is loadable now.
   465  	// (This ensures that correct information is recorded in the manifest.)
   466  	config, loadDiags := loader.LoadConfig(".")
   467  	assertNoDiagnostics(t, tfdiags.Diagnostics{}.Append(loadDiags))
   468  
   469  	wantTraces := map[string]string{
   470  		"":                             "in local caller for go-getter-modules",
   471  		"acctest_root":                 "in root module",
   472  		"acctest_root.child_a":         "in child_a module",
   473  		"acctest_root.child_a.child_b": "in child_b module",
   474  		"acctest_child_a":              "in child_a module",
   475  		"acctest_child_a.child_b":      "in child_b module",
   476  		"acctest_child_b":              "in child_b module",
   477  	}
   478  	gotTraces := map[string]string{}
   479  	config.DeepEach(func(c *configs.Config) {
   480  		path := strings.Join(c.Path, ".")
   481  		if c.Module.Variables["v"] == nil {
   482  			gotTraces[path] = "<missing>"
   483  			return
   484  		}
   485  		varDesc := c.Module.Variables["v"].Description
   486  		gotTraces[path] = varDesc
   487  	})
   488  	assertResultDeepEqual(t, gotTraces, wantTraces)
   489  
   490  }
   491  
   492  type testInstallHooks struct {
   493  	Calls []testInstallHookCall
   494  }
   495  
   496  type testInstallHookCall struct {
   497  	Name        string
   498  	ModuleAddr  string
   499  	PackageAddr string
   500  	Version     *version.Version
   501  	LocalPath   string
   502  }
   503  
   504  func (h *testInstallHooks) Download(moduleAddr, packageAddr string, version *version.Version) {
   505  	h.Calls = append(h.Calls, testInstallHookCall{
   506  		Name:        "Download",
   507  		ModuleAddr:  moduleAddr,
   508  		PackageAddr: packageAddr,
   509  		Version:     version,
   510  	})
   511  }
   512  
   513  func (h *testInstallHooks) Install(moduleAddr string, version *version.Version, localPath string) {
   514  	h.Calls = append(h.Calls, testInstallHookCall{
   515  		Name:       "Install",
   516  		ModuleAddr: moduleAddr,
   517  		Version:    version,
   518  		LocalPath:  localPath,
   519  	})
   520  }
   521  
   522  // tempChdir copies the contents of the given directory to a temporary
   523  // directory and changes the test process's current working directory to
   524  // point to that directory. Also returned is a function that should be
   525  // called at the end of the test (e.g. via "defer") to restore the previous
   526  // working directory.
   527  //
   528  // Tests using this helper cannot safely be run in parallel with other tests.
   529  func tempChdir(t *testing.T, sourceDir string) (string, func()) {
   530  	t.Helper()
   531  
   532  	tmpDir, err := ioutil.TempDir("", "terraform-configload")
   533  	if err != nil {
   534  		t.Fatalf("failed to create temporary directory: %s", err)
   535  		return "", nil
   536  	}
   537  
   538  	if err := copyDir(tmpDir, sourceDir); err != nil {
   539  		t.Fatalf("failed to copy fixture to temporary directory: %s", err)
   540  		return "", nil
   541  	}
   542  
   543  	oldDir, err := os.Getwd()
   544  	if err != nil {
   545  		t.Fatalf("failed to determine current working directory: %s", err)
   546  		return "", nil
   547  	}
   548  
   549  	err = os.Chdir(tmpDir)
   550  	if err != nil {
   551  		t.Fatalf("failed to switch to temp dir %s: %s", tmpDir, err)
   552  		return "", nil
   553  	}
   554  
   555  	// Most of the tests need this, so we'll make it just in case.
   556  	os.MkdirAll(filepath.Join(tmpDir, ".terraform/modules"), os.ModePerm)
   557  
   558  	t.Logf("tempChdir switched to %s after copying from %s", tmpDir, sourceDir)
   559  
   560  	return tmpDir, func() {
   561  		err := os.Chdir(oldDir)
   562  		if err != nil {
   563  			panic(fmt.Errorf("failed to restore previous working directory %s: %s", oldDir, err))
   564  		}
   565  
   566  		if os.Getenv("TF_CONFIGLOAD_TEST_KEEP_TMP") == "" {
   567  			os.RemoveAll(tmpDir)
   568  		}
   569  	}
   570  }
   571  
   572  func assertNoDiagnostics(t *testing.T, diags tfdiags.Diagnostics) bool {
   573  	t.Helper()
   574  	return assertDiagnosticCount(t, diags, 0)
   575  }
   576  
   577  func assertDiagnosticCount(t *testing.T, diags tfdiags.Diagnostics, want int) bool {
   578  	t.Helper()
   579  	if len(diags) != 0 {
   580  		t.Errorf("wrong number of diagnostics %d; want %d", len(diags), want)
   581  		for _, diag := range diags {
   582  			t.Logf("- %s", diag)
   583  		}
   584  		return true
   585  	}
   586  	return false
   587  }
   588  
   589  func assertDiagnosticSummary(t *testing.T, diags tfdiags.Diagnostics, want string) bool {
   590  	t.Helper()
   591  
   592  	for _, diag := range diags {
   593  		if diag.Description().Summary == want {
   594  			return false
   595  		}
   596  	}
   597  
   598  	t.Errorf("missing diagnostic summary %q", want)
   599  	for _, diag := range diags {
   600  		t.Logf("- %s", diag)
   601  	}
   602  	return true
   603  }
   604  
   605  func assertResultDeepEqual(t *testing.T, got, want interface{}) bool {
   606  	t.Helper()
   607  	if diff := deep.Equal(got, want); diff != nil {
   608  		for _, problem := range diff {
   609  			t.Errorf("%s", problem)
   610  		}
   611  		return true
   612  	}
   613  	return false
   614  }