github.com/cayleygraph/cayley@v0.7.7/graph/kv/kvtest/kvtest.go (about)

     1  package kvtest
     2  
     3  import (
     4  	"context"
     5  	"reflect"
     6  	"testing"
     7  
     8  	"github.com/cayleygraph/cayley/graph"
     9  	"github.com/cayleygraph/cayley/graph/graphtest"
    10  	"github.com/cayleygraph/cayley/graph/graphtest/testutil"
    11  	"github.com/cayleygraph/cayley/graph/kv"
    12  	"github.com/cayleygraph/cayley/graph/shape"
    13  	"github.com/cayleygraph/quad"
    14  	hkv "github.com/hidal-go/hidalgo/kv"
    15  	"github.com/stretchr/testify/require"
    16  )
    17  
    18  type DatabaseFunc func(t testing.TB) (hkv.KV, graph.Options, func())
    19  
    20  type Config struct {
    21  	AlwaysRunIntegration bool
    22  }
    23  
    24  func (c Config) quadStore() *graphtest.Config {
    25  	return &graphtest.Config{
    26  		NoPrimitives:         true,
    27  		AlwaysRunIntegration: c.AlwaysRunIntegration,
    28  	}
    29  }
    30  
    31  func newQuadStoreFunc(gen DatabaseFunc, bloom bool) testutil.DatabaseFunc {
    32  	return func(t testing.TB) (graph.QuadStore, graph.Options, func()) {
    33  		return newQuadStore(t, gen, bloom)
    34  	}
    35  }
    36  
    37  func NewQuadStoreFunc(gen DatabaseFunc) testutil.DatabaseFunc {
    38  	return newQuadStoreFunc(gen, true)
    39  }
    40  
    41  func newQuadStore(t testing.TB, gen DatabaseFunc, bloom bool) (graph.QuadStore, graph.Options, func()) {
    42  	db, opt, closer := gen(t)
    43  	if opt == nil {
    44  		opt = make(graph.Options)
    45  	}
    46  	if !bloom {
    47  		opt[kv.OptNoBloom] = true
    48  	}
    49  	err := kv.Init(db, opt)
    50  	if err != nil {
    51  		db.Close()
    52  		closer()
    53  		require.Fail(t, "init failed", "%v", err)
    54  	}
    55  	kdb, err := kv.New(db, opt)
    56  	if err != nil {
    57  		db.Close()
    58  		closer()
    59  		require.Fail(t, "create failed", "%v", err)
    60  	}
    61  	return kdb, opt, func() {
    62  		kdb.Close()
    63  		closer()
    64  	}
    65  }
    66  
    67  func NewQuadStore(t testing.TB, gen DatabaseFunc) (graph.QuadStore, graph.Options, func()) {
    68  	return newQuadStore(t, gen, true)
    69  }
    70  
    71  func TestAll(t *testing.T, gen DatabaseFunc, conf *Config) {
    72  	if conf == nil {
    73  		conf = &Config{}
    74  	}
    75  	qsgen := NewQuadStoreFunc(gen)
    76  	t.Run("qs", func(t *testing.T) {
    77  		graphtest.TestAll(t, qsgen, conf.quadStore())
    78  	})
    79  	qsgenNoBloom := newQuadStoreFunc(gen, false)
    80  	t.Run("qs-no-bloom", func(t *testing.T) {
    81  		graphtest.TestAll(t, qsgenNoBloom, conf.quadStore())
    82  	})
    83  	t.Run("optimize", func(t *testing.T) {
    84  		testOptimize(t, gen, conf)
    85  	})
    86  }
    87  
    88  func testOptimize(t *testing.T, gen DatabaseFunc, _ *Config) {
    89  	ctx := context.TODO()
    90  	qs, opts, closer := NewQuadStore(t, gen)
    91  	defer closer()
    92  
    93  	testutil.MakeWriter(t, qs, opts, graphtest.MakeQuadSet()...)
    94  
    95  	// With an linksto-fixed pair
    96  	lto := shape.BuildIterator(qs, shape.Quads{
    97  		{Dir: quad.Object, Values: shape.Lookup{quad.Raw("F")}},
    98  	})
    99  
   100  	oldIt := shape.BuildIterator(qs, shape.Quads{
   101  		{Dir: quad.Object, Values: shape.Lookup{quad.Raw("F")}},
   102  	})
   103  	newIt, ok := lto.Optimize()
   104  	if ok {
   105  		t.Errorf("unexpected optimization step")
   106  	}
   107  	if _, ok := newIt.(*kv.QuadIterator); !ok {
   108  		t.Errorf("Optimized iterator type does not match original, got: %T", newIt)
   109  	}
   110  
   111  	newQuads := graphtest.IteratedQuads(t, qs, newIt)
   112  	oldQuads := graphtest.IteratedQuads(t, qs, oldIt)
   113  	if !reflect.DeepEqual(newQuads, oldQuads) {
   114  		t.Errorf("Optimized iteration does not match original")
   115  	}
   116  
   117  	oldIt.Next(ctx)
   118  	oldResults := make(map[string]graph.Ref)
   119  	oldIt.TagResults(oldResults)
   120  	newIt.Next(ctx)
   121  	newResults := make(map[string]graph.Ref)
   122  	newIt.TagResults(newResults)
   123  	if !reflect.DeepEqual(newResults, oldResults) {
   124  		t.Errorf("Discordant tag results, new:%v old:%v", newResults, oldResults)
   125  	}
   126  }
   127  
   128  func BenchmarkAll(t *testing.B, gen DatabaseFunc, conf *Config) {
   129  	if conf == nil {
   130  		conf = &Config{}
   131  	}
   132  	qsgen := NewQuadStoreFunc(gen)
   133  	t.Run("qs", func(t *testing.B) {
   134  		graphtest.BenchmarkAll(t, qsgen, conf.quadStore())
   135  	})
   136  }