Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | |
| 2 // for details. All rights reserved. Use of this source code is governed by a | |
| 3 // BSD-style license that can be found in the LICENSE file. | |
| 4 | |
| 5 library test.index.page_node_manager; | |
| 6 | |
| 7 import 'dart:math'; | |
| 8 import 'dart:typed_data'; | |
| 9 | |
| 10 import 'package:analysis_server/src/index/b_plus_tree.dart'; | |
| 11 import 'package:analysis_server/src/index/page_node_manager.dart'; | |
| 12 import 'package:unittest/unittest.dart'; | |
| 13 | |
| 14 import '../reflective_tests.dart'; | |
| 15 | |
| 16 | |
| 17 main() { | |
| 18 groupSep = ' | '; | |
| 19 group('FixedStringCodecTest', () { | |
| 20 runReflectiveTests(_FixedStringCodecTest); | |
| 21 }); | |
| 22 group('MemoryPageManager', () { | |
| 23 runReflectiveTests(_MemoryPageManagerTest); | |
| 24 }); | |
| 25 group('PageNodeManager', () { | |
| 26 runReflectiveTests(_PageNodeManagerTest); | |
| 27 }); | |
| 28 group('Uint32CodecTest', () { | |
| 29 runReflectiveTests(_Uint32CodecTest); | |
| 30 }); | |
| 31 test('B+ tree with PageNodeManager', _treeWithPageNodeManager); | |
| 32 } | |
| 33 | |
| 34 | |
| 35 int _intComparator(int a, int b) => a - b; | |
| 36 | |
| 37 | |
| 38 /** | |
| 39 * A stress test for [BPlusTree] using [PageNodeManager]. | |
| 40 */ | |
| 41 _treeWithPageNodeManager() { | |
| 42 int pageSize = 256; | |
| 43 MemoryPageManager pageManager = new MemoryPageManager(pageSize); | |
| 44 NodeManager<int, String, int> nodeManager = new PageNodeManager<int, String>( | |
| 45 pageManager, Uint32Codec.INSTANCE, new FixedStringCodec(7)); | |
| 46 // NodeManager<int, String, int> nodeManager = new MemoryNodeManager(); | |
| 47 int maxIndexKeys = (pageSize - 64) ~/ (4 + 4); | |
|
Paul Berry
2014/06/10 18:39:09
What's the source of the "- 64"?
scheglov
2014/06/10 20:12:12
Already cleaned up.
| |
| 48 int maxLeafKeys = (pageSize - 64) ~/ (4 + (2 + 2 * 7)); | |
| 49 print('maxIndexKeys: $maxIndexKeys maxLeafKeys: $maxLeafKeys'); | |
| 50 BPlusTree<int, String, int> tree = new BPlusTree(maxIndexKeys, maxLeafKeys, | |
| 51 _intComparator, nodeManager); | |
| 52 int maxKey = 1000000; | |
| 53 int tryCount = 1000; | |
| 54 Set<int> keys = new Set<int>(); | |
| 55 { | |
| 56 Random random = new Random(); | |
|
Paul Berry
2014/06/10 18:39:08
Using Random() makes the unit test nondeterministi
scheglov
2014/06/10 20:12:12
Done.
| |
| 57 for (int i = 0; i < tryCount; i++) { | |
| 58 int key = random.nextInt(maxKey); | |
| 59 keys.add(key); | |
| 60 tree.insert(key, 'V$key'); | |
| 61 } | |
| 62 } | |
| 63 // find every | |
| 64 for (int key in keys) { | |
| 65 expect(tree.find(key), 'V$key'); | |
| 66 } | |
| 67 // remove random keys | |
| 68 { | |
| 69 Random random = new Random(); | |
| 70 for (int key in new Set<int>.from(keys)) { | |
| 71 if (random.nextBool()) { | |
| 72 keys.remove(key); | |
| 73 expect(tree.remove(key), 'V$key'); | |
| 74 } | |
| 75 } | |
| 76 } | |
| 77 // find every remaining key | |
| 78 for (int key in keys) { | |
| 79 expect(tree.find(key), 'V$key'); | |
| 80 } | |
| 81 } | |
|
Paul Berry
2014/06/10 18:39:08
Should we also verify that all the removed keys ar
scheglov
2014/06/10 20:12:12
Done.
| |
| 82 | |
| 83 | |
| 84 @ReflectiveTestCase() | |
| 85 class _FixedStringCodecTest { | |
| 86 ByteData buffer; | |
| 87 Uint8List bytes = new Uint8List(2 + 2 * 4); | |
| 88 FixedStringCodec codec = new FixedStringCodec(4); | |
| 89 | |
| 90 void setUp() { | |
| 91 buffer = new ByteData.view(bytes.buffer); | |
| 92 } | |
| 93 | |
| 94 test_empty() { | |
| 95 // encode | |
| 96 codec.encode(buffer, ''); | |
| 97 expect(bytes, [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]); | |
| 98 // decode | |
| 99 expect(codec.decode(buffer), ''); | |
| 100 } | |
| 101 | |
| 102 test_fourChars() { | |
| 103 // encode | |
| 104 codec.encode(buffer, 'ABCD'); | |
| 105 expect(bytes, [0, 4, 0, 65, 0, 66, 0, 67, 0, 68]); | |
| 106 // decode | |
| 107 expect(codec.decode(buffer), 'ABCD'); | |
| 108 } | |
| 109 | |
| 110 test_tooManyChars() { | |
| 111 expect(() { | |
| 112 codec.encode(buffer, 'ABCDE'); | |
| 113 }, throws); | |
| 114 } | |
| 115 | |
| 116 test_twoChars() { | |
| 117 // encode | |
| 118 codec.encode(buffer, 'AB'); | |
| 119 expect(bytes, [0, 2, 0, 65, 0, 66, 0, 0, 0, 0]); | |
| 120 // decode | |
| 121 expect(codec.decode(buffer), 'AB'); | |
| 122 } | |
| 123 } | |
|
Paul Berry
2014/06/10 18:39:09
We should also test:
- Non-ASCII characters
- Unic
scheglov
2014/06/10 20:12:12
IIRC Dart sources are UTF-8 encoded.
I've added so
| |
| 124 | |
| 125 | |
| 126 | |
| 127 @ReflectiveTestCase() | |
| 128 class _MemoryPageManagerTest { | |
| 129 static const PAGE_SIZE = 8; | |
| 130 MemoryPageManager manager = new MemoryPageManager(PAGE_SIZE); | |
| 131 | |
| 132 test_alloc() { | |
| 133 int idA = manager.alloc(); | |
| 134 int idB = manager.alloc(); | |
| 135 expect(idB, isNot(idA)); | |
| 136 } | |
| 137 | |
| 138 test_free() { | |
| 139 int id = manager.alloc(); | |
| 140 manager.free(id); | |
| 141 // double free | |
| 142 expect(() { | |
| 143 manager.free(id); | |
| 144 }, throws); | |
| 145 } | |
| 146 | |
| 147 test_read() { | |
| 148 int id = manager.alloc(); | |
| 149 Uint8List page = manager.read(id); | |
| 150 expect(page.length, PAGE_SIZE); | |
| 151 } | |
| 152 | |
| 153 test_read_doesNotExist() { | |
| 154 expect(() { | |
| 155 manager.read(0); | |
| 156 }, throws); | |
| 157 } | |
| 158 | |
| 159 test_write() { | |
| 160 int id = manager.alloc(); | |
| 161 // do write | |
| 162 { | |
| 163 Uint8List page = new Uint8List(PAGE_SIZE); | |
| 164 page[3] = 42; | |
| 165 manager.write(id, page); | |
| 166 } | |
| 167 // now read | |
| 168 { | |
| 169 Uint8List page = manager.read(id); | |
| 170 expect(page.length, PAGE_SIZE); | |
| 171 expect(page[3], 42); | |
| 172 } | |
| 173 } | |
| 174 | |
| 175 test_write_doesNotExist() { | |
| 176 expect(() { | |
| 177 Uint8List page = new Uint8List(PAGE_SIZE); | |
| 178 manager.write(42, page); | |
| 179 }, throws); | |
| 180 } | |
| 181 } | |
| 182 | |
| 183 | |
| 184 | |
| 185 @ReflectiveTestCase() | |
| 186 class _PageNodeManagerTest { | |
| 187 static const Codec KEY_CODEC = Uint32Codec.INSTANCE; | |
| 188 static const int PAGE_SIZE = 128; | |
| 189 static const Codec VALUE_CODEC = const FixedStringCodec(4); | |
| 190 | |
| 191 PageNodeManager<int, String> nodeManager; | |
| 192 MemoryPageManager pageManager = new MemoryPageManager(PAGE_SIZE); | |
| 193 | |
| 194 setUp() { | |
| 195 nodeManager = new PageNodeManager<int, String>(pageManager, KEY_CODEC, | |
| 196 VALUE_CODEC); | |
| 197 } | |
| 198 | |
| 199 test_index_createDelete() { | |
| 200 int id = nodeManager.createIndex(); | |
| 201 expect(nodeManager.isIndex(id), isTrue); | |
| 202 // do delete | |
| 203 nodeManager.delete(id); | |
| 204 expect(nodeManager.isIndex(id), isFalse); | |
| 205 } | |
| 206 | |
| 207 test_index_readWrite() { | |
| 208 int id = nodeManager.createIndex(); | |
| 209 expect(nodeManager.isIndex(id), isTrue); | |
| 210 // write | |
| 211 { | |
| 212 var keys = [1, 2]; | |
| 213 var children = [10, 20, 30]; | |
| 214 nodeManager.writeIndex(id, new IndexNodeData<int, int>(keys, children)); | |
| 215 } | |
| 216 // check the page | |
| 217 { | |
| 218 Uint8List page = pageManager.read(id); | |
| 219 expect(page, [0, 0, 0, 2, 0, 0, 0, 10, 0, 0, 0, 1, 0, 0, 0, 20, 0, 0, 0, | |
| 220 2, 0, 0, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
| 221 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 , 0, 0, 0, | |
| 222 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 , 0, 0, 0, | |
| 223 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 , 0, 0, 0, | |
| 224 0, 0]); | |
| 225 } | |
| 226 // read | |
| 227 { | |
| 228 IndexNodeData<int, int> data = nodeManager.readIndex(id); | |
| 229 expect(data.keys, [1, 2]); | |
| 230 expect(data.children, [10, 20, 30]); | |
| 231 } | |
| 232 } | |
| 233 | |
| 234 test_leaf_readWrite() { | |
| 235 int id = nodeManager.createLeaf(); | |
| 236 expect(nodeManager.isIndex(id), isFalse); | |
| 237 // write | |
| 238 { | |
| 239 var keys = [1, 2, 3]; | |
| 240 var children = ['A', 'BB', 'CCC']; | |
| 241 nodeManager.writeLeaf(id, new LeafNodeData<int, String>(keys, children)); | |
| 242 } | |
| 243 // check the page | |
| 244 { | |
| 245 Uint8List page = pageManager.read(id); | |
| 246 expect(page, [0, 0, 0, 3, 0, 0, 0, 1, 0, 1, 0, 65, 0, 0, 0, 0, 0, 0, 0, 0, | |
| 247 0, 2, 0, 2, 0, 66, 0, 66, 0, 0, 0, 0, 0, 0, 0, 3, 0, 3, 0, 67, 0, 67, 0, 67, 0, | |
| 248 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 , 0, 0, 0, | |
| 249 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 , 0, 0, 0, | |
| 250 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 , 0, 0, 0, | |
| 251 0, 0]); | |
| 252 } | |
| 253 // read | |
| 254 { | |
| 255 LeafNodeData<int, String> data = nodeManager.readLeaf(id); | |
| 256 expect(data.keys, [1, 2, 3]); | |
| 257 expect(data.values, ['A', 'BB', 'CCC']); | |
| 258 } | |
| 259 } | |
| 260 } | |
| 261 | |
| 262 @ReflectiveTestCase() | |
| 263 class _Uint32CodecTest { | |
| 264 ByteData buffer; | |
| 265 Uint8List bytes = new Uint8List(4); | |
| 266 Uint32Codec codec = Uint32Codec.INSTANCE; | |
| 267 | |
| 268 void setUp() { | |
| 269 buffer = new ByteData.view(bytes.buffer); | |
| 270 } | |
| 271 | |
| 272 test_all() { | |
| 273 // encode | |
| 274 codec.encode(buffer, 42); | |
| 275 expect(bytes, [0, 0, 0, 42]); | |
| 276 // decode | |
| 277 expect(codec.decode(buffer), 42); | |
| 278 } | |
| 279 } | |
| OLD | NEW |