Include LevelDB fixture generators for curator.

This will help reduce common boilerplate for our test process
with respect to LevelDB-related things.
This commit is contained in:
Matt T. Proud 2013-03-27 12:52:08 +01:00
parent a4f0578a7e
commit 6dcaa28806
2 changed files with 145 additions and 22 deletions

View file

@ -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),
}
}

View file

@ -28,32 +28,34 @@ const (
NilCloser = nilCloser(true)
)
type Closer interface {
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() {
}
nilCloser bool
// TemporaryDirectory models a closeable path for transient POSIX disk
// activities.
type TemporaryDirectory interface {
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 {
// temporaryDirectory is kept as a private type due to private fields and
// their interactions.
temporaryDirectory struct {
path string
tester Tester
}
)
func (c nilCloser) Close() {
}
func (t temporaryDirectory) Close() {
err := os.RemoveAll(t.path)