Browse Source

auth: fix remove subset when there are equal ranges

Xiang Li 9 years ago
parent
commit
e67613830e
2 changed files with 30 additions and 4 deletions
  1. 20 4
      auth/range_perm_cache.go
  2. 10 0
      auth/range_perm_cache_test.go

+ 20 - 4
auth/range_perm_cache.go

@@ -38,22 +38,38 @@ func isSubset(a, b *rangePerm) bool {
 	}
 }
 
+func isRangeEqual(a, b *rangePerm) bool {
+	return bytes.Equal(a.begin, b.begin) && bytes.Equal(a.end, b.end)
+}
+
 // removeSubsetRangePerms removes any rangePerms that are subsets of other rangePerms.
+// If there are equal ranges, removeSubsetRangePerms only keeps one of them.
 func removeSubsetRangePerms(perms []*rangePerm) []*rangePerm {
 	// TODO(mitake): currently it is O(n^2), we need a better algorithm
 	newp := make([]*rangePerm, 0)
 
 	for i := range perms {
-		subset := false
+		skip := false
 
 		for j := range perms {
-			if i != j && isSubset(perms[i], perms[j]) {
-				subset = true
+			if i == j {
+				continue
+			}
+
+			if isRangeEqual(perms[i], perms[j]) {
+				// if ranges are equal, we only keep the first range.
+				if i > j {
+					skip = true
+					break
+				}
+			} else if isSubset(perms[i], perms[j]) {
+				// if a range is a strict subset of the other one, we skip the subset.
+				skip = true
 				break
 			}
 		}
 
-		if subset {
+		if skip {
 			continue
 		}
 

+ 10 - 0
auth/range_perm_cache_test.go

@@ -108,6 +108,16 @@ func TestGetMergedPerms(t *testing.T) {
 			[]*rangePerm{{[]byte("a"), []byte("")}, {[]byte("b"), []byte("c")}, {[]byte("b"), []byte("")}, {[]byte("c"), []byte("")}, {[]byte("d"), []byte("")}},
 			[]*rangePerm{{[]byte("a"), []byte("")}, {[]byte("b"), []byte("c")}, {[]byte("d"), []byte("")}},
 		},
+		// duplicate ranges
+		{
+			[]*rangePerm{{[]byte("a"), []byte("f")}, {[]byte("a"), []byte("f")}},
+			[]*rangePerm{{[]byte("a"), []byte("f")}},
+		},
+		// duplicate keys
+		{
+			[]*rangePerm{{[]byte("a"), []byte("")}, {[]byte("a"), []byte("")}, {[]byte("a"), []byte("")}},
+			[]*rangePerm{{[]byte("a"), []byte("")}},
+		},
 	}
 
 	for i, tt := range tests {