blob: 58091cca1c34554cd05ccd3f643677694d38fcf2 [file] [log] [blame]
// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package vsync
import (
"testing"
wire "v.io/v23/services/syncbase"
)
var (
emptyRule = &wire.CrRule{Resolver: wire.ResolverTypeLastWins}
collectionRule = &wire.CrRule{CollectionId: wire.Id{"u", "t1"}, Resolver: wire.ResolverTypeLastWins}
collection2Rule = &wire.CrRule{CollectionId: wire.Id{"u", "t2"}, Resolver: wire.ResolverTypeAppResolves}
fooRule = &wire.CrRule{CollectionId: wire.Id{"u", "t1"}, KeyPrefix: "foo", Resolver: wire.ResolverTypeAppResolves}
foobarRule = &wire.CrRule{CollectionId: wire.Id{"u", "t1"}, KeyPrefix: "foobar", Resolver: wire.ResolverTypeLastWins}
foobar2Rule = &wire.CrRule{CollectionId: wire.Id{"u", "t1"}, KeyPrefix: "foobar", Resolver: wire.ResolverTypeDefer}
barRule = &wire.CrRule{CollectionId: wire.Id{"u", "t1"}, KeyPrefix: "bar", Resolver: wire.ResolverTypeAppResolves}
)
var (
schema = &wire.SchemaMetadata{Policy: wire.CrPolicy{
Rules: []wire.CrRule{
*emptyRule, *collectionRule, *collection2Rule, *fooRule, *foobarRule, *foobar2Rule, *barRule,
}}}
)
type testRule struct {
forRule *wire.CrRule
againstRule *wire.CrRule
result bool
}
func TestIsRuleMoreSpecific(t *testing.T) {
rules := []testRule{
createTestRule(collectionRule, emptyRule, true),
createTestRule(fooRule, collectionRule, true),
createTestRule(foobarRule, fooRule, true),
createTestRule(foobar2Rule, foobarRule, true),
createTestRule(emptyRule, collectionRule, false),
createTestRule(collection2Rule, collectionRule, false),
createTestRule(collectionRule, fooRule, false),
createTestRule(fooRule, foobarRule, false),
createTestRule(fooRule, barRule, false),
}
for _, test := range rules {
if isRuleMoreSpecific(test.forRule, test.againstRule) != test.result {
t.Errorf("failed test for rule %v against rule %v", test.forRule, test.againstRule)
}
}
}
func createTestRule(forRule, against *wire.CrRule, result bool) testRule {
return testRule{
forRule: forRule,
againstRule: against,
result: result,
}
}
type testOidRule struct {
oid string
rule *wire.CrRule
result bool
}
func TestIsRuleApplicable(t *testing.T) {
rules := []testOidRule{
makeTestOidRule("u", "t1", "foopie", emptyRule, true),
makeTestOidRule("u", "t1", "foopie", collectionRule, true),
makeTestOidRule("u", "t1", "foopie", fooRule, true),
makeTestOidRule("u", "t1", "abc", collectionRule, true),
makeTestOidRule("u", "t1", "fo", collectionRule, true),
makeTestOidRule("u", "t1", "foobar", foobarRule, true),
makeTestOidRule("u", "t3", "abc", emptyRule, true),
makeTestOidRule("u", "t1", "foopie", foobarRule, false),
makeTestOidRule("u", "t1", "foopie", collection2Rule, false),
makeTestOidRule("u", "t1", "foopie", barRule, false),
}
for _, test := range rules {
if isRuleApplicable(test.oid, test.rule) != test.result {
t.Errorf("failed test for oid %v for rule %v", test.oid, test.rule)
}
}
}
func makeTestOidRule(cxBlessing, cxName, row string, rule *wire.CrRule, result bool) testOidRule {
return testOidRule{
oid: makeRowKeyFromParts(cxBlessing, cxName, row),
rule: rule,
result: result,
}
}
type testResType struct {
oid string
result wire.ResolverType
}
func TestGetResolutionType(t *testing.T) {
testCases := []testResType{
testResType{oid: makeRowKeyFromParts("u", "t1", "abc"), result: wire.ResolverTypeLastWins},
testResType{oid: makeRowKeyFromParts("u", "t1", "fo"), result: wire.ResolverTypeLastWins},
testResType{oid: makeRowKeyFromParts("u", "t1", "foo"), result: wire.ResolverTypeAppResolves},
testResType{oid: makeRowKeyFromParts("u", "t1", "foopie"), result: wire.ResolverTypeAppResolves},
testResType{oid: makeRowKeyFromParts("u", "t1", "foobar"), result: wire.ResolverTypeDefer},
testResType{oid: makeRowKeyFromParts("u", "t1", "bar"), result: wire.ResolverTypeAppResolves},
testResType{oid: makeRowKeyFromParts("u", "t2", "abc"), result: wire.ResolverTypeAppResolves},
testResType{oid: makeCollectionPermsKey("u", "t2"), result: wire.ResolverTypeLastWins},
testResType{oid: makeRowKeyFromParts("u", "t3", "abc"), result: wire.ResolverTypeLastWins},
}
for _, test := range testCases {
if actual := getResolutionType(test.oid, schema); actual != test.result {
t.Errorf("failed test for oid %v, resolverType expected: %v actual: %v", test.oid, test.result, actual)
}
}
}
func TestGroupConflictsByType(t *testing.T) {
updObjMap := map[string]*objConflictState{}
updObjMap[makeRowKeyFromParts("u", "t1", "abc")] = &objConflictState{isConflict: true}
updObjMap[makeRowKeyFromParts("u", "t1", "fo")] = &objConflictState{isConflict: true}
updObjMap[makeRowKeyFromParts("u", "t1", "foo")] = &objConflictState{isConflict: true}
updObjMap[makeRowKeyFromParts("u", "t1", "foopie")] = &objConflictState{isConflict: true}
updObjMap[makeRowKeyFromParts("u", "t1", "foobar")] = &objConflictState{isConflict: true}
updObjMap[makeRowKeyFromParts("u", "t1", "bar")] = &objConflictState{isConflict: true}
updObjMap[makeRowKeyFromParts("u", "t2", "abc")] = &objConflictState{isConflict: true}
updObjMap[makeRowKeyFromParts("u", "t3", "abc")] = &objConflictState{isConflict: true}
iSt := initiationState{updObjects: updObjMap}
result := iSt.groupConflictsByType(schema)
verifyTypeGroupMember(t, result, wire.ResolverTypeLastWins, makeRowKeyFromParts("u", "t1", "abc"))
verifyTypeGroupMember(t, result, wire.ResolverTypeLastWins, makeRowKeyFromParts("u", "t1", "fo"))
verifyTypeGroupMember(t, result, wire.ResolverTypeLastWins, makeRowKeyFromParts("u", "t3", "abc"))
verifyTypeGroupMember(t, result, wire.ResolverTypeAppResolves, makeRowKeyFromParts("u", "t1", "foo"))
verifyTypeGroupMember(t, result, wire.ResolverTypeAppResolves, makeRowKeyFromParts("u", "t1", "foopie"))
verifyTypeGroupMember(t, result, wire.ResolverTypeAppResolves, makeRowKeyFromParts("u", "t1", "bar"))
verifyTypeGroupMember(t, result, wire.ResolverTypeAppResolves, makeRowKeyFromParts("u", "t2", "abc"))
verifyTypeGroupMember(t, result, wire.ResolverTypeDefer, makeRowKeyFromParts("u", "t1", "foobar"))
}
func verifyTypeGroupMember(t *testing.T, result map[wire.ResolverType]map[string]*objConflictState, rtype wire.ResolverType, oid string) {
if _, ok := result[rtype][oid]; !ok {
t.Errorf("object with oid: %v was not grouped under type: %v", oid, rtype)
}
}