[tools][src] Convert ExpandHome to dependency injection
Converts fileutils.ExpandHome to use dependency injection so that tests
can avoid interacting with the real environment. Additionally, adds test
coverage for affected code that is not blocked on other dependency
injection conversions.
Bug: 344014313
Change-Id: I1b78c0e601396fc1cbc80fb4f4c2380647dfec17
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/223855
Commit-Queue: Brian Sheedy <bsheedy@google.com>
Reviewed-by: dan sinclair <dsinclair@chromium.org>
Auto-Submit: Brian Sheedy <bsheedy@google.com>
Commit-Queue: dan sinclair <dsinclair@chromium.org>
diff --git a/tools/src/auth/auth.go b/tools/src/auth/auth.go
index 9bf4009..9960d04 100644
--- a/tools/src/auth/auth.go
+++ b/tools/src/auth/auth.go
@@ -29,15 +29,18 @@
import (
"dawn.googlesource.com/dawn/tools/src/fileutils"
+ "dawn.googlesource.com/dawn/tools/src/oswrapper"
"go.chromium.org/luci/auth"
"go.chromium.org/luci/hardcoded/chromeinfra"
)
// DefaultAuthOptions returns the default authentication options for use by
// command line arguments.
-func DefaultAuthOptions(additionalScopes ...string) auth.Options {
+func DefaultAuthOptions(
+ environProvider oswrapper.EnvironProvider, additionalScopes ...string) auth.Options {
+
def := chromeinfra.DefaultAuthOptions()
- def.SecretsDir = fileutils.ExpandHome("~/.config/dawn-cts")
+ def.SecretsDir = fileutils.ExpandHome("~/.config/dawn-cts", environProvider)
def.Scopes = append(def.Scopes,
"https://www.googleapis.com/auth/gerritcodereview",
auth.OAuthScopeEmail)
diff --git a/tools/src/auth/auth_test.go b/tools/src/auth/auth_test.go
new file mode 100644
index 0000000..69b40a5
--- /dev/null
+++ b/tools/src/auth/auth_test.go
@@ -0,0 +1,76 @@
+// Copyright 2025 The Dawn & Tint Authors
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this
+// list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package auth
+
+import (
+ "testing"
+
+ "dawn.googlesource.com/dawn/tools/src/oswrapper"
+ "github.com/stretchr/testify/require"
+ "go.chromium.org/luci/auth"
+)
+
+func TestDefaultAuthOptions_NoAdditionalScopes(t *testing.T) {
+ wrapper := oswrapper.CreateMemMapOSWrapper()
+ wrapper.Environment = map[string]string{
+ "HOME": "/home",
+ }
+
+ authOptions := DefaultAuthOptions(wrapper)
+
+ require.Equal(t, authOptions.SecretsDir, "/home/.config/dawn-cts")
+ require.GreaterOrEqual(t, len(authOptions.Scopes), 2)
+ require.Equal(
+ t,
+ []string{
+ "https://www.googleapis.com/auth/gerritcodereview",
+ auth.OAuthScopeEmail,
+ },
+ authOptions.Scopes[len(authOptions.Scopes)-2:])
+}
+
+func TestDefaultAuthOptions_AdditionalScopes(t *testing.T) {
+ wrapper := oswrapper.CreateMemMapOSWrapper()
+ wrapper.Environment = map[string]string{
+ "HOME": "/home",
+ }
+
+ authOptions := DefaultAuthOptions(wrapper, "scope1", "scope2")
+
+ require.Equal(t, authOptions.SecretsDir, "/home/.config/dawn-cts")
+ require.GreaterOrEqual(t, len(authOptions.Scopes), 4)
+ require.Equal(
+ t,
+ []string{
+ "https://www.googleapis.com/auth/gerritcodereview",
+ auth.OAuthScopeEmail,
+ "scope1",
+ "scope2",
+ },
+ authOptions.Scopes[len(authOptions.Scopes)-4:])
+}
diff --git a/tools/src/cmd/add-gerrit-hashtags/main.go b/tools/src/cmd/add-gerrit-hashtags/main.go
index bbd5dcd..d65e2da 100644
--- a/tools/src/cmd/add-gerrit-hashtags/main.go
+++ b/tools/src/cmd/add-gerrit-hashtags/main.go
@@ -43,6 +43,7 @@
"dawn.googlesource.com/dawn/tools/src/dawn"
"dawn.googlesource.com/dawn/tools/src/gerrit"
"dawn.googlesource.com/dawn/tools/src/git"
+ "dawn.googlesource.com/dawn/tools/src/oswrapper"
"go.chromium.org/luci/auth/client/authcli"
)
@@ -78,7 +79,7 @@
}
func main() {
- authFlags.Register(flag.CommandLine, auth.DefaultAuthOptions())
+ authFlags.Register(flag.CommandLine, auth.DefaultAuthOptions(oswrapper.GetRealOSWrapper()))
flag.Usage = func() {
out := flag.CommandLine.Output()
diff --git a/tools/src/cmd/auto-submit/main.go b/tools/src/cmd/auto-submit/main.go
index 18d18bf..56681ae 100644
--- a/tools/src/cmd/auto-submit/main.go
+++ b/tools/src/cmd/auto-submit/main.go
@@ -43,6 +43,7 @@
"dawn.googlesource.com/dawn/tools/src/dawn"
"dawn.googlesource.com/dawn/tools/src/gerrit"
"dawn.googlesource.com/dawn/tools/src/git"
+ "dawn.googlesource.com/dawn/tools/src/oswrapper"
"go.chromium.org/luci/auth/client/authcli"
)
@@ -75,7 +76,7 @@
}
func main() {
- authFlags.Register(flag.CommandLine, auth.DefaultAuthOptions())
+ authFlags.Register(flag.CommandLine, auth.DefaultAuthOptions(oswrapper.GetRealOSWrapper()))
flag.Usage = func() {
out := flag.CommandLine.Output()
diff --git a/tools/src/cmd/cts/common/results.go b/tools/src/cmd/cts/common/results.go
index fa9c641..d2d840c 100644
--- a/tools/src/cmd/cts/common/results.go
+++ b/tools/src/cmd/cts/common/results.go
@@ -33,7 +33,6 @@
"flag"
"fmt"
"log"
- "os"
"path/filepath"
"sort"
"strconv"
@@ -179,6 +178,9 @@
return resultsByExecutionMode, nil
}
+// TODO(crbug.com/344014313): Switch to using the resultsdb.Querier contained
+// within the provided Config instead of taking a separate argument.
+
// CacheResults looks in the cache at 'cacheDir' for the results for the given patchset.
// If the cache contains the results, then these are loaded, transformed with CleanResults() and
// returned.
@@ -226,11 +228,11 @@
var cachePath string
if cacheDir != "" {
- dir := fileutils.ExpandHome(cacheDir)
+ dir := fileutils.ExpandHome(cacheDir, cfg.OsWrapper)
path := filepath.Join(dir, strconv.Itoa(ps.Change), fmt.Sprintf("ps-%v%v.txt", ps.Patchset, fileSuffix))
- if _, err := os.Stat(path); err == nil {
+ if _, err := cfg.OsWrapper.Stat(path); err == nil {
log.Printf("loading cached results from cl %v ps %v...", ps.Change, ps.Patchset)
- return result.Load(path)
+ return result.LoadWithWrapper(path, cfg.OsWrapper)
}
cachePath = path
}
@@ -241,10 +243,6 @@
return nil, err
}
- if err := result.Save(cachePath, resultsByExecutionMode); err != nil {
- log.Println("failed to save results to cache: %w", err)
- }
-
// Expand aliased tags, remove specific tags
for i, results := range resultsByExecutionMode {
CleanResults(cfg, &results)
@@ -252,6 +250,10 @@
resultsByExecutionMode[i] = results
}
+ if err := result.SaveWithWrapper(cachePath, resultsByExecutionMode, cfg.OsWrapper); err != nil {
+ log.Println("failed to save results to cache: %w", err)
+ }
+
return resultsByExecutionMode, nil
}
@@ -603,7 +605,7 @@
// Load cached results if they are available.
var cachePath string
if cacheDir != "" {
- dir := fileutils.ExpandHomeWithWrapper(cacheDir, osWrapper)
+ dir := fileutils.ExpandHome(cacheDir, osWrapper)
year, month, day := time.Now().Date()
path := filepath.Join(dir, "expectation-affected-ci-results", fmt.Sprintf("%d-%d-%d.txt", year, month, day))
if _, err := osWrapper.Stat(path); err == nil {
diff --git a/tools/src/cmd/cts/common/results_test.go b/tools/src/cmd/cts/common/results_test.go
index 75d1c2c..97a8cd3 100644
--- a/tools/src/cmd/cts/common/results_test.go
+++ b/tools/src/cmd/cts/common/results_test.go
@@ -37,6 +37,7 @@
"dawn.googlesource.com/dawn/tools/src/cts/query"
"dawn.googlesource.com/dawn/tools/src/cts/result"
"dawn.googlesource.com/dawn/tools/src/fileutils"
+ "dawn.googlesource.com/dawn/tools/src/gerrit"
"dawn.googlesource.com/dawn/tools/src/oswrapper"
"dawn.googlesource.com/dawn/tools/src/resultsdb"
"github.com/stretchr/testify/require"
@@ -45,14 +46,242 @@
// TODO(crbug.com/342554800): Add test coverage for:
// ResultSource.GetResults (requires breaking out into helper functions)
// ResultSource.GetUnsuppressedFailingResults (ditto)
-// CacheResults (requires os abstraction crbug.com/344014313)
-// CacheUnsuppressedFailingResults (ditto)
// LatestCTSRoll
// LatestPatchset
// MostRecentResultsForChange (requires os abstraction crbug.com/344014313)
// MostRecentUnsuppressedFailingResultsForChange (ditto)
/*******************************************************************************
+ * CacheResults tests
+ ******************************************************************************/
+
+func getCacheResultsSharedSetupData() (
+ context.Context, Config, oswrapper.MemMapOSWrapper, gerrit.Patchset, string) {
+
+ ctx := context.Background()
+ wrapper := oswrapper.CreateMemMapOSWrapper()
+ patchset := gerrit.Patchset{
+ Change: 1,
+ Patchset: 2,
+ }
+ cacheDir := "/cache"
+ cfg := Config{
+ Tests: []TestConfig{
+ {
+ ExecutionMode: result.ExecutionMode("execution_mode"),
+ Prefixes: []string{"prefix"},
+ },
+ },
+ OsWrapper: wrapper,
+ }
+ cfg.Tag.Remove = []string{"tag_to_remove"}
+
+ return ctx, cfg, wrapper, patchset, cacheDir
+}
+
+func TestCacheResults_CacheHit(t *testing.T) {
+ testCacheResults_CacheHit_Impl(t, false)
+}
+
+func TestCacheUnsuppressedFailingResults_CacheHit(t *testing.T) {
+ testCacheResults_CacheHit_Impl(t, true)
+}
+
+func testCacheResults_CacheHit_Impl(t *testing.T, unsuppressedOnly bool) {
+ client := resultsdb.MockBigQueryClient{}
+ var testedFunc cacheResultsFunc
+ var clientDataField *resultsdb.PrefixGroupedQueryResults
+ var partialCacheFilePath string
+ if unsuppressedOnly {
+ testedFunc = CacheUnsuppressedFailingResults
+ clientDataField = &client.UnsuppressedFailureReturnValues
+ partialCacheFilePath = filepath.Join("1", "ps-2-unsuppressed-failures.txt")
+ } else {
+ testedFunc = CacheResults
+ clientDataField = &client.ReturnValues
+ partialCacheFilePath = filepath.Join("1", "ps-2.txt")
+ }
+
+ ctx, cfg, wrapper, patchset, cacheDir := getCacheResultsSharedSetupData()
+
+ // Return bad data to ensure that no querying occurs when the cache is hit.
+ *clientDataField = resultsdb.PrefixGroupedQueryResults{
+ "prefix": []resultsdb.QueryResult{
+ {
+ TestId: "bad_test",
+ Status: "FAIL",
+ Tags: []resultsdb.TagPair{},
+ Duration: 1.0,
+ },
+ },
+ }
+
+ cachedResults := result.ResultsByExecutionMode{
+ "execution_mode": result.List{
+ {
+ Query: query.Parse("_test_1"),
+ Tags: result.NewTags("tag_1"),
+ Status: result.Failure,
+ Duration: 0,
+ MayExonerate: false,
+ },
+ },
+ }
+
+ cachePath := filepath.Join(cacheDir, partialCacheFilePath)
+ err := result.SaveWithWrapper(cachePath, cachedResults, wrapper)
+ require.NoErrorf(t, err, "Got error writing results: %v", err)
+
+ resultsByExecutionMode, err := testedFunc(ctx, cfg, patchset, cacheDir, client, BuildsByName{})
+ require.NoErrorf(t, err, "Got error caching results: %v", err)
+ require.Equal(t, cachedResults, resultsByExecutionMode)
+}
+
+func TestCacheResults_GetRawResultsError(t *testing.T) {
+ testCacheResults_GetRawResultsError_Impl(t, false)
+}
+
+func TestCacheUnsuppressedFailingResults_GetRawResultsError(t *testing.T) {
+ testCacheResults_GetRawResultsError_Impl(t, true)
+}
+
+func testCacheResults_GetRawResultsError_Impl(t *testing.T, unsuppressedOnly bool) {
+ client := resultsdb.MockBigQueryClient{}
+ var testedFunc cacheResultsFunc
+ var clientDataField *resultsdb.PrefixGroupedQueryResults
+ if unsuppressedOnly {
+ testedFunc = CacheUnsuppressedFailingResults
+ clientDataField = &client.UnsuppressedFailureReturnValues
+ } else {
+ testedFunc = CacheResults
+ clientDataField = &client.ReturnValues
+ }
+
+ ctx, cfg, _, patchset, cacheDir := getCacheResultsSharedSetupData()
+
+ *clientDataField = resultsdb.PrefixGroupedQueryResults{
+ "prefix": []resultsdb.QueryResult{
+ {
+ TestId: "bad_test",
+ Status: "FAIL",
+ Tags: []resultsdb.TagPair{},
+ Duration: 1.0,
+ },
+ },
+ }
+
+ resultsByExecutionMode, err := testedFunc(ctx, cfg, patchset, cacheDir, client, BuildsByName{})
+ require.Nil(t, resultsByExecutionMode)
+ require.ErrorContains(t, err,
+ "Test ID bad_test did not start with prefix even though query should have filtered.")
+}
+
+func TestCacheResults_Success(t *testing.T) {
+ testCacheResults_Success_Impl(t, false)
+}
+
+func TestCacheUnsuppressedFailingResults_Success(t *testing.T) {
+ testCacheResults_Success_Impl(t, true)
+}
+
+func testCacheResults_Success_Impl(t *testing.T, unsuppressedOnly bool) {
+ client := resultsdb.MockBigQueryClient{}
+ var testedFunc cacheResultsFunc
+ var clientDataField *resultsdb.PrefixGroupedQueryResults
+ if unsuppressedOnly {
+ testedFunc = CacheUnsuppressedFailingResults
+ clientDataField = &client.UnsuppressedFailureReturnValues
+ } else {
+ testedFunc = CacheResults
+ clientDataField = &client.ReturnValues
+ }
+
+ ctx, cfg, _, patchset, cacheDir := getCacheResultsSharedSetupData()
+
+ *clientDataField = resultsdb.PrefixGroupedQueryResults{
+ "prefix": []resultsdb.QueryResult{
+ {
+ TestId: "prefix_test_2",
+ Status: "CRASH",
+ Tags: []resultsdb.TagPair{
+ {
+ Key: "typ_tag",
+ Value: "tag_2",
+ },
+ },
+ Duration: 2,
+ },
+ {
+ TestId: "prefix_test_1",
+ Status: "FAIL",
+ Tags: []resultsdb.TagPair{
+ {
+ Key: "typ_tag",
+ Value: "tag_1",
+ },
+ // This should be removed by CleanResults().
+ {
+ Key: "typ_tag",
+ Value: "tag_to_remove",
+ },
+ },
+ Duration: 5,
+ },
+ // Should be merged into the above result by CleanResults()
+ {
+ TestId: "prefix_test_1",
+ Status: "PASS",
+ Tags: []resultsdb.TagPair{
+ {
+ Key: "typ_tag",
+ Value: "tag_1",
+ },
+ // This should be removed by CleanResults().
+ {
+ Key: "typ_tag",
+ Value: "tag_to_remove",
+ },
+ },
+ Duration: 1,
+ },
+ },
+ }
+
+ expectedResults := result.ResultsByExecutionMode{
+ "execution_mode": result.List{
+ {
+ Query: query.Parse("_test_1"),
+ Tags: result.NewTags("tag_1"),
+ Status: result.Failure,
+ Duration: 3000000000,
+ MayExonerate: false,
+ },
+ {
+ Query: query.Parse("_test_2"),
+ Tags: result.NewTags("tag_2"),
+ Status: result.Crash,
+ Duration: 2000000000,
+ MayExonerate: false,
+ },
+ },
+ }
+
+ // Check that the initial results are retrieved and cleaned properly.
+ resultsByExecutionMode, err := testedFunc(
+ ctx, cfg, patchset, cacheDir, client, BuildsByName{})
+ require.NoErrorf(t, err, "Got error caching results: %v", err)
+ require.Equal(t, expectedResults, resultsByExecutionMode)
+
+ // Check that the results were cached and that hitting the cache still results
+ // in cleaned data.
+ client = resultsdb.MockBigQueryClient{}
+ resultsByExecutionMode, err = testedFunc(
+ ctx, cfg, patchset, cacheDir, client, BuildsByName{})
+ require.NoErrorf(t, err, "Got error caching results: %v", err)
+ require.Equal(t, expectedResults, resultsByExecutionMode)
+}
+
+/*******************************************************************************
* GetResults tests
******************************************************************************/
diff --git a/tools/src/cmd/cts/export/export.go b/tools/src/cmd/cts/export/export.go
index f323109..9c6438d 100644
--- a/tools/src/cmd/cts/export/export.go
+++ b/tools/src/cmd/cts/export/export.go
@@ -67,7 +67,9 @@
}
func (c *cmd) RegisterFlags(ctx context.Context, cfg common.Config) ([]string, error) {
- c.flags.auth.Register(flag.CommandLine, auth.DefaultAuthOptions(sheets.SpreadsheetsScope))
+ c.flags.auth.Register(
+ flag.CommandLine,
+ auth.DefaultAuthOptions(cfg.OsWrapper, sheets.SpreadsheetsScope))
c.flags.results.RegisterFlags(cfg)
npmPath, _ := exec.LookPath("npm")
flag.StringVar(&c.flags.npmPath, "npm", npmPath, "path to npm")
diff --git a/tools/src/cmd/cts/results/results.go b/tools/src/cmd/cts/results/results.go
index d43309b..ff35ea3 100644
--- a/tools/src/cmd/cts/results/results.go
+++ b/tools/src/cmd/cts/results/results.go
@@ -64,7 +64,7 @@
flag.StringVar(&c.flags.output, "o", "results.txt", "output file. '-' writes to stdout")
flag.BoolVar(&c.flags.unsuppressedFailuresOnly, "unsuppressed-failures-only", false, "only pull results for unsuppressed failures")
c.flags.source.RegisterFlags(cfg)
- c.flags.auth.Register(flag.CommandLine, auth.DefaultAuthOptions())
+ c.flags.auth.Register(flag.CommandLine, auth.DefaultAuthOptions(cfg.OsWrapper))
return nil, nil
}
diff --git a/tools/src/cmd/cts/roll/roll.go b/tools/src/cmd/cts/roll/roll.go
index 4923a4f..43e35a6 100644
--- a/tools/src/cmd/cts/roll/roll.go
+++ b/tools/src/cmd/cts/roll/roll.go
@@ -109,7 +109,7 @@
func (c *cmd) RegisterFlags(ctx context.Context, cfg common.Config) ([]string, error) {
gitPath, _ := exec.LookPath("git")
npmPath, _ := exec.LookPath("npm")
- c.flags.auth.Register(flag.CommandLine, commonAuth.DefaultAuthOptions(sheets.SpreadsheetsScope))
+ c.flags.auth.Register(flag.CommandLine, commonAuth.DefaultAuthOptions(cfg.OsWrapper, sheets.SpreadsheetsScope))
flag.StringVar(&c.flags.gitPath, "git", gitPath, "path to git")
flag.StringVar(&c.flags.npmPath, "npm", npmPath, "path to npm")
flag.StringVar(&c.flags.nodePath, "node", fileutils.NodePath(), "path to node")
diff --git a/tools/src/cmd/cts/time/time.go b/tools/src/cmd/cts/time/time.go
index 3cb390e..0a2fd4e 100644
--- a/tools/src/cmd/cts/time/time.go
+++ b/tools/src/cmd/cts/time/time.go
@@ -69,7 +69,7 @@
func (c *cmd) RegisterFlags(ctx context.Context, cfg common.Config) ([]string, error) {
c.flags.source.RegisterFlags(cfg)
- c.flags.auth.Register(flag.CommandLine, auth.DefaultAuthOptions())
+ c.flags.auth.Register(flag.CommandLine, auth.DefaultAuthOptions(cfg.OsWrapper))
flag.IntVar(&c.flags.topN, "top", 0, "print the top N slowest tests")
flag.BoolVar(&c.flags.histogram, "histogram", false, "print a histogram of test timings")
flag.StringVar(&c.flags.query, "query", "", "test query to filter results")
diff --git a/tools/src/cmd/cts/treemap/treemap.go b/tools/src/cmd/cts/treemap/treemap.go
index a6f4b8b..4027919 100644
--- a/tools/src/cmd/cts/treemap/treemap.go
+++ b/tools/src/cmd/cts/treemap/treemap.go
@@ -82,7 +82,7 @@
func (c *cmd) RegisterFlags(ctx context.Context, cfg common.Config) ([]string, error) {
c.flags.source.RegisterFlags(cfg)
- c.flags.auth.Register(flag.CommandLine, auth.DefaultAuthOptions())
+ c.flags.auth.Register(flag.CommandLine, auth.DefaultAuthOptions(cfg.OsWrapper))
flag.BoolVar(&c.flags.keepAlive, "keep-alive", false, "keep the server alive after the page has been closed")
return []string{"[cases | timing]"}, nil
}
diff --git a/tools/src/cmd/cts/update/expectations/expectations.go b/tools/src/cmd/cts/update/expectations/expectations.go
index bcf9efb..39666b1 100644
--- a/tools/src/cmd/cts/update/expectations/expectations.go
+++ b/tools/src/cmd/cts/update/expectations/expectations.go
@@ -78,7 +78,7 @@
func (c *cmd) RegisterFlags(ctx context.Context, cfg common.Config) ([]string, error) {
c.flags.results.RegisterFlags(cfg)
- c.flags.auth.Register(flag.CommandLine, auth.DefaultAuthOptions())
+ c.flags.auth.Register(flag.CommandLine, auth.DefaultAuthOptions(cfg.OsWrapper))
flag.BoolVar(&c.flags.verbose, "verbose", false, "emit additional logging")
flag.BoolVar(&c.flags.generateExplicitTags, "generate-explicit-tags", false,
"Use the most explicit tags for expectations instead of several broad ones")
diff --git a/tools/src/cmd/gerrit-stats/main.go b/tools/src/cmd/gerrit-stats/main.go
index eee7e6a..fce2868 100644
--- a/tools/src/cmd/gerrit-stats/main.go
+++ b/tools/src/cmd/gerrit-stats/main.go
@@ -42,6 +42,7 @@
"dawn.googlesource.com/dawn/tools/src/dawn"
"dawn.googlesource.com/dawn/tools/src/gerrit"
"dawn.googlesource.com/dawn/tools/src/git"
+ "dawn.googlesource.com/dawn/tools/src/oswrapper"
"go.chromium.org/luci/auth/client/authcli"
)
@@ -73,7 +74,7 @@
}
func main() {
- authFlags.Register(flag.CommandLine, auth.DefaultAuthOptions())
+ authFlags.Register(flag.CommandLine, auth.DefaultAuthOptions(oswrapper.GetRealOSWrapper()))
flag.Parse()
if err := run(); err != nil {
diff --git a/tools/src/cmd/snippets/main.go b/tools/src/cmd/snippets/main.go
index 0d51050..075a9bd 100644
--- a/tools/src/cmd/snippets/main.go
+++ b/tools/src/cmd/snippets/main.go
@@ -41,6 +41,7 @@
"dawn.googlesource.com/dawn/tools/src/dawn"
"dawn.googlesource.com/dawn/tools/src/gerrit"
"dawn.googlesource.com/dawn/tools/src/git"
+ "dawn.googlesource.com/dawn/tools/src/oswrapper"
"go.chromium.org/luci/auth/client/authcli"
)
@@ -70,7 +71,7 @@
}
func main() {
- authFlags.Register(flag.CommandLine, auth.DefaultAuthOptions())
+ authFlags.Register(flag.CommandLine, auth.DefaultAuthOptions(oswrapper.GetRealOSWrapper()))
flag.Parse()
if err := run(); err != nil {
diff --git a/tools/src/cmd/time-cmd/main.go b/tools/src/cmd/time-cmd/main.go
index 193e33a..5eee296 100644
--- a/tools/src/cmd/time-cmd/main.go
+++ b/tools/src/cmd/time-cmd/main.go
@@ -42,16 +42,20 @@
"dawn.googlesource.com/dawn/tools/src/fileutils"
"dawn.googlesource.com/dawn/tools/src/glob"
+ "dawn.googlesource.com/dawn/tools/src/oswrapper"
"dawn.googlesource.com/dawn/tools/src/progressbar"
)
func main() {
- if err := run(); err != nil {
+ if err := run(oswrapper.GetRealOSWrapper()); err != nil {
fmt.Println(err)
os.Exit(1)
}
}
-func run() error {
+
+// TODO(crbug.com/344014313): Add test coverage once glob.Glob is converted to
+// use dependency injection.
+func run(osWrapper oswrapper.OSWrapper) error {
flag.Usage = func() {
out := flag.CommandLine.Output()
fmt.Fprintf(out, "time-cmd runs a given command for each file found in a glob, returning the sorted run times..\n")
@@ -83,9 +87,9 @@
return fmt.Errorf("Missing command")
}
- fileGlob = fileutils.ExpandHome(fileGlob)
+ fileGlob = fileutils.ExpandHome(fileGlob, osWrapper)
- exe, err := exec.LookPath(fileutils.ExpandHome(args[0]))
+ exe, err := exec.LookPath(fileutils.ExpandHome(args[0], osWrapper))
if err != nil {
return fmt.Errorf("could not find executable '%v'", args[0])
}
diff --git a/tools/src/fileutils/paths.go b/tools/src/fileutils/paths.go
index 5fb22a9..4989309 100644
--- a/tools/src/fileutils/paths.go
+++ b/tools/src/fileutils/paths.go
@@ -83,20 +83,7 @@
// ExpandHome returns the string with all occurrences of '~' replaced with the
// user's home directory. The the user's home directory cannot be found, then
// the input string is returned.
-func ExpandHome(path string) string {
- if strings.ContainsRune(path, '~') {
- if home, err := os.UserHomeDir(); err == nil {
- return strings.ReplaceAll(path, "~", home)
- }
- }
- return path
-}
-
-// TODO(crbug.com/344014313): Merge this into ExpandHome once all uses are using
-// dependency injection.
-// ExpandHomeWithWrapper is a copy of ExpandHome that uses the provided
-// FilesystemReader instead of calling os directly.
-func ExpandHomeWithWrapper(path string, environProvider oswrapper.EnvironProvider) string {
+func ExpandHome(path string, environProvider oswrapper.EnvironProvider) string {
if strings.ContainsRune(path, '~') {
if home, err := environProvider.UserHomeDir(); err == nil {
return strings.ReplaceAll(path, "~", home)
diff --git a/tools/src/fileutils/paths_test.go b/tools/src/fileutils/paths_test.go
index dc25fe0..04fbe1a 100644
--- a/tools/src/fileutils/paths_test.go
+++ b/tools/src/fileutils/paths_test.go
@@ -65,7 +65,7 @@
}
}
-func TestExpandHomeWithWrapper(t *testing.T) {
+func TestExpandHome(t *testing.T) {
tests := []struct {
name string
input string
@@ -105,7 +105,7 @@
"HOME": "/home",
}
- expandedPath := fileutils.ExpandHomeWithWrapper(testCase.input, wrapper)
+ expandedPath := fileutils.ExpandHome(testCase.input, wrapper)
require.Equal(t, testCase.want, expandedPath)
})
}