From 6dcaa2880693b228ceaa44b245ba64f160d0e86a Mon Sep 17 00:00:00 2001 From: "Matt T. Proud" Date: Wed, 27 Mar 2013 12:52:08 +0100 Subject: [PATCH] Include LevelDB fixture generators for curator. This will help reduce common boilerplate for our test process with respect to LevelDB-related things. --- storage/raw/leveldb/test/fixtures.go | 121 +++++++++++++++++++++++++++ utility/test/directory.go | 46 +++++----- 2 files changed, 145 insertions(+), 22 deletions(-) create mode 100644 storage/raw/leveldb/test/fixtures.go diff --git a/storage/raw/leveldb/test/fixtures.go b/storage/raw/leveldb/test/fixtures.go new file mode 100644 index 000000000..81346f938 --- /dev/null +++ b/storage/raw/leveldb/test/fixtures.go @@ -0,0 +1,121 @@ +// 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 ( + "github.com/prometheus/prometheus/coding" + "github.com/prometheus/prometheus/storage/raw" + "github.com/prometheus/prometheus/storage/raw/leveldb" + "github.com/prometheus/prometheus/utility/test" +) + +const ( + cacheCapacity = 0 + bitsPerBloomFilterEncoded = 0 +) + +type ( + // Pair models a prospective (key, value) double that will be committed to + // a database. + Pair interface { + Get() (key, value coding.Encoder) + } + + // Pairs models a list of Pair for disk committing. + Pairs []Pair + + // Preparer readies a LevelDB store for a given raw state given the fixtures + // definitions passed into it. + Preparer interface { + // Prepare furnishes the database and returns its path along with any + // encountered anomalies. + Prepare(namespace string, f FixtureFactory) test.TemporaryDirectory + } + + FixtureFactory interface { + // HasNext indicates whether the FixtureFactory has more pending fixture + // data to build. + HasNext() (has bool) + // Next emits the next (key, value) double for storage. + Next() (key coding.Encoder, value coding.Encoder) + } + + preparer struct { + tester test.Tester + } + + cassetteFactory struct { + index int + count int + pairs Pairs + } +) + +func (p preparer) Prepare(n string, f FixtureFactory) (t test.TemporaryDirectory) { + t = test.NewTemporaryDirectory(n, p.tester) + + var ( + persistence raw.Persistence + err error + ) + + persistence, err = leveldb.NewLevelDBPersistence(t.Path(), cacheCapacity, bitsPerBloomFilterEncoded) + if err != nil { + defer t.Close() + p.tester.Fatal(err) + } + + for f.HasNext() { + var ( + key coding.Encoder + value coding.Encoder + ) + + key, value = f.Next() + + err = persistence.Put(key, value) + if err != nil { + defer t.Close() + p.tester.Fatal(err) + } + } + + return +} + +func (f cassetteFactory) HasNext() bool { + return f.index < f.count +} + +func (f *cassetteFactory) Next() (key, value coding.Encoder) { + key, value = f.pairs[f.index].Get() + + f.index++ + + return +} + +// NewPreparer creates a new Preparer for use in testing scenarios. +func NewPreparer(t test.Tester) Preparer { + return preparer{t} +} + +// NewCassetteFactory builds a new FixtureFactory that uses Pairs as the basis +// for generated fixture data. +func NewCassetteFactory(pairs Pairs) FixtureFactory { + return &cassetteFactory{ + pairs: pairs, + count: len(pairs), + } +} diff --git a/utility/test/directory.go b/utility/test/directory.go index 537d8ade4..4263fcf4b 100644 --- a/utility/test/directory.go +++ b/utility/test/directory.go @@ -28,33 +28,35 @@ const ( 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 ( + Closer interface { + // Close reaps the underlying directory and its children. The directory + // could be deleted by its users already. + Close() + } -type nilCloser bool + nilCloser bool + + // TemporaryDirectory models a closeable path for transient POSIX disk + // activities. + 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. + temporaryDirectory struct { + path string + tester Tester + } +) 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 {