Skip to content

Commit afc853c

Browse files
authored
Break potential infinite loop (#71)
* adding ut and fix * removing some files * remove the next branch when releasing a path * removing unneeded files Co-authored-by: Eliran Eretz-Kedosha <eleretzk@microsoft.com>
1 parent 8d59c92 commit afc853c

File tree

3 files changed

+79
-1
lines changed

3 files changed

+79
-1
lines changed

packages/red-black-tree/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
"ava": "^0.24.0",
3535
"rimraf": "^2.6.2",
3636
"tslint": "^5.9.1",
37-
"typescript": "^2.6.2"
37+
"typescript": "3.5.1"
3838
},
3939
"ava": {
4040
"files": [

packages/red-black-tree/src/internals/path.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ export class PathNode<K, V> {
6767
release (): PathNode<K, V> {
6868
var p = this.parent;
6969
this.node = NONE;
70+
this.next = BRANCH.NONE;
7071
this.parent = PathNode.cache;
7172
PathNode.cache = this;
7273
return p;
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import test from 'ava';
2+
import { empty, set } from '../../src';
3+
import { RedBlackTreeStructure, isNone } from '../../src/internals';
4+
5+
let tree: RedBlackTreeStructure<string, User>;
6+
7+
type User = {
8+
name: string,
9+
id: string
10+
};
11+
12+
const testUser1: User = {
13+
name: 'Luke',
14+
id: '298'
15+
};
16+
17+
const testUser2: User = {
18+
name: 'Leia',
19+
id: '299'
20+
};
21+
22+
const testUser3: User = {
23+
name: 'Han',
24+
id: '300'
25+
};
26+
27+
const testUser4: User = {
28+
name: 'Chewbacca',
29+
id: '301'
30+
};
31+
32+
test.beforeEach(() => {
33+
tree = empty<string, User>((a, b) => a < b ? -1 : (a > b ? 1 : 0), true);
34+
});
35+
36+
test('should keep the tree balanced', t => {
37+
t.plan(13);
38+
39+
// Set 298 and make sure it's the root and no other elements are there
40+
tree = set(testUser1.id, testUser1, tree);
41+
t.is(tree._root.key, testUser1.id);
42+
t.is(isNone(tree._root._left), true);
43+
t.is(isNone(tree._root._right), true);
44+
45+
// Set 299, no rebalance. 299 should be on the right
46+
tree = set(testUser2.id, testUser2, tree);
47+
t.is(tree._root.key, testUser1.id);
48+
t.is(isNone(tree._root._left), true);
49+
t.is(tree._root._right.key, testUser2.id);
50+
51+
// Set 300, this should cause a rebalance that puts 299 at the top
52+
tree = set(testUser3.id, testUser3, tree);
53+
t.is(tree._root.key, testUser2.id); // 299 is root
54+
t.is(tree._root._left.key, testUser1.id); // 298 goes left
55+
t.is(tree._root._right.key, testUser3.id); // 300 goes right
56+
57+
// Set 301, no rebalance - will go on the right of 300
58+
tree = set(testUser4.id, testUser4, tree);
59+
t.is(tree._root.key, testUser2.id); // 299 is root
60+
t.is(tree._root._left.key, testUser1.id); // 298 goes left
61+
t.is(tree._root._right.key, testUser3.id); // 300 goes right
62+
t.is(tree._root._right._right.key, testUser4.id); // 300 goes right
63+
});
64+
65+
test('should keep the tree balanced - many items synchronously', t => {
66+
// Add accounts to the tree which will trigger lots of rebalancing
67+
for (let i = 0; i < 1000; i++) {
68+
const user: User = {
69+
name: i.toString(),
70+
id: i.toString()
71+
};
72+
tree = set(user.id, user, tree);
73+
}
74+
75+
t.is(tree._root.key, '487');
76+
t.is(tree._size, 1000);
77+
});

0 commit comments

Comments
 (0)