2018-09-05 17:10:35 +01:00
|
|
|
// Copyright (C) 2018 Storj Labs, Inc.
|
|
|
|
// See LICENSE for copying information.
|
|
|
|
|
|
|
|
package testsuite
|
|
|
|
|
|
|
|
import (
|
|
|
|
"math/rand"
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
"storj.io/storj/storage"
|
|
|
|
)
|
|
|
|
|
|
|
|
func testIterateAll(t *testing.T, store storage.KeyValueStore) {
|
|
|
|
items := storage.Items{
|
|
|
|
newItem("a", "a", false),
|
|
|
|
newItem("b/1", "b/1", false),
|
|
|
|
newItem("b/2", "b/2", false),
|
|
|
|
newItem("b/3", "b/3", false),
|
|
|
|
newItem("c", "c", false),
|
|
|
|
newItem("c/", "c/", false),
|
|
|
|
newItem("c//", "c//", false),
|
|
|
|
newItem("c/1", "c/1", false),
|
|
|
|
newItem("g", "g", false),
|
|
|
|
newItem("h", "h", false),
|
|
|
|
}
|
|
|
|
rand.Shuffle(len(items), items.Swap)
|
|
|
|
defer cleanupItems(store, items)
|
2018-09-07 15:20:15 +01:00
|
|
|
if err := storage.PutAll(store, items...); err != nil {
|
|
|
|
t.Fatalf("failed to setup: %v", err)
|
2018-09-05 17:10:35 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
testIterations(t, store, []iterationTest{
|
|
|
|
{"no limits",
|
|
|
|
storage.IterateOptions{
|
|
|
|
Recurse: true,
|
|
|
|
}, storage.Items{
|
|
|
|
newItem("a", "a", false),
|
|
|
|
newItem("b/1", "b/1", false),
|
|
|
|
newItem("b/2", "b/2", false),
|
|
|
|
newItem("b/3", "b/3", false),
|
|
|
|
newItem("c", "c", false),
|
|
|
|
newItem("c/", "c/", false),
|
|
|
|
newItem("c//", "c//", false),
|
|
|
|
newItem("c/1", "c/1", false),
|
|
|
|
newItem("g", "g", false),
|
|
|
|
newItem("h", "h", false),
|
|
|
|
}},
|
2018-09-07 15:20:15 +01:00
|
|
|
{"no limits with non-nil first",
|
|
|
|
storage.IterateOptions{
|
|
|
|
Recurse: true,
|
|
|
|
First: storage.Key(""),
|
|
|
|
}, storage.Items{
|
|
|
|
newItem("a", "a", false),
|
|
|
|
newItem("b/1", "b/1", false),
|
|
|
|
newItem("b/2", "b/2", false),
|
|
|
|
newItem("b/3", "b/3", false),
|
|
|
|
newItem("c", "c", false),
|
|
|
|
newItem("c/", "c/", false),
|
|
|
|
newItem("c//", "c//", false),
|
|
|
|
newItem("c/1", "c/1", false),
|
|
|
|
newItem("g", "g", false),
|
|
|
|
newItem("h", "h", false),
|
|
|
|
}},
|
2018-09-05 17:10:35 +01:00
|
|
|
{"no limits reverse",
|
|
|
|
storage.IterateOptions{
|
|
|
|
Recurse: true, Reverse: true,
|
|
|
|
}, storage.Items{
|
|
|
|
newItem("h", "h", false),
|
|
|
|
newItem("g", "g", false),
|
|
|
|
newItem("c/1", "c/1", false),
|
|
|
|
newItem("c//", "c//", false),
|
|
|
|
newItem("c/", "c/", false),
|
|
|
|
newItem("c", "c", false),
|
|
|
|
newItem("b/3", "b/3", false),
|
|
|
|
newItem("b/2", "b/2", false),
|
|
|
|
newItem("b/1", "b/1", false),
|
|
|
|
newItem("a", "a", false),
|
|
|
|
}},
|
|
|
|
|
|
|
|
{"at a",
|
|
|
|
storage.IterateOptions{
|
|
|
|
First: storage.Key("a"),
|
|
|
|
Recurse: true,
|
|
|
|
}, storage.Items{
|
|
|
|
newItem("a", "a", false),
|
|
|
|
newItem("b/1", "b/1", false),
|
|
|
|
newItem("b/2", "b/2", false),
|
|
|
|
newItem("b/3", "b/3", false),
|
|
|
|
newItem("c", "c", false),
|
|
|
|
newItem("c/", "c/", false),
|
|
|
|
newItem("c//", "c//", false),
|
|
|
|
newItem("c/1", "c/1", false),
|
|
|
|
newItem("g", "g", false),
|
|
|
|
newItem("h", "h", false),
|
|
|
|
}},
|
|
|
|
{"at a reverse",
|
|
|
|
storage.IterateOptions{
|
|
|
|
First: storage.Key("a"),
|
|
|
|
Recurse: true, Reverse: true,
|
|
|
|
}, storage.Items{
|
|
|
|
newItem("a", "a", false),
|
|
|
|
}},
|
|
|
|
|
|
|
|
{"after a",
|
|
|
|
storage.IterateOptions{
|
|
|
|
First: storage.NextKey(storage.Key("a")),
|
|
|
|
Recurse: true,
|
|
|
|
}, storage.Items{
|
|
|
|
newItem("b/1", "b/1", false),
|
|
|
|
newItem("b/2", "b/2", false),
|
|
|
|
newItem("b/3", "b/3", false),
|
|
|
|
newItem("c", "c", false),
|
|
|
|
newItem("c/", "c/", false),
|
|
|
|
newItem("c//", "c//", false),
|
|
|
|
newItem("c/1", "c/1", false),
|
|
|
|
newItem("g", "g", false),
|
|
|
|
newItem("h", "h", false),
|
|
|
|
}},
|
|
|
|
|
|
|
|
{"at b",
|
|
|
|
storage.IterateOptions{
|
|
|
|
First: storage.Key("b"),
|
|
|
|
Recurse: true,
|
|
|
|
}, storage.Items{
|
|
|
|
newItem("b/1", "b/1", false),
|
|
|
|
newItem("b/2", "b/2", false),
|
|
|
|
newItem("b/3", "b/3", false),
|
|
|
|
newItem("c", "c", false),
|
|
|
|
newItem("c/", "c/", false),
|
|
|
|
newItem("c//", "c//", false),
|
|
|
|
newItem("c/1", "c/1", false),
|
|
|
|
newItem("g", "g", false),
|
|
|
|
newItem("h", "h", false),
|
|
|
|
}},
|
|
|
|
{"after b",
|
|
|
|
storage.IterateOptions{
|
|
|
|
First: storage.NextKey(storage.Key("b")),
|
|
|
|
Recurse: true,
|
|
|
|
}, storage.Items{
|
|
|
|
newItem("b/1", "b/1", false),
|
|
|
|
newItem("b/2", "b/2", false),
|
|
|
|
newItem("b/3", "b/3", false),
|
|
|
|
newItem("c", "c", false),
|
|
|
|
newItem("c/", "c/", false),
|
|
|
|
newItem("c//", "c//", false),
|
|
|
|
newItem("c/1", "c/1", false),
|
|
|
|
newItem("g", "g", false),
|
|
|
|
newItem("h", "h", false),
|
|
|
|
}},
|
|
|
|
|
|
|
|
{"at c",
|
|
|
|
storage.IterateOptions{
|
|
|
|
First: storage.Key("c"),
|
|
|
|
Recurse: true,
|
|
|
|
}, storage.Items{
|
|
|
|
newItem("c", "c", false),
|
|
|
|
newItem("c/", "c/", false),
|
|
|
|
newItem("c//", "c//", false),
|
|
|
|
newItem("c/1", "c/1", false),
|
|
|
|
newItem("g", "g", false),
|
|
|
|
newItem("h", "h", false),
|
|
|
|
}},
|
|
|
|
{"after c",
|
|
|
|
storage.IterateOptions{
|
|
|
|
First: storage.NextKey(storage.Key("c")),
|
|
|
|
Recurse: true,
|
|
|
|
}, storage.Items{
|
|
|
|
newItem("c/", "c/", false),
|
|
|
|
newItem("c//", "c//", false),
|
|
|
|
newItem("c/1", "c/1", false),
|
|
|
|
newItem("g", "g", false),
|
|
|
|
newItem("h", "h", false),
|
|
|
|
}},
|
|
|
|
|
|
|
|
{"at e",
|
|
|
|
storage.IterateOptions{
|
|
|
|
First: storage.Key("e"),
|
|
|
|
Recurse: true,
|
|
|
|
}, storage.Items{
|
|
|
|
newItem("g", "g", false),
|
|
|
|
newItem("h", "h", false),
|
|
|
|
}},
|
|
|
|
{"at e reverse",
|
|
|
|
storage.IterateOptions{
|
|
|
|
First: storage.Key("e"),
|
|
|
|
Recurse: true, Reverse: true,
|
|
|
|
}, storage.Items{
|
|
|
|
newItem("c/1", "c/1", false),
|
|
|
|
newItem("c//", "c//", false),
|
|
|
|
newItem("c/", "c/", false),
|
|
|
|
newItem("c", "c", false),
|
|
|
|
newItem("b/3", "b/3", false),
|
|
|
|
newItem("b/2", "b/2", false),
|
|
|
|
newItem("b/1", "b/1", false),
|
|
|
|
newItem("a", "a", false),
|
|
|
|
}},
|
|
|
|
|
|
|
|
{"prefix b slash",
|
|
|
|
storage.IterateOptions{
|
|
|
|
Prefix: storage.Key("b/"),
|
|
|
|
Recurse: true,
|
|
|
|
}, storage.Items{
|
|
|
|
newItem("b/1", "b/1", false),
|
|
|
|
newItem("b/2", "b/2", false),
|
|
|
|
newItem("b/3", "b/3", false),
|
|
|
|
}},
|
|
|
|
{"prefix b slash at a",
|
|
|
|
storage.IterateOptions{
|
|
|
|
Prefix: storage.Key("b/"), First: storage.Key("a"),
|
|
|
|
Recurse: true,
|
|
|
|
}, storage.Items{
|
|
|
|
newItem("b/1", "b/1", false),
|
|
|
|
newItem("b/2", "b/2", false),
|
|
|
|
newItem("b/3", "b/3", false),
|
|
|
|
}},
|
|
|
|
{"prefix b slash at b slash 2",
|
|
|
|
storage.IterateOptions{
|
|
|
|
Prefix: storage.Key("b/"), First: storage.Key("b/2"),
|
|
|
|
Recurse: true,
|
|
|
|
}, storage.Items{
|
|
|
|
newItem("b/2", "b/2", false),
|
|
|
|
newItem("b/3", "b/3", false),
|
|
|
|
}},
|
|
|
|
{"reverse prefix b slash",
|
|
|
|
storage.IterateOptions{
|
|
|
|
Prefix: storage.Key("b/"),
|
|
|
|
Recurse: true, Reverse: true,
|
|
|
|
}, storage.Items{
|
|
|
|
newItem("b/3", "b/3", false),
|
|
|
|
newItem("b/2", "b/2", false),
|
|
|
|
newItem("b/1", "b/1", false),
|
|
|
|
}},
|
|
|
|
{"reverse prefix b slash at b slash 2",
|
|
|
|
storage.IterateOptions{
|
|
|
|
Prefix: storage.Key("b/"), First: storage.Key("b/2"),
|
|
|
|
Recurse: true, Reverse: true,
|
|
|
|
}, storage.Items{
|
|
|
|
newItem("b/2", "b/2", false),
|
|
|
|
newItem("b/1", "b/1", false),
|
|
|
|
}},
|
|
|
|
|
|
|
|
{"prefix c slash",
|
|
|
|
storage.IterateOptions{
|
|
|
|
Prefix: storage.Key("c/"),
|
|
|
|
Recurse: true,
|
|
|
|
}, storage.Items{
|
|
|
|
newItem("c/", "c/", false),
|
|
|
|
newItem("c//", "c//", false),
|
|
|
|
newItem("c/1", "c/1", false),
|
|
|
|
}},
|
|
|
|
{"reverse prefix c slash",
|
|
|
|
storage.IterateOptions{
|
|
|
|
Prefix: storage.Key("c/"),
|
|
|
|
Recurse: true, Reverse: true,
|
|
|
|
}, storage.Items{
|
|
|
|
newItem("c/1", "c/1", false),
|
|
|
|
newItem("c//", "c//", false),
|
|
|
|
newItem("c/", "c/", false),
|
|
|
|
}},
|
|
|
|
|
|
|
|
{"prefix c slash slash",
|
|
|
|
storage.IterateOptions{
|
|
|
|
Prefix: storage.Key("c//"),
|
|
|
|
Recurse: true,
|
|
|
|
}, storage.Items{
|
|
|
|
newItem("c//", "c//", false),
|
|
|
|
}},
|
|
|
|
{"reverse prefix c slash slash",
|
|
|
|
storage.IterateOptions{
|
|
|
|
Prefix: storage.Key("c//"),
|
|
|
|
Recurse: true, Reverse: true,
|
|
|
|
}, storage.Items{
|
|
|
|
newItem("c//", "c//", false),
|
|
|
|
}},
|
|
|
|
})
|
|
|
|
}
|