2013-11-27 20:47:04 +00:00
|
|
|
/*
|
Rename import paths from camlistore.org to perkeep.org.
Part of the project renaming, issue #981.
After this, users will need to mv their $GOPATH/src/camlistore.org to
$GOPATH/src/perkeep.org. Sorry.
This doesn't yet rename the tools like camlistored, camput, camget,
camtool, etc.
Also, this only moves the lru package to internal. More will move to
internal later.
Also, this doesn't yet remove the "/pkg/" directory. That'll likely
happen later.
This updates some docs, but not all.
devcam test now passes again, even with Go 1.10 (which requires vet
checks are clean too). So a bunch of vet tests are fixed in this CL
too, and a bunch of other broken tests are now fixed (introduced from
the past week of merging the CL backlog).
Change-Id: If580db1691b5b99f8ed6195070789b1f44877dd4
2018-01-01 22:41:41 +00:00
|
|
|
Copyright 2013 The Perkeep Authors
|
2013-11-27 20:47:04 +00:00
|
|
|
|
|
|
|
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.
|
|
|
|
*/
|
|
|
|
|
2014-02-13 00:39:53 +00:00
|
|
|
package index_test
|
2013-11-27 20:47:04 +00:00
|
|
|
|
|
|
|
import (
|
2014-06-11 16:37:08 +00:00
|
|
|
"fmt"
|
2013-11-27 20:47:04 +00:00
|
|
|
"reflect"
|
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
|
2016-02-05 14:56:16 +00:00
|
|
|
"go4.org/types"
|
2018-01-19 18:53:44 +00:00
|
|
|
"perkeep.org/internal/testhooks"
|
Rename import paths from camlistore.org to perkeep.org.
Part of the project renaming, issue #981.
After this, users will need to mv their $GOPATH/src/camlistore.org to
$GOPATH/src/perkeep.org. Sorry.
This doesn't yet rename the tools like camlistored, camput, camget,
camtool, etc.
Also, this only moves the lru package to internal. More will move to
internal later.
Also, this doesn't yet remove the "/pkg/" directory. That'll likely
happen later.
This updates some docs, but not all.
devcam test now passes again, even with Go 1.10 (which requires vet
checks are clean too). So a bunch of vet tests are fixed in this CL
too, and a bunch of other broken tests are now fixed (introduced from
the past week of merging the CL backlog).
Change-Id: If580db1691b5b99f8ed6195070789b1f44877dd4
2018-01-01 22:41:41 +00:00
|
|
|
"perkeep.org/pkg/blob"
|
|
|
|
"perkeep.org/pkg/index"
|
|
|
|
"perkeep.org/pkg/index/indextest"
|
|
|
|
"perkeep.org/pkg/types/camtypes"
|
2013-11-27 20:47:04 +00:00
|
|
|
)
|
|
|
|
|
2018-03-02 17:29:52 +00:00
|
|
|
func newTestCorpusWithPermanode(t *testing.T) (c *index.Corpus, pn blob.Ref, keyID1, keyID2 string) {
|
2016-05-12 04:05:43 +00:00
|
|
|
c = index.ExpNewCorpus()
|
|
|
|
pn = blob.MustParse("abc-123")
|
2018-03-02 17:29:52 +00:00
|
|
|
sig1 := indextest.PubKey.BlobRef()
|
|
|
|
keyID2 = "abc-789"
|
|
|
|
sig2 := blob.MustParse(keyID2)
|
2018-01-19 18:53:44 +00:00
|
|
|
if err := c.Exp_AddKeyID(sig1, indextest.KeyID); err != nil {
|
2018-01-19 19:53:37 +00:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2018-03-02 17:29:52 +00:00
|
|
|
if err := c.Exp_AddKeyID(sig2, keyID2); err != nil {
|
2018-01-19 19:53:37 +00:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2013-11-27 20:47:04 +00:00
|
|
|
tm := time.Unix(99, 0)
|
2016-05-12 04:05:43 +00:00
|
|
|
claim := func(verb, attr, val string, sig blob.Ref) *camtypes.Claim {
|
2013-11-27 20:47:04 +00:00
|
|
|
tm = tm.Add(time.Second)
|
2013-12-09 13:15:34 +00:00
|
|
|
return &camtypes.Claim{
|
2016-05-12 04:05:43 +00:00
|
|
|
Type: verb + "-attribute",
|
|
|
|
Attr: attr,
|
|
|
|
Value: val,
|
|
|
|
Date: tm,
|
|
|
|
Signer: sig,
|
2013-11-27 20:47:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-01-27 16:09:18 +00:00
|
|
|
c.SetClaims(pn, []*camtypes.Claim{
|
2016-05-12 04:05:43 +00:00
|
|
|
claim("set", "foo", "foov", sig1), // time 100
|
|
|
|
|
|
|
|
claim("add", "tag", "a", sig1), // time 101
|
|
|
|
claim("add", "tag", "b", sig1), // time 102
|
|
|
|
claim("del", "tag", "", sig1),
|
|
|
|
claim("add", "tag", "c", sig1),
|
|
|
|
claim("add", "tag", "d", sig2),
|
|
|
|
claim("add", "tag", "e", sig1),
|
|
|
|
claim("del", "tag", "d", sig2),
|
|
|
|
claim("add", "tag", "f", sig2),
|
|
|
|
|
|
|
|
claim("add", "DelAll", "a", sig1),
|
|
|
|
claim("add", "DelAll", "b", sig1),
|
|
|
|
claim("add", "DelAll", "c", sig2),
|
|
|
|
claim("del", "DelAll", "", sig1),
|
|
|
|
|
|
|
|
claim("add", "DelOne", "a", sig1),
|
|
|
|
claim("add", "DelOne", "b", sig1),
|
|
|
|
claim("add", "DelOne", "c", sig1),
|
|
|
|
claim("add", "DelOne", "d", sig2),
|
|
|
|
claim("add", "DelOne", "e", sig2),
|
|
|
|
claim("del", "DelOne", "d", sig2),
|
|
|
|
claim("del", "DelOne", "a", sig1),
|
|
|
|
|
|
|
|
claim("add", "SetAfterAdd", "a", sig1),
|
|
|
|
claim("add", "SetAfterAdd", "b", sig1),
|
|
|
|
claim("add", "SetAfterAdd", "c", sig2),
|
|
|
|
claim("set", "SetAfterAdd", "setv", sig1),
|
|
|
|
|
|
|
|
// The claims below help testing
|
2016-01-27 16:09:18 +00:00
|
|
|
// slow and fast path equivalence
|
2016-05-12 04:05:43 +00:00
|
|
|
// (lookups based on pm.Claims and cached attrs).
|
|
|
|
//
|
|
|
|
// Permanode attr queries at time.Time{} and
|
|
|
|
// time.Unix(200, 0) should yield the same results
|
|
|
|
// for the above claims. The difference is that
|
|
|
|
// they use the cache at time.Time{} and
|
|
|
|
// the pm.Claims directly (bypassing the cache)
|
|
|
|
// at time.Unix(200, 0).
|
2016-01-27 16:09:18 +00:00
|
|
|
{
|
2016-05-12 04:05:43 +00:00
|
|
|
Type: "set-attribute",
|
|
|
|
Attr: "CacheTest",
|
|
|
|
Value: "foo",
|
|
|
|
Date: time.Unix(201, 0),
|
|
|
|
Signer: sig1,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Type: "set-attribute",
|
|
|
|
Attr: "CacheTest",
|
|
|
|
Value: "foo",
|
|
|
|
Date: time.Unix(202, 0),
|
|
|
|
Signer: sig2,
|
2013-11-27 20:47:04 +00:00
|
|
|
},
|
2014-02-13 00:39:53 +00:00
|
|
|
})
|
2013-11-27 20:47:04 +00:00
|
|
|
|
2018-03-02 17:29:52 +00:00
|
|
|
return c, pn, indextest.KeyID, keyID2
|
2016-01-27 16:09:18 +00:00
|
|
|
}
|
|
|
|
|
2018-03-02 17:29:52 +00:00
|
|
|
// TODO(mpl): remove that whole test?
|
|
|
|
|
2018-01-19 18:53:44 +00:00
|
|
|
func TestCorpusAnySignerHashWorks(t *testing.T) {
|
|
|
|
restore := testhooks.SetUseSHA1(true)
|
|
|
|
defer restore()
|
|
|
|
c, pn, sig1, sig2 := newTestCorpusWithPermanode(t)
|
|
|
|
|
|
|
|
// nothing special, just checking setup for foo attr with sig1 is correct
|
|
|
|
got := c.PermanodeAttrValue(pn, "foo", time.Time{}, sig1)
|
|
|
|
if got != "foov" {
|
|
|
|
t.Fatalf("with %v, attr %q = %q; want %q",
|
|
|
|
sig1, "foo", got, "foov")
|
|
|
|
}
|
|
|
|
// and that we can't find it with sig2
|
|
|
|
got = c.PermanodeAttrValue(pn, "foo", time.Time{}, sig2)
|
|
|
|
if got != "" {
|
|
|
|
t.Fatalf("expected empty result with sig2, got %q", got)
|
|
|
|
}
|
|
|
|
|
2018-03-02 17:29:52 +00:00
|
|
|
sig1SHA1 := indextest.PubKey.BlobRef()
|
2018-01-19 18:53:44 +00:00
|
|
|
testhooks.SetUseSHA1(false)
|
|
|
|
// now add sha224 version of sig1, and verify we can also find foo with it
|
|
|
|
sig1Current := indextest.PubKey.BlobRef()
|
2018-03-02 17:29:52 +00:00
|
|
|
if sig1SHA1 == sig1Current {
|
2018-01-19 18:53:44 +00:00
|
|
|
t.Fatal("sha1 signer ref and sha224 signer ref should be different")
|
|
|
|
}
|
|
|
|
if err := c.Exp_AddKeyID(sig1Current, indextest.KeyID); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2018-03-02 17:29:52 +00:00
|
|
|
got = c.PermanodeAttrValue(pn, "foo", time.Time{}, indextest.KeyID)
|
2018-01-19 18:53:44 +00:00
|
|
|
if got != "foov" {
|
|
|
|
t.Errorf("with %v, attr %q = %q; want %q",
|
|
|
|
sig1Current, "foo", got, "foov")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-01-27 16:09:18 +00:00
|
|
|
func TestCorpusAppendPermanodeAttrValues(t *testing.T) {
|
2018-01-19 19:53:37 +00:00
|
|
|
c, pn, sig1, sig2 := newTestCorpusWithPermanode(t)
|
2016-01-27 16:09:18 +00:00
|
|
|
s := func(s ...string) []string { return s }
|
|
|
|
|
2018-03-02 17:29:52 +00:00
|
|
|
sigMissing := "xyz-123"
|
2016-05-12 04:05:43 +00:00
|
|
|
|
2013-11-27 20:47:04 +00:00
|
|
|
tests := []struct {
|
|
|
|
attr string
|
|
|
|
want []string
|
|
|
|
t time.Time
|
2018-03-02 17:29:52 +00:00
|
|
|
sig string
|
2013-11-27 20:47:04 +00:00
|
|
|
}{
|
|
|
|
{attr: "not-exist", want: s()},
|
|
|
|
{attr: "DelAll", want: s()},
|
2016-05-12 04:05:43 +00:00
|
|
|
{attr: "DelOne", want: s("b", "c", "e")},
|
2013-11-27 20:47:04 +00:00
|
|
|
{attr: "foo", want: s("foov")},
|
2016-05-12 04:05:43 +00:00
|
|
|
{attr: "tag", want: s("c", "e", "f")},
|
2013-11-27 20:47:04 +00:00
|
|
|
{attr: "tag", want: s("a", "b"), t: time.Unix(102, 0)},
|
|
|
|
{attr: "SetAfterAdd", want: s("setv")},
|
2016-05-12 04:05:43 +00:00
|
|
|
// sig1
|
|
|
|
{attr: "not-exist", want: s(), sig: sig1},
|
|
|
|
{attr: "DelAll", want: s(), sig: sig1},
|
|
|
|
{attr: "DelOne", want: s("b", "c"), sig: sig1},
|
|
|
|
{attr: "foo", want: s("foov"), sig: sig1},
|
|
|
|
{attr: "tag", want: s("c", "e"), sig: sig1},
|
|
|
|
{attr: "tag", want: s("a", "b"), t: time.Unix(102, 0), sig: sig1},
|
|
|
|
{attr: "SetAfterAdd", want: s("setv"), sig: sig1},
|
|
|
|
// sig2
|
|
|
|
{attr: "DelAll", want: s("c"), sig: sig2},
|
|
|
|
{attr: "DelOne", want: s("e"), sig: sig2},
|
|
|
|
{attr: "tag", want: s("d"), t: time.Unix(105, 0), sig: sig2},
|
|
|
|
{attr: "SetAfterAdd", want: s("c"), sig: sig2},
|
|
|
|
// sigMissing (not present in pn)
|
|
|
|
{attr: "tag", want: s(), sig: sigMissing},
|
2013-11-27 20:47:04 +00:00
|
|
|
}
|
|
|
|
for i, tt := range tests {
|
2016-05-12 04:05:43 +00:00
|
|
|
got := c.AppendPermanodeAttrValues(nil, pn, tt.attr, tt.t, tt.sig)
|
2013-11-27 20:47:04 +00:00
|
|
|
if len(got) == 0 && len(tt.want) == 0 {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(got, tt.want) {
|
|
|
|
t.Errorf("%d. attr %q = %q; want %q",
|
|
|
|
i, tt.attr, got, tt.want)
|
|
|
|
}
|
2016-01-27 16:09:18 +00:00
|
|
|
|
|
|
|
if !tt.t.IsZero() {
|
|
|
|
// skip equivalence test if specific time was given
|
|
|
|
continue
|
|
|
|
}
|
2016-05-12 04:05:43 +00:00
|
|
|
got = c.AppendPermanodeAttrValues(nil, pn, tt.attr, time.Unix(200, 0), tt.sig)
|
2016-01-27 16:09:18 +00:00
|
|
|
if len(got) == 0 && len(tt.want) == 0 {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(got, tt.want) {
|
|
|
|
t.Errorf("%d. attr %q = %q; want %q",
|
|
|
|
i, tt.attr, got, tt.want)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-22 04:34:24 +00:00
|
|
|
func TestCorpusPermanodeAttrValue(t *testing.T) {
|
2018-01-19 19:53:37 +00:00
|
|
|
c, pn, sig1, sig2 := newTestCorpusWithPermanode(t)
|
2016-01-27 16:09:18 +00:00
|
|
|
|
|
|
|
tests := []struct {
|
|
|
|
attr string
|
|
|
|
want string
|
|
|
|
t time.Time
|
2018-03-02 17:29:52 +00:00
|
|
|
sig string
|
2016-01-27 16:09:18 +00:00
|
|
|
}{
|
|
|
|
{attr: "not-exist", want: ""},
|
|
|
|
{attr: "DelAll", want: ""},
|
|
|
|
{attr: "DelOne", want: "b"},
|
|
|
|
{attr: "foo", want: "foov"},
|
|
|
|
{attr: "tag", want: "c"},
|
|
|
|
{attr: "tag", want: "a", t: time.Unix(102, 0)},
|
|
|
|
{attr: "SetAfterAdd", want: "setv"},
|
2016-05-12 04:05:43 +00:00
|
|
|
// sig1
|
|
|
|
{attr: "not-exist", want: "", sig: sig1},
|
|
|
|
{attr: "DelAll", want: "", sig: sig1},
|
|
|
|
{attr: "DelOne", want: "b", sig: sig1},
|
|
|
|
{attr: "foo", want: "foov", sig: sig1},
|
|
|
|
{attr: "tag", want: "c", sig: sig1},
|
|
|
|
{attr: "SetAfterAdd", want: "setv", sig: sig1},
|
|
|
|
// sig2
|
|
|
|
{attr: "DelAll", want: "c", sig: sig2},
|
|
|
|
{attr: "DelOne", want: "e", sig: sig2},
|
|
|
|
{attr: "foo", want: "", sig: sig2},
|
|
|
|
{attr: "tag", want: "f", sig: sig2},
|
|
|
|
{attr: "SetAfterAdd", want: "c", sig: sig2},
|
2016-01-27 16:09:18 +00:00
|
|
|
}
|
|
|
|
for i, tt := range tests {
|
2016-05-12 04:05:43 +00:00
|
|
|
got := c.PermanodeAttrValue(pn, tt.attr, tt.t, tt.sig)
|
2016-01-27 16:09:18 +00:00
|
|
|
if len(got) == 0 && len(tt.want) == 0 {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(got, tt.want) {
|
|
|
|
t.Errorf("%d. attr %q = %q; want %q",
|
|
|
|
i, tt.attr, got, tt.want)
|
|
|
|
}
|
|
|
|
|
|
|
|
if !tt.t.IsZero() {
|
|
|
|
// skip equivalence test if specific time was given
|
|
|
|
continue
|
|
|
|
}
|
2016-05-12 04:05:43 +00:00
|
|
|
got = c.PermanodeAttrValue(pn, tt.attr, time.Unix(200, 0), tt.sig)
|
2016-01-27 16:09:18 +00:00
|
|
|
if len(got) == 0 && len(tt.want) == 0 {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(got, tt.want) {
|
|
|
|
t.Errorf("%d. attr %q = %q; want %q",
|
|
|
|
i, tt.attr, got, tt.want)
|
|
|
|
}
|
2013-11-27 20:47:04 +00:00
|
|
|
}
|
2016-01-27 16:09:18 +00:00
|
|
|
}
|
|
|
|
|
2016-04-22 04:34:24 +00:00
|
|
|
func TestCorpusPermanodeHasAttrValue(t *testing.T) {
|
2018-01-19 19:53:37 +00:00
|
|
|
c, pn, _, _ := newTestCorpusWithPermanode(t)
|
2016-01-27 16:09:18 +00:00
|
|
|
|
|
|
|
tests := []struct {
|
|
|
|
attr string
|
|
|
|
val string
|
|
|
|
want bool
|
|
|
|
t time.Time
|
|
|
|
}{
|
|
|
|
{attr: "DelAll", val: "a", want: false},
|
|
|
|
{attr: "DelOne", val: "b", want: true},
|
|
|
|
{attr: "DelOne", val: "a", want: false},
|
|
|
|
{attr: "foo", val: "foov", want: true},
|
|
|
|
{attr: "tag", val: "c", want: true},
|
|
|
|
{attr: "tag", val: "a", want: true, t: time.Unix(102, 0)},
|
|
|
|
{attr: "tag", val: "c", want: false, t: time.Unix(102, 0)},
|
|
|
|
{attr: "SetAfterAdd", val: "setv", want: true},
|
|
|
|
{attr: "SetAfterAdd", val: "a", want: false},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
2016-04-22 04:34:24 +00:00
|
|
|
got := c.PermanodeHasAttrValue(pn, tt.t, tt.attr, tt.val)
|
2016-01-27 16:09:18 +00:00
|
|
|
if got != tt.want {
|
|
|
|
t.Errorf("attr %q, val %q = %v; want %v",
|
|
|
|
tt.attr, tt.val, got, tt.want)
|
|
|
|
}
|
|
|
|
|
|
|
|
if !tt.t.IsZero() {
|
|
|
|
// skip equivalence test if specific time was given
|
|
|
|
continue
|
|
|
|
}
|
2016-04-22 04:34:24 +00:00
|
|
|
got = c.PermanodeHasAttrValue(pn, time.Unix(200, 0), tt.attr, tt.val)
|
2016-01-27 16:09:18 +00:00
|
|
|
if got != tt.want {
|
|
|
|
t.Errorf("attr %q, val %q = %v; want %v",
|
|
|
|
tt.attr, tt.val, got, tt.want)
|
|
|
|
}
|
|
|
|
}
|
2013-11-27 20:47:04 +00:00
|
|
|
}
|
2013-12-04 05:52:00 +00:00
|
|
|
|
|
|
|
func TestKVClaimAllocs(t *testing.T) {
|
|
|
|
n := testing.AllocsPerRun(20, func() {
|
2014-02-13 00:39:53 +00:00
|
|
|
index.ExpKvClaim("claim|sha1-b380b3080f9c71faa5c1d82bbd4d583a473bc77d|2931A67C26F5ABDA|2011-11-28T01:32:37.000123456Z|sha1-b3d93daee62e40d36237ff444022f42d7d0e43f2",
|
2013-12-04 05:52:00 +00:00
|
|
|
"set-attribute|tag|foo1|sha1-ad87ca5c78bd0ce1195c46f7c98e6025abbaf007",
|
|
|
|
blob.Parse)
|
|
|
|
})
|
|
|
|
t.Logf("%v allocations", n)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestKVClaim(t *testing.T) {
|
|
|
|
tests := []struct {
|
|
|
|
k, v string
|
|
|
|
ok bool
|
|
|
|
want camtypes.Claim
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
k: "claim|sha1-b380b3080f9c71faa5c1d82bbd4d583a473bc77d|2931A67C26F5ABDA|2011-11-28T01:32:37.000123456Z|sha1-b3d93daee62e40d36237ff444022f42d7d0e43f2",
|
|
|
|
v: "set-attribute|tag|foo1|sha1-ad87ca5c78bd0ce1195c46f7c98e6025abbaf007",
|
|
|
|
ok: true,
|
|
|
|
want: camtypes.Claim{
|
|
|
|
BlobRef: blob.MustParse("sha1-b3d93daee62e40d36237ff444022f42d7d0e43f2"),
|
|
|
|
Signer: blob.MustParse("sha1-ad87ca5c78bd0ce1195c46f7c98e6025abbaf007"),
|
|
|
|
Permanode: blob.MustParse("sha1-b380b3080f9c71faa5c1d82bbd4d583a473bc77d"),
|
|
|
|
Type: "set-attribute",
|
|
|
|
Attr: "tag",
|
|
|
|
Value: "foo1",
|
|
|
|
Date: time.Time(types.ParseTime3339OrZero("2011-11-28T01:32:37.000123456Z")),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
2014-02-13 00:39:53 +00:00
|
|
|
got, ok := index.ExpKvClaim(tt.k, tt.v, blob.Parse)
|
2013-12-04 05:52:00 +00:00
|
|
|
if ok != tt.ok {
|
|
|
|
t.Errorf("kvClaim(%q, %q) = ok %v; want %v", tt.k, tt.v, ok, tt.ok)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
if got != tt.want {
|
|
|
|
t.Errorf("kvClaim(%q, %q) = %+v; want %+v", tt.k, tt.v, got, tt.want)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-02-13 00:39:53 +00:00
|
|
|
|
2014-04-30 00:07:32 +00:00
|
|
|
func TestDeletePermanode_Modtime(t *testing.T) {
|
|
|
|
testDeletePermanodes(t,
|
2017-08-29 22:22:46 +00:00
|
|
|
func(c *index.Corpus, fn func(m camtypes.BlobMeta) bool) error {
|
|
|
|
c.EnumeratePermanodesLastModified(fn)
|
|
|
|
return nil
|
2014-04-30 00:07:32 +00:00
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestDeletePermanode_CreateTime(t *testing.T) {
|
|
|
|
testDeletePermanodes(t,
|
2017-08-29 22:22:46 +00:00
|
|
|
func(c *index.Corpus, fn func(m camtypes.BlobMeta) bool) error {
|
|
|
|
c.EnumeratePermanodesCreated(fn, true)
|
|
|
|
return nil
|
2014-04-30 00:07:32 +00:00
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
func testDeletePermanodes(t *testing.T,
|
2017-08-29 22:22:46 +00:00
|
|
|
enumFunc func(*index.Corpus, func(m camtypes.BlobMeta) bool) error) {
|
2018-01-09 23:07:38 +00:00
|
|
|
|
2014-02-13 00:39:53 +00:00
|
|
|
idx := index.NewMemoryIndex()
|
|
|
|
idxd := indextest.NewIndexDeps(idx)
|
2018-01-09 23:07:38 +00:00
|
|
|
idxd.Fataler = t
|
2014-02-13 00:39:53 +00:00
|
|
|
foopn := idxd.NewPlannedPermanode("foo")
|
|
|
|
idxd.SetAttribute(foopn, "tag", "foo")
|
|
|
|
barpn := idxd.NewPlannedPermanode("bar")
|
|
|
|
idxd.SetAttribute(barpn, "tag", "bar")
|
|
|
|
bazpn := idxd.NewPlannedPermanode("baz")
|
|
|
|
idxd.SetAttribute(bazpn, "tag", "baz")
|
|
|
|
idxd.Delete(barpn)
|
|
|
|
c, err := idxd.Index.KeepInMemory()
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("error slurping index to memory: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// check that we initially only find permanodes foo and baz,
|
|
|
|
// because bar is already marked as deleted.
|
|
|
|
want := []blob.Ref{foopn, bazpn}
|
|
|
|
var got []camtypes.BlobMeta
|
2017-08-29 22:22:46 +00:00
|
|
|
enumFunc(c, func(m camtypes.BlobMeta) bool {
|
|
|
|
got = append(got, m)
|
|
|
|
return true
|
|
|
|
})
|
2014-02-13 00:39:53 +00:00
|
|
|
if len(got) != len(want) {
|
|
|
|
t.Fatalf("Saw %d permanodes in corpus; want %d", len(got), len(want))
|
|
|
|
}
|
|
|
|
for _, bm := range got {
|
|
|
|
found := false
|
|
|
|
for _, perm := range want {
|
|
|
|
if bm.Ref == perm {
|
|
|
|
found = true
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if !found {
|
|
|
|
t.Fatalf("permanode %v was not found in corpus", bm.Ref)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// now add a delete claim for permanode baz, and check that we're only left with foo permanode
|
|
|
|
delbaz := idxd.Delete(bazpn)
|
|
|
|
want = []blob.Ref{foopn}
|
|
|
|
got = got[:0]
|
2017-08-29 22:22:46 +00:00
|
|
|
enumFunc(c, func(m camtypes.BlobMeta) bool {
|
|
|
|
got = append(got, m)
|
|
|
|
return true
|
|
|
|
})
|
2014-02-13 00:39:53 +00:00
|
|
|
if len(got) != len(want) {
|
|
|
|
t.Fatalf("Saw %d permanodes in corpus; want %d", len(got), len(want))
|
|
|
|
}
|
|
|
|
if got[0].Ref != foopn {
|
|
|
|
t.Fatalf("Wrong permanode found in corpus. Wanted %v, got %v", foopn, got[0].Ref)
|
|
|
|
}
|
|
|
|
|
|
|
|
// baz undeletion. delete delbaz.
|
|
|
|
idxd.Delete(delbaz)
|
|
|
|
want = []blob.Ref{foopn, bazpn}
|
|
|
|
got = got[:0]
|
2017-08-29 22:22:46 +00:00
|
|
|
enumFunc(c, func(m camtypes.BlobMeta) bool {
|
|
|
|
got = append(got, m)
|
|
|
|
return true
|
|
|
|
})
|
2014-02-13 00:39:53 +00:00
|
|
|
if len(got) != len(want) {
|
|
|
|
t.Fatalf("Saw %d permanodes in corpus; want %d", len(got), len(want))
|
|
|
|
}
|
|
|
|
for _, bm := range got {
|
|
|
|
found := false
|
|
|
|
for _, perm := range want {
|
|
|
|
if bm.Ref == perm {
|
|
|
|
found = true
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if !found {
|
|
|
|
t.Fatalf("permanode %v was not found in corpus", bm.Ref)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-04-30 00:07:32 +00:00
|
|
|
|
|
|
|
func TestEnumerateOrder_Modtime(t *testing.T) {
|
|
|
|
testEnumerateOrder(t,
|
2017-08-29 22:22:46 +00:00
|
|
|
func(c *index.Corpus, fn func(m camtypes.BlobMeta) bool) error {
|
|
|
|
c.EnumeratePermanodesLastModified(fn)
|
|
|
|
return nil
|
2014-04-30 00:07:32 +00:00
|
|
|
},
|
|
|
|
modtimeOrder,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestEnumerateOrder_CreateTime(t *testing.T) {
|
|
|
|
testEnumerateOrder(t,
|
2017-08-29 22:22:46 +00:00
|
|
|
func(c *index.Corpus, fn func(m camtypes.BlobMeta) bool) error {
|
|
|
|
c.EnumeratePermanodesCreated(fn, true)
|
|
|
|
return nil
|
2014-04-30 00:07:32 +00:00
|
|
|
},
|
|
|
|
createOrder,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
const (
|
|
|
|
modtimeOrder = iota
|
|
|
|
createOrder
|
|
|
|
)
|
|
|
|
|
|
|
|
func testEnumerateOrder(t *testing.T,
|
2017-08-29 22:22:46 +00:00
|
|
|
enumFunc func(*index.Corpus, func(m camtypes.BlobMeta) bool) error,
|
2014-04-30 00:07:32 +00:00
|
|
|
order int) {
|
|
|
|
idx := index.NewMemoryIndex()
|
|
|
|
idxd := indextest.NewIndexDeps(idx)
|
2018-01-09 23:07:38 +00:00
|
|
|
idxd.Fataler = t
|
2014-04-30 00:07:32 +00:00
|
|
|
|
|
|
|
// permanode with no contents
|
|
|
|
foopn := idxd.NewPlannedPermanode("foo")
|
|
|
|
idxd.SetAttribute(foopn, "tag", "foo")
|
|
|
|
// permanode with file contents
|
|
|
|
// we set the time of the contents 1 second older than the modtime of foopn
|
|
|
|
fooModTime := idxd.LastTime()
|
|
|
|
fileTime := fooModTime.Add(-1 * time.Second)
|
|
|
|
fileRef, _ := idxd.UploadFile("foo.html", "<html>I am an html file.</html>", fileTime)
|
|
|
|
barpn := idxd.NewPlannedPermanode("bar")
|
|
|
|
idxd.SetAttribute(barpn, "camliContent", fileRef.String())
|
|
|
|
|
|
|
|
c, err := idxd.Index.KeepInMemory()
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("error slurping index to memory: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// check that we get a different order whether with enumerate according to
|
|
|
|
// contents time, or to permanode modtime.
|
|
|
|
var want []blob.Ref
|
|
|
|
if order == modtimeOrder {
|
|
|
|
// modtime.
|
|
|
|
want = []blob.Ref{barpn, foopn}
|
|
|
|
} else {
|
|
|
|
// creation time.
|
|
|
|
want = []blob.Ref{foopn, barpn}
|
|
|
|
}
|
|
|
|
var got []camtypes.BlobMeta
|
2017-08-29 22:22:46 +00:00
|
|
|
enumFunc(c, func(m camtypes.BlobMeta) bool {
|
|
|
|
got = append(got, m)
|
|
|
|
return true
|
|
|
|
})
|
2014-04-30 00:07:32 +00:00
|
|
|
if len(got) != len(want) {
|
|
|
|
t.Fatalf("Saw %d permanodes in corpus; want %d", len(got), len(want))
|
|
|
|
}
|
|
|
|
for k, v := range got {
|
|
|
|
if v.Ref != want[k] {
|
|
|
|
t.Fatalf("Wrong result from enumeration. Got %v, wanted %v.", v.Ref, want[k])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-06-11 16:37:08 +00:00
|
|
|
|
|
|
|
// should be run with -race
|
|
|
|
func TestCacheSortedPermanodes_ModtimeRace(t *testing.T) {
|
|
|
|
testCacheSortedPermanodesRace(t,
|
2017-08-29 22:22:46 +00:00
|
|
|
func(c *index.Corpus, fn func(m camtypes.BlobMeta) bool) error {
|
|
|
|
c.EnumeratePermanodesLastModified(fn)
|
|
|
|
return nil
|
2014-06-11 16:37:08 +00:00
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
// should be run with -race
|
|
|
|
func TestCacheSortedPermanodes_CreateTimeRace(t *testing.T) {
|
|
|
|
testCacheSortedPermanodesRace(t,
|
2017-08-29 22:22:46 +00:00
|
|
|
func(c *index.Corpus, fn func(m camtypes.BlobMeta) bool) error {
|
|
|
|
c.EnumeratePermanodesCreated(fn, true)
|
|
|
|
return nil
|
2014-06-11 16:37:08 +00:00
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2017-08-29 22:22:46 +00:00
|
|
|
// TODO(mpl): see later if we can delete. or if we have to fix it further.
|
2014-06-11 16:37:08 +00:00
|
|
|
func testCacheSortedPermanodesRace(t *testing.T,
|
2017-08-29 22:22:46 +00:00
|
|
|
enumFunc func(*index.Corpus, func(m camtypes.BlobMeta) bool) error) {
|
2014-06-11 16:37:08 +00:00
|
|
|
idx := index.NewMemoryIndex()
|
|
|
|
idxd := indextest.NewIndexDeps(idx)
|
|
|
|
idxd.Fataler = t
|
2018-01-09 23:07:38 +00:00
|
|
|
|
2014-06-11 16:37:08 +00:00
|
|
|
c, err := idxd.Index.KeepInMemory()
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("error slurping index to memory: %v", err)
|
|
|
|
}
|
|
|
|
donec := make(chan struct{})
|
|
|
|
go func() {
|
|
|
|
for i := 0; i < 100; i++ {
|
|
|
|
nth := fmt.Sprintf("%d", i)
|
2016-05-03 13:00:35 +00:00
|
|
|
// No need to lock the index here. It is already done within NewPlannedPermanode,
|
|
|
|
// because it calls idxd.Index.ReceiveBlob.
|
2014-06-11 16:37:08 +00:00
|
|
|
pn := idxd.NewPlannedPermanode(nth)
|
|
|
|
idxd.SetAttribute(pn, "tag", nth)
|
|
|
|
}
|
|
|
|
donec <- struct{}{}
|
|
|
|
}()
|
|
|
|
go func() {
|
|
|
|
for i := 0; i < 10; i++ {
|
2017-08-29 22:22:46 +00:00
|
|
|
idx.RLock()
|
|
|
|
enumFunc(c, func(m camtypes.BlobMeta) bool {
|
|
|
|
return true
|
|
|
|
})
|
|
|
|
idx.RUnlock()
|
2014-06-11 16:37:08 +00:00
|
|
|
}
|
|
|
|
donec <- struct{}{}
|
|
|
|
}()
|
|
|
|
<-donec
|
|
|
|
<-donec
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestLazySortedPermanodes(t *testing.T) {
|
|
|
|
idx := index.NewMemoryIndex()
|
|
|
|
idxd := indextest.NewIndexDeps(idx)
|
|
|
|
idxd.Fataler = t
|
|
|
|
c, err := idxd.Index.KeepInMemory()
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("error slurping index to memory: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
lsp := c.Exp_LSPByTime(false)
|
|
|
|
if len(lsp) != 0 {
|
|
|
|
t.Fatal("LazySortedPermanodes cache should be empty on startup")
|
|
|
|
}
|
|
|
|
|
|
|
|
pn := idxd.NewPlannedPermanode("one")
|
|
|
|
idxd.SetAttribute(pn, "tag", "one")
|
|
|
|
|
|
|
|
enum := func(reverse bool) {
|
2017-08-19 05:26:51 +00:00
|
|
|
c.EnumeratePermanodesCreated(func(m camtypes.BlobMeta) bool { return true }, reverse)
|
2014-06-11 16:37:08 +00:00
|
|
|
}
|
|
|
|
enum(false)
|
|
|
|
lsp = c.Exp_LSPByTime(false)
|
|
|
|
if len(lsp) != 1 {
|
|
|
|
t.Fatalf("LazySortedPermanodes after 1st enum: got %v items, wanted 1", len(lsp))
|
|
|
|
}
|
|
|
|
lsp = c.Exp_LSPByTime(true)
|
|
|
|
if len(lsp) != 0 {
|
|
|
|
t.Fatalf("LazySortedPermanodes reversed after 1st enum: got %v items, wanted 0", len(lsp))
|
|
|
|
}
|
|
|
|
|
|
|
|
enum(true)
|
|
|
|
lsp = c.Exp_LSPByTime(false)
|
|
|
|
if len(lsp) != 1 {
|
|
|
|
t.Fatalf("LazySortedPermanodes after 2nd enum: got %v items, wanted 1", len(lsp))
|
|
|
|
}
|
|
|
|
lsp = c.Exp_LSPByTime(true)
|
|
|
|
if len(lsp) != 1 {
|
|
|
|
t.Fatalf("LazySortedPermanodes reversed after 2nd enum: got %v items, wanted 1", len(lsp))
|
|
|
|
}
|
|
|
|
|
|
|
|
pn = idxd.NewPlannedPermanode("two")
|
|
|
|
idxd.SetAttribute(pn, "tag", "two")
|
|
|
|
|
|
|
|
enum(true)
|
|
|
|
lsp = c.Exp_LSPByTime(false)
|
|
|
|
if len(lsp) != 0 {
|
|
|
|
t.Fatalf("LazySortedPermanodes after 2nd permanode: got %v items, wanted 0 because of cache invalidation", len(lsp))
|
|
|
|
}
|
|
|
|
lsp = c.Exp_LSPByTime(true)
|
|
|
|
if len(lsp) != 2 {
|
|
|
|
t.Fatalf("LazySortedPermanodes reversed after 2nd permanode: got %v items, wanted 2", len(lsp))
|
|
|
|
}
|
|
|
|
|
|
|
|
pn = idxd.NewPlannedPermanode("three")
|
|
|
|
idxd.SetAttribute(pn, "tag", "three")
|
|
|
|
|
|
|
|
enum(false)
|
|
|
|
lsp = c.Exp_LSPByTime(true)
|
|
|
|
if len(lsp) != 0 {
|
|
|
|
t.Fatalf("LazySortedPermanodes reversed after 3rd permanode: got %v items, wanted 0 because of cache invalidation", len(lsp))
|
|
|
|
}
|
|
|
|
lsp = c.Exp_LSPByTime(false)
|
|
|
|
if len(lsp) != 3 {
|
|
|
|
t.Fatalf("LazySortedPermanodes after 3rd permanode: got %v items, wanted 3", len(lsp))
|
|
|
|
}
|
|
|
|
|
|
|
|
enum(true)
|
|
|
|
lsp = c.Exp_LSPByTime(false)
|
|
|
|
if len(lsp) != 3 {
|
|
|
|
t.Fatalf("LazySortedPermanodes after 5th enum: got %v items, wanted 3", len(lsp))
|
|
|
|
}
|
|
|
|
lsp = c.Exp_LSPByTime(true)
|
|
|
|
if len(lsp) != 3 {
|
|
|
|
t.Fatalf("LazySortedPermanodes reversed after 5th enum: got %v items, wanted 3", len(lsp))
|
|
|
|
}
|
|
|
|
}
|