Skip to content
Permalink

Comparing changes

This is a direct comparison between two commits made in this repository or its related repositories. View the default comparison for this range or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: ipfs/go-datastore
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 8d7bb60c048498d8f6ffca1995f51ec3bc6a190b
Choose a base ref
..
head repository: ipfs/go-datastore
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: f2cf8767a00ff91306cfb9e7a1da6386b7deda03
Choose a head ref
Showing with 44 additions and 45 deletions.
  1. +1 −11 features.go
  2. +18 −21 features_test.go
  3. +2 −2 scoped/generate/main.go
  4. +1 −1 scoped/{impls.go → impls.gen.go}
  5. +2 −2 scoped/scoped.go
  6. +20 −8 scoped/scoped_test.go
12 changes: 1 addition & 11 deletions features.go
Original file line number Diff line number Diff line change
@@ -110,16 +110,6 @@ func Features() []Feature {
}
}

// FeaturesByNames returns the features with the given names, if they are known.
func FeaturesByNames(names ...string) (features []Feature) {
for _, n := range names {
if feat, ok := featuresByName[n]; ok {
features = append(features, feat)
}
}
return
}

// FeatureByName returns the feature with the given name, if known.
func FeatureByName(name string) (Feature, bool) {
feat, known := featuresByName[name]
@@ -131,7 +121,7 @@ func FeaturesForDatastore(dstore Datastore) (features []Feature) {
if dstore == nil {
return nil
}
dstoreType := reflect.ValueOf(dstore).Type()
dstoreType := reflect.TypeOf(dstore)
for _, f := range Features() {
fType := reflect.TypeOf(f.Interface).Elem()
if dstoreType.Implements(fType) {
39 changes: 18 additions & 21 deletions features_test.go
Original file line number Diff line number Diff line change
@@ -1,30 +1,11 @@
package datastore

import (
"fmt"
"reflect"
"testing"
)

func TestFeaturesByNames(t *testing.T) {
feats := FeaturesByNames()
if feats != nil {
t.Fatalf("expected nil features, got %v", feats)
}

feats = FeaturesByNames(FeatureNameBatching)
if len(feats) != 1 ||
feats[0].Name != FeatureNameBatching ||
feats[0].Interface != (*BatchingFeature)(nil) ||
feats[0].DatastoreInterface != (*Batching)(nil) {
t.Fatalf("expected a batching feature, got %v", feats)
}

feats = FeaturesByNames(FeatureNameBatching, "UnknownFeature")
if len(feats) != 1 || feats[0].Name != FeatureNameBatching {
t.Fatalf("expected a batching feature, got %v", feats)
}
}

func TestFeatureByName(t *testing.T) {
feat, ok := FeatureByName(FeatureNameBatching)
if !ok {
@@ -42,6 +23,17 @@ func TestFeatureByName(t *testing.T) {
}
}

func featuresByNames(names []string) (fs []Feature) {
for _, n := range names {
f, ok := FeatureByName(n)
if !ok {
panic(fmt.Sprintf("unknown feature %s", n))
}
fs = append(fs, f)
}
return
}

func TestFeaturesForDatastore(t *testing.T) {
cases := []struct {
name string
@@ -63,6 +55,11 @@ func TestFeaturesForDatastore(t *testing.T) {
d: &LogDatastore{},
expectedFeatures: []string{"Batching", "Checked", "GC", "Persistent", "Scrubbed"},
},
{
name: "nil datastore",
d: nil,
expectedFeatures: nil,
},
}

for _, c := range cases {
@@ -71,7 +68,7 @@ func TestFeaturesForDatastore(t *testing.T) {
if len(feats) != len(c.expectedFeatures) {
t.Fatalf("expected %d features, got %v", len(c.expectedFeatures), feats)
}
expectedFeats := FeaturesByNames(c.expectedFeatures...)
expectedFeats := featuresByNames(c.expectedFeatures)
if !reflect.DeepEqual(expectedFeats, feats) {
t.Fatalf("expected features %v, got %v", c.expectedFeatures, feats)
}
4 changes: 2 additions & 2 deletions scoped/generate/main.go
Original file line number Diff line number Diff line change
@@ -33,7 +33,7 @@ func (d *ds{{ $idx }}) Children() []ds.Datastore {
return []ds.Datastore{d.Datastore}
}
{{ end }}
var ctors = map[int]func(ds.Datastore) ds.Datastore{
var ctors = map[uint]func(ds.Datastore) ds.Datastore{
{{- range $idx, $features := .StructFeatures }}
{{ $idx }}: func(dstore ds.Datastore) ds.Datastore {
return &ds{{ $idx }}{
@@ -89,7 +89,7 @@ func main() {
panic(err)
}

f, err := os.Create("impls.go")
f, err := os.Create("impls.gen.go")
if err != nil {
panic(err)
}
2 changes: 1 addition & 1 deletion scoped/impls.go → scoped/impls.gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions scoped/scoped.go
Original file line number Diff line number Diff line change
@@ -32,10 +32,10 @@ func WithFeatures(dstore ds.Datastore, features []ds.Feature) ds.Datastore {
}
}

ctor := 0
var ctor uint
for i, f := range ds.Features() {
if _, ok := dstoreFeatureSet[f.Name]; ok {
ctor += (1 << i)
ctor |= (1 << uint(i))
}
}
return ctors[ctor](dstore)
28 changes: 20 additions & 8 deletions scoped/scoped_test.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,24 @@
package scoped

import (
"fmt"
"reflect"
"testing"

ds "github.com/ipfs/go-datastore"
)

func featuresByNames(names ...string) (fs []ds.Feature) {
for _, n := range names {
f, ok := ds.FeatureByName(n)
if !ok {
panic(fmt.Sprintf("unknown feature %s", n))
}
fs = append(fs, f)
}
return
}

func TestWithFeatures(t *testing.T) {
cases := []struct {
name string
@@ -24,26 +36,26 @@ func TestWithFeatures(t *testing.T) {
{
name: "identity case",
dstore: &ds.MapDatastore{},
features: ds.FeaturesByNames("Batching"),
expectedFeatures: ds.FeaturesByNames("Batching"),
features: featuresByNames("Batching"),
expectedFeatures: featuresByNames("Batching"),
},
{
name: "should scope down correctly",
dstore: &ds.LogDatastore{},
features: ds.FeaturesByNames("Batching"),
expectedFeatures: ds.FeaturesByNames("Batching"),
features: featuresByNames("Batching"),
expectedFeatures: featuresByNames("Batching"),
},
{
name: "takes intersection of features",
dstore: &ds.MapDatastore{},
features: ds.FeaturesByNames("Batching", "Checked"),
expectedFeatures: ds.FeaturesByNames("Batching"),
features: featuresByNames("Batching", "Checked"),
expectedFeatures: featuresByNames("Batching"),
},
{
name: "uses correct impl even if features are not canonically sorted",
dstore: &ds.NullDatastore{},
features: ds.FeaturesByNames("Checked", "Batching", "Scrubbed"),
expectedFeatures: ds.FeaturesByNames("Batching", "Checked", "Scrubbed"),
features: featuresByNames("Checked", "Batching", "Scrubbed"),
expectedFeatures: featuresByNames("Batching", "Checked", "Scrubbed"),
},
}
for _, c := range cases {