diff --git a/rules/rules_test.go b/rules/rules_test.go index b0f1d400da..b89d865ded 100644 --- a/rules/rules_test.go +++ b/rules/rules_test.go @@ -17,8 +17,7 @@ import ( "fmt" "github.com/prometheus/prometheus/rules/ast" "github.com/prometheus/prometheus/storage/metric" - "io/ioutil" - "os" + "github.com/prometheus/prometheus/utility/test" "strings" "testing" "time" @@ -213,19 +212,10 @@ func vectorComparisonString(expected []string, actual []string) string { } func TestExpressions(t *testing.T) { - temporaryDirectory, err := ioutil.TempDir("", "rule_expression_tests") - if err != nil { - t.Errorf("Could not create temporary directory: %q\n", err) - return - } - tieredStorage := metric.NewTieredStorage(5000, 5000, 100, time.Second*30, time.Second*1, time.Second*20, temporaryDirectory) + temporaryDirectory := test.NewTemporaryDirectory("rule_expression_tests", t) + defer temporaryDirectory.Close() + tieredStorage := metric.NewTieredStorage(5000, 5000, 100, time.Second*30, time.Second*1, time.Second*20, temporaryDirectory.Path()) go tieredStorage.Serve() - defer func() { - tieredStorage.Close() - if err = os.RemoveAll(temporaryDirectory); err != nil { - t.Errorf("Could not remove temporary directory: %q\n", err) - } - }() ast.SetStorage(tieredStorage) diff --git a/storage/metric/rule_integration_test.go b/storage/metric/rule_integration_test.go index 0f807420c0..bffa046b5e 100644 --- a/storage/metric/rule_integration_test.go +++ b/storage/metric/rule_integration_test.go @@ -16,13 +16,11 @@ package metric import ( "github.com/prometheus/prometheus/model" "github.com/prometheus/prometheus/utility/test" - "io" - "io/ioutil" "testing" "time" ) -func GetValueAtTimeTests(persistenceMaker func() (MetricPersistence, io.Closer), t test.Tester) { +func GetValueAtTimeTests(persistenceMaker func() (MetricPersistence, test.Closer), t test.Tester) { type value struct { year int month time.Month @@ -555,15 +553,11 @@ func GetValueAtTimeTests(persistenceMaker func() (MetricPersistence, io.Closer), p, closer := persistenceMaker() defer func() { + defer closer.Close() err := p.Close() if err != nil { t.Fatalf("Encountered anomaly closing persistence: %q\n", err) } - - err = closer.Close() - if err != nil { - t.Fatalf("Encountered anomaly purging persistence: %q\n", err) - } }() m := model.Metric{ @@ -609,7 +603,7 @@ func GetValueAtTimeTests(persistenceMaker func() (MetricPersistence, io.Closer), } } -func GetBoundaryValuesTests(persistenceMaker func() (MetricPersistence, io.Closer), t test.Tester) { +func GetBoundaryValuesTests(persistenceMaker func() (MetricPersistence, test.Closer), t test.Tester) { type value struct { year int month time.Month @@ -1001,14 +995,11 @@ func GetBoundaryValuesTests(persistenceMaker func() (MetricPersistence, io.Close p, closer := persistenceMaker() defer func() { + defer closer.Close() err := p.Close() if err != nil { t.Fatalf("Encountered anomaly closing persistence: %q\n", err) } - err = closer.Close() - if err != nil { - t.Fatalf("Encountered anomaly purging persistence: %q\n", err) - } }() m := model.Metric{ @@ -1067,7 +1058,7 @@ func GetBoundaryValuesTests(persistenceMaker func() (MetricPersistence, io.Close } } -func GetRangeValuesTests(persistenceMaker func() (MetricPersistence, io.Closer), t test.Tester) { +func GetRangeValuesTests(persistenceMaker func() (MetricPersistence, test.Closer), t test.Tester) { type value struct { year int month time.Month @@ -1358,14 +1349,11 @@ func GetRangeValuesTests(persistenceMaker func() (MetricPersistence, io.Closer), p, closer := persistenceMaker() defer func() { + defer closer.Close() err := p.Close() if err != nil { t.Fatalf("Encountered anomaly closing persistence: %q\n", err) } - err = closer.Close() - if err != nil { - t.Fatalf("Encountered anomaly purging persistence: %q\n", err) - } }() m := model.Metric{ @@ -1487,8 +1475,8 @@ func BenchmarkLevelDBGetRangeValues(b *testing.B) { } func testMemoryGetValueAtTime(t test.Tester) { - persistenceMaker := func() (MetricPersistence, io.Closer) { - return NewMemorySeriesStorage(), ioutil.NopCloser(nil) + persistenceMaker := func() (MetricPersistence, test.Closer) { + return NewMemorySeriesStorage(), test.NilCloser } GetValueAtTimeTests(persistenceMaker, t) @@ -1505,8 +1493,8 @@ func BenchmarkMemoryGetValueAtTime(b *testing.B) { } func testMemoryGetBoundaryValues(t test.Tester) { - persistenceMaker := func() (MetricPersistence, io.Closer) { - return NewMemorySeriesStorage(), ioutil.NopCloser(nil) + persistenceMaker := func() (MetricPersistence, test.Closer) { + return NewMemorySeriesStorage(), test.NilCloser } GetBoundaryValuesTests(persistenceMaker, t) @@ -1523,8 +1511,8 @@ func BenchmarkMemoryGetBoundaryValues(b *testing.B) { } func testMemoryGetRangeValues(t test.Tester) { - persistenceMaker := func() (MetricPersistence, io.Closer) { - return NewMemorySeriesStorage(), ioutil.NopCloser(nil) + persistenceMaker := func() (MetricPersistence, test.Closer) { + return NewMemorySeriesStorage(), test.NilCloser } GetRangeValuesTests(persistenceMaker, t) diff --git a/storage/metric/stochastic_test.go b/storage/metric/stochastic_test.go index 062a2c1535..fd22cf53d7 100644 --- a/storage/metric/stochastic_test.go +++ b/storage/metric/stochastic_test.go @@ -17,7 +17,6 @@ import ( "fmt" "github.com/prometheus/prometheus/model" "github.com/prometheus/prometheus/utility/test" - "io/ioutil" "math" "math/rand" "testing" @@ -186,9 +185,10 @@ func AppendSampleAsPureSingleEntityAppendTests(p MetricPersistence, t test.Teste } } -func StochasticTests(persistenceMaker func() MetricPersistence, t test.Tester) { +func StochasticTests(persistenceMaker func() (MetricPersistence, test.Closer), t test.Tester) { stochastic := func(x int) (success bool) { - p := persistenceMaker() + p, closer := persistenceMaker() + defer closer.Close() defer func() { err := p.Close() if err != nil { @@ -497,18 +497,15 @@ func BenchmarkLevelDBAppendSampleAsPureSingleEntityAppend(b *testing.B) { } func testLevelDBStochastic(t test.Tester) { - persistenceMaker := func() MetricPersistence { - temporaryDirectory, err := ioutil.TempDir("", "test_leveldb_stochastic") - if err != nil { - t.Errorf("Could not create test directory: %q\n", err) - } + persistenceMaker := func() (MetricPersistence, test.Closer) { + temporaryDirectory := test.NewTemporaryDirectory("test_leveldb_stochastic", t) - p, err := NewLevelDBMetricPersistence(temporaryDirectory) + p, err := NewLevelDBMetricPersistence(temporaryDirectory.Path()) if err != nil { t.Errorf("Could not start up LevelDB: %q\n", err) } - return p + return p, temporaryDirectory } StochasticTests(persistenceMaker, t) @@ -585,8 +582,8 @@ func BenchmarkMemoryAppendSampleAsPureSingleEntityAppend(b *testing.B) { } func testMemoryStochastic(t test.Tester) { - persistenceMaker := func() MetricPersistence { - return NewMemorySeriesStorage() + persistenceMaker := func() (MetricPersistence, test.Closer) { + return NewMemorySeriesStorage(), test.NilCloser } StochasticTests(persistenceMaker, t) diff --git a/storage/metric/test_helper.go b/storage/metric/test_helper.go index 6bafbf3634..959f3f7845 100644 --- a/storage/metric/test_helper.go +++ b/storage/metric/test_helper.go @@ -17,9 +17,6 @@ import ( "fmt" "github.com/prometheus/prometheus/model" "github.com/prometheus/prometheus/utility/test" - "io" - "io/ioutil" - "os" "time" ) @@ -34,52 +31,25 @@ func testAppendSample(p MetricPersistence, s model.Sample, t test.Tester) { } } -type purger struct { - path string -} +func buildLevelDBTestPersistencesMaker(name string, t test.Tester) func() (MetricPersistence, test.Closer) { + return func() (MetricPersistence, test.Closer) { + temporaryDirectory := test.NewTemporaryDirectory("get_value_at_time", t) -func (p purger) Close() error { - return os.RemoveAll(p.path) -} - -func buildLevelDBTestPersistencesMaker(name string, t test.Tester) func() (MetricPersistence, io.Closer) { - return func() (MetricPersistence, io.Closer) { - temporaryDirectory, err := ioutil.TempDir("", "get_value_at_time") - if err != nil { - t.Errorf("Could not create test directory: %q\n", err) - } - - p, err := NewLevelDBMetricPersistence(temporaryDirectory) + p, err := NewLevelDBMetricPersistence(temporaryDirectory.Path()) if err != nil { t.Errorf("Could not start up LevelDB: %q\n", err) } - purger := purger{ - path: temporaryDirectory, - } - - return p, purger + return p, temporaryDirectory } - } func buildLevelDBTestPersistence(name string, f func(p MetricPersistence, t test.Tester)) func(t test.Tester) { return func(t test.Tester) { - temporaryDirectory, err := ioutil.TempDir("", fmt.Sprintf("test_leveldb_%s", name)) + temporaryDirectory := test.NewTemporaryDirectory(fmt.Sprintf("test_leveldb_%s", name), t) + defer temporaryDirectory.Close() - if err != nil { - t.Errorf("Could not create test directory: %q\n", err) - return - } - - defer func() { - err := os.RemoveAll(temporaryDirectory) - if err != nil { - t.Errorf("Could not remove temporary directory: %q\n", err) - } - }() - - p, err := NewLevelDBMetricPersistence(temporaryDirectory) + p, err := NewLevelDBMetricPersistence(temporaryDirectory.Path()) if err != nil { t.Errorf("Could not create LevelDB Metric Persistence: %q\n", err) } diff --git a/storage/metric/tiered_test.go b/storage/metric/tiered_test.go index a5e0b9bfaa..a689123d01 100644 --- a/storage/metric/tiered_test.go +++ b/storage/metric/tiered_test.go @@ -17,26 +17,25 @@ import ( "fmt" "github.com/prometheus/prometheus/model" "github.com/prometheus/prometheus/utility/test" - "io/ioutil" - "os" "sort" "testing" "time" ) type testTieredStorageCloser struct { - storage Storage - dirName string + storage Storage + directory test.Closer } -func (t *testTieredStorageCloser) Close() { +func (t testTieredStorageCloser) Close() { t.storage.Close() - os.RemoveAll(t.dirName) + t.directory.Close() } -func newTestTieredStorage(t test.Tester) (storage Storage, closer *testTieredStorageCloser) { - tempDir, _ := ioutil.TempDir("", "test_tiered_storage") - storage = NewTieredStorage(5000000, 2500, 1000, 5*time.Second, 15*time.Second, 0*time.Second, tempDir) +func newTestTieredStorage(t test.Tester) (storage Storage, closer test.Closer) { + var directory test.TemporaryDirectory + directory = test.NewTemporaryDirectory("test_tiered_storage", t) + storage = NewTieredStorage(5000000, 2500, 1000, 5*time.Second, 15*time.Second, 0*time.Second, directory.Path()) if storage == nil { t.Fatalf("%d. storage == nil") @@ -44,8 +43,8 @@ func newTestTieredStorage(t test.Tester) (storage Storage, closer *testTieredSto go storage.Serve() closer = &testTieredStorageCloser{ - storage: storage, - dirName: tempDir, + storage: storage, + directory: directory, } return } diff --git a/utility/test/directory.go b/utility/test/directory.go new file mode 100644 index 0000000000..537d8ade42 --- /dev/null +++ b/utility/test/directory.go @@ -0,0 +1,93 @@ +// Copyright 2013 Prometheus Team +// 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 test + +import ( + "io/ioutil" + "os" +) + +const ( + // The base directory used for test emissions, which instructs the operating + // system to use the default temporary directory as the base or TMPDIR + // environment variable. + defaultDirectory = "" + + // A NO-OP Closer. + NilCloser = nilCloser(true) +) + +type Closer interface { + // Close reaps the underlying directory and its children. The directory + // could be deleted by its users already. + Close() +} + +type nilCloser bool + +func (c nilCloser) Close() { +} + +// TemporaryDirectory models a closeable path for transient POSIX disk +// activities. +type TemporaryDirectory interface { + Closer + + // Path returns the underlying path for access. + Path() string +} + +// temporaryDirectory is kept as a private type due to private fields and their +// interactions. +type temporaryDirectory struct { + path string + tester Tester +} + +func (t temporaryDirectory) Close() { + err := os.RemoveAll(t.path) + if err != nil { + switch { + case os.IsNotExist(err): + return + default: + t.tester.Fatal(err) + } + } +} + +func (t temporaryDirectory) Path() string { + return t.path +} + +// NewTemporaryDirectory creates a new temporary directory for transient POSIX +// activities. +func NewTemporaryDirectory(name string, t Tester) (handler TemporaryDirectory) { + var ( + directory string + err error + ) + + directory, err = ioutil.TempDir(defaultDirectory, name) + if err != nil { + t.Fatal(err) + } + + handler = temporaryDirectory{ + path: directory, + tester: t, + } + + return +}