[fuchsia_inspect] Implement implicit root nodes.
Design: go/inspect-root
Change-Id: I2c65c4563fba73405aa1ab99b9ddbf0a45391d9d
diff --git a/public/dart/fuchsia_inspect/lib/src/testing/matcher.dart b/public/dart/fuchsia_inspect/lib/src/testing/matcher.dart
index 890c11c..be9b845 100644
--- a/public/dart/fuchsia_inspect/lib/src/testing/matcher.dart
+++ b/public/dart/fuchsia_inspect/lib/src/testing/matcher.dart
@@ -46,12 +46,7 @@
/// Retrieve the root node matcher, which can be used to match against
/// nested properties and children.
NodeMatcher node() {
- if (Block.read(_holder, 1).type == BlockType.nodeValue) {
- return NodeMatcher._valid(this, 1);
- } else {
- _addError('No root node found at index 1');
- return NodeMatcher._invalid(this);
- }
+ return NodeMatcher._valid(this, 0);
}
// Internal method to check if the given index is valid and can be
diff --git a/public/dart/fuchsia_inspect/lib/src/vmo/block.dart b/public/dart/fuchsia_inspect/lib/src/vmo/block.dart
index e5b02c0..51eff4f 100644
--- a/public/dart/fuchsia_inspect/lib/src/vmo/block.dart
+++ b/public/dart/fuchsia_inspect/lib/src/vmo/block.dart
@@ -104,17 +104,6 @@
_vmo.writeInt64Direct(_payloadOffset, _payloadBits.value);
}
- /// Initializes the root [BlockType.nodeValue] block.
- ///
- /// Throws [StateError] if this block wasn't [BlockType.reserved].
- void becomeRoot() {
- _checkType(BlockType.reserved);
- becomeValue(parentIndex: rootParentIndex, nameIndex: rootNameIndex);
- _header.write(orderBits, 0);
- becomeNode();
- _writeAllBits();
- }
-
/// Converts a [BlockType.anyValue] block to a [BlockType.nodeValue] block.
///
/// Throws [StateError] if this block wasn't [BlockType.anyValue].
diff --git a/public/dart/fuchsia_inspect/lib/src/vmo/vmo_fields.dart b/public/dart/fuchsia_inspect/lib/src/vmo/vmo_fields.dart
index fcaddf5..e3ad98b 100644
--- a/public/dart/fuchsia_inspect/lib/src/vmo/vmo_fields.dart
+++ b/public/dart/fuchsia_inspect/lib/src/vmo/vmo_fields.dart
@@ -24,17 +24,8 @@
/// Version for HEADER block.
const int headerVersionNumber = 0;
-/// Index of the one-and-only root node (16 bytes).
-const int rootNodeIndex = 1;
-
-/// Each Node needs a parent; Root's parent is 0, which is never a real node.
-const int rootParentIndex = 0;
-
-/// Index of the NAME of the one-and-only root node (32 bytes).
-const int rootNameIndex = 2;
-
-/// First index availalbe for the heap.
-const int heapStartIndex = 4;
+/// First index available for the heap.
+const int heapStartIndex = 2;
/// Size of VMO-block's header bitfield in bytes.
const int headerSizeBytes = 8;
diff --git a/public/dart/fuchsia_inspect/lib/src/vmo/vmo_writer.dart b/public/dart/fuchsia_inspect/lib/src/vmo/vmo_writer.dart
index 813ddb8..4a0e71a 100644
--- a/public/dart/fuchsia_inspect/lib/src/vmo/vmo_writer.dart
+++ b/public/dart/fuchsia_inspect/lib/src/vmo/vmo_writer.dart
@@ -18,9 +18,6 @@
/// Index 0 will never be allocated, so it's the designated 'invalid' value.
const int invalidIndex = 0;
-/// Name of the root node.
-const String rootName = 'root';
-
/// An Inspect-format VMO with accessors.
///
/// This writes Values (Nodes, Metrics, and Properties) to
@@ -46,9 +43,6 @@
VmoWriter(this._vmo, Function heapFactory) {
_vmo.beginWork();
_headerBlock = Block.create(_vmo, headerIndex)..becomeHeader();
- Block.create(_vmo, rootNodeIndex, order: defaultBlockOrder).becomeRoot();
- Block.create(_vmo, rootNameIndex, order: defaultBlockOrder)
- .becomeName(rootName);
_heap = heapFactory(_vmo);
_vmo.commit();
}
@@ -62,8 +56,8 @@
/// Creates a [VmoWriter] with a given VMO.
factory VmoWriter.withVmo(VmoHolder vmo) => VmoWriter(vmo, _heapCreate);
- /// Gets the top Node of the Inspect tree (always at index 1).
- int get rootNode => rootNodeIndex;
+ /// Gets the top Node of the Inspect tree (always set to index 0, which is the header).
+ int get rootNode => 0;
/// The underlying VMO
Vmo get vmo => _vmo.vmo;
@@ -221,7 +215,10 @@
}
nameBlock.becomeName(name);
block.becomeValue(parentIndex: parent, nameIndex: nameBlock.index);
- Block.read(_vmo, parent).childCount += 1;
+ if (parent != 0) {
+ // Only increment child count if the parent is not the special header block.
+ Block.read(_vmo, parent).childCount += 1;
+ }
return block;
}
@@ -315,6 +312,11 @@
// If the parent is a TOMBSTONE and has no children then free it.
// TOMBSTONES have no parent, so there's no recursion.
void _unparent(Block value) {
+ if (value.parentIndex == 0) {
+ // Never delete the header node.
+ return;
+ }
+
var parent = Block.read(_vmo, value.parentIndex);
if (--parent.childCount == 0 && parent.type == BlockType.tombstone) {
_heap.freeBlock(parent);
diff --git a/public/dart/fuchsia_inspect/test/vmo/block_test.dart b/public/dart/fuchsia_inspect/test/vmo/block_test.dart
index 78f7860..f0a0afc 100644
--- a/public/dart/fuchsia_inspect/test/vmo/block_test.dart
+++ b/public/dart/fuchsia_inspect/test/vmo/block_test.dart
@@ -22,8 +22,6 @@
block.unlock();
});
_accepts(
- 'becomeRoot', [BlockType.reserved], (block) => block.becomeRoot());
- _accepts(
'becomeNode', [BlockType.anyValue], (block) => block.becomeNode());
_accepts('becomeProperty', [BlockType.anyValue],
(block) => block.becomeProperty());
@@ -159,13 +157,6 @@
'00 0000 49 4E 53 50 0200 0000 0000 0000');
});
- test('Becoming the special root node', () {
- final vmo = FakeVmoHolder(64);
- Block.create(vmo, 1).becomeRoot();
- compare(vmo, 16,
- '${hexChar(BlockType.nodeValue.value)} 0 00 0000 2000 0000 0000');
- });
-
test('Becoming and modifying an intValue via free, reserved, anyValue', () {
final vmo = FakeVmoHolder(64);
final block = Block.create(vmo, 2)..becomeFree(5);
diff --git a/public/dart/fuchsia_inspect/test/vmo/heap_test.dart b/public/dart/fuchsia_inspect/test/vmo/heap_test.dart
index eadb586..f3704c9 100644
--- a/public/dart/fuchsia_inspect/test/vmo/heap_test.dart
+++ b/public/dart/fuchsia_inspect/test/vmo/heap_test.dart
@@ -15,15 +15,15 @@
// In the VMO data structure, indexes 0..3 are reserved for VMO HEADER block,
// root-node block, and root-node's name.
//
-// A 128-byte heap holds indexes 0..7 (at 16 bytes per index).
+// A 96-byte heap holds indexes 0..5 (at 16 bytes per index).
// Since allocated blocks are 32 bytes, the first allocated block will be at
-// index 4, and the second will be at index 6.
+// index 2, and the second will be at index 4.
//
// Two allocated blocks should be enough to test the data structure
-// algorithms, so the heap will be conveniently small at 128 bytes, and
-// we'll expect to see 4 and 6 as valid allocated indexes.
-const int _heapSizeBytes = 128;
-const List<int> _allocatedIndexes = [4, 6];
+// algorithms, so the heap will be conveniently small at 96 bytes, and
+// we'll expect to see 2 and 4 as valid allocated indexes.
+const int _heapSizeBytes = 96;
+const List<int> _allocatedIndexes = [2, 4];
void main() {
group('In the Heap', () {
@@ -33,12 +33,10 @@
var f = hexChar(BlockType.free.value);
compare(vmo, 0x00, '0 0 000000 00000000 00000000 00000000');
compare(vmo, 0x10, '0 0 000000 00000000 00000000 00000000');
- compare(vmo, 0x20, '0 0 000000 00000000 00000000 00000000');
+ compare(vmo, 0x20, '$f 1 000000 00000000 00000000 00000000');
compare(vmo, 0x30, '0 0 000000 00000000 00000000 00000000');
compare(vmo, 0x40, '$f 1 0_0000 00000000 00000000 00000000');
compare(vmo, 0x50, '0 0 000000 00000000 00000000 00000000');
- compare(vmo, 0x60, '$f 1 0_0000 00000000 00000000 00000000');
- compare(vmo, 0x70, '0 0 000000 00000000 00000000 00000000');
});
test('allocate changes VMO contents correctly', () {
@@ -47,10 +45,10 @@
var blocks = _allocateEverything(heap);
expect(blocks, hasLength(2));
var r = hexChar(BlockType.reserved.value);
+ compare(vmo, 0x20, '$r 1 0_0000 00000000 00000000 00000000');
+ compare(vmo, 0x30, '0 0 000000 00000000 00000000 00000000');
compare(vmo, 0x40, '$r 1 0_0000 00000000 00000000 00000000');
compare(vmo, 0x50, '0 0 000000 00000000 00000000 00000000');
- compare(vmo, 0x60, '$r 1 0_0000 00000000 00000000 00000000');
- compare(vmo, 0x70, '0 0 000000 00000000 00000000 00000000');
});
test('free and re-allocate work correctly', () {
@@ -80,7 +78,7 @@
}
// Make sure we're actually getting unique blocks
expect(Set.of(blocks.map((block) => block.index)), hasLength(blocks.length));
- // With a heapSize-byte VMO, valid indexes are only 4 and 6 (see comment above).
+ // With a heapSize-byte VMO, valid indexes are only 2 and 4 (see comment above).
for (var block in blocks) {
expect(block.index, isIn(_allocatedIndexes));
}
diff --git a/public/dart/fuchsia_inspect/test/vmo/little_big_slab_test.dart b/public/dart/fuchsia_inspect/test/vmo/little_big_slab_test.dart
index 61449b7..8e9230d 100644
--- a/public/dart/fuchsia_inspect/test/vmo/little_big_slab_test.dart
+++ b/public/dart/fuchsia_inspect/test/vmo/little_big_slab_test.dart
@@ -17,12 +17,6 @@
// root-node block, and root-node's name.
//
// A 128-byte heap holds indexes 0..7 (at 16 bytes per index).
-// Since allocated blocks are 32 bytes, the first allocated block will be at
-// index 4, and the second will be at index 6.
-//
-// Two allocated blocks should be enough to test the data structure
-// algorithms, so the heap will be conveniently small at 128 bytes, and
-// we'll expect to see 4 and 6 as valid allocated indexes.
const int _heapSizeBytes = 128;
void main() {
@@ -33,7 +27,7 @@
var f = hexChar(BlockType.free.value);
compare(vmo, 0x00, '0 0 000000 00000000 00000000 00000000');
compare(vmo, 0x10, '0 0 000000 00000000 00000000 00000000');
- compare(vmo, 0x20, '0 0 000000 00000000 00000000 00000000');
+ compare(vmo, 0x20, '$f 1 000000 00000000 00000000 00000000');
compare(vmo, 0x30, '0 0 000000 00000000 00000000 00000000');
compare(vmo, 0x40, '$f 1 0_0000 00000000 00000000 00000000');
compare(vmo, 0x50, '0 0 000000 00000000 00000000 00000000');
@@ -42,13 +36,13 @@
});
test('allocate changes VMO contents correctly', () {
- const List<int> _allocatedIndexes = [4, 6];
+ const List<int> _allocatedIndexes = [2, 4, 6];
var vmo = FakeVmoHolder(_heapSizeBytes);
var heap = LittleBigSlab(vmo, smallOrder: 1, bigOrder: 3);
var blocks =
_allocateEverything(heap, allocatedIndexes: _allocatedIndexes);
- expect(blocks, hasLength(2));
+ expect(blocks, hasLength(3));
var r = hexChar(BlockType.reserved.value);
compare(vmo, 0x40, '$r 1 0_0000 00000000 00000000 00000000');
compare(vmo, 0x50, '0 0 000000 00000000 00000000 00000000');
@@ -57,7 +51,7 @@
});
test('free and re-allocate work correctly', () {
- const List<int> _allocatedIndexes = [4, 6];
+ const List<int> _allocatedIndexes = [2, 4, 6];
var vmo = FakeVmoHolder(_heapSizeBytes);
var heap = LittleBigSlab(vmo, smallOrder: 1, bigOrder: 5);
@@ -70,9 +64,12 @@
_allocateEverything(heap, allocatedIndexes: _allocatedIndexes);
expect(lastBlock, hasLength(1));
// Free in reverse order to mix up the list
- heap..freeBlock(blocks.removeLast())..freeBlock(lastBlock.removeLast());
+ heap
+ ..freeBlock(blocks.removeLast())
+ ..freeBlock(blocks.removeLast())
+ ..freeBlock(lastBlock.removeLast());
blocks = _allocateEverything(heap, allocatedIndexes: _allocatedIndexes);
- // Should get two blocks again
+ // Should get three blocks again
expect(blocks, hasLength(_allocatedIndexes.length));
// At this point, it is not possible to allocate a continuous big block
@@ -81,13 +78,13 @@
});
group('Tests specific to the little big slab allocator:', () {
test('Allocate a big slab', () {
- const List<int> _allocatedIndexes = [4, 6];
+ const List<int> _allocatedIndexes = [2, 4, 6];
var vmo = FakeVmoHolder(_heapSizeBytes);
var heap = LittleBigSlab(vmo, smallOrder: 1, bigOrder: 2);
var blocks = _allocateEverything(heap,
sizeHint: 128, allocatedIndexes: _allocatedIndexes);
- expect(blocks, hasLength(1));
+ expect(blocks, hasLength(2));
var r = hexChar(BlockType.reserved.value);
compare(vmo, 0x40, '$r 2 0_0000 00000000 00000000 00000000');
compare(vmo, 0x50, '0 0 000000 00000000 00000000 00000000');
@@ -98,7 +95,7 @@
// Allocates the entire heap in small blocks. This exercises block splits,
// as well as heap grow.
test('Allocate and grow heap', () {
- const List<int> _allocatedIndexes = [4, 6, 8, 10, 12, 14];
+ const List<int> _allocatedIndexes = [2, 4, 6, 8, 10, 12, 14];
const int heapSizeBytes = 256;
var vmo = FakeVmoHolder(heapSizeBytes);
@@ -109,6 +106,8 @@
sizeHint: 16, allocatedIndexes: _allocatedIndexes);
expect(blocks, hasLength(_allocatedIndexes.length));
var r = hexChar(BlockType.reserved.value);
+ compare(vmo, 0x20, '$r 1 0_0000 00000000 00000000 00000000');
+ compare(vmo, 0x30, '0 0 000000 00000000 00000000 00000000');
compare(vmo, 0x40, '$r 1 0_0000 00000000 00000000 00000000');
compare(vmo, 0x50, '0 0 000000 00000000 00000000 00000000');
compare(vmo, 0x60, '$r 1 0_0000 00000000 00000000 00000000');
@@ -124,7 +123,7 @@
});
test('free and re-allocate work correctly', () {
- List<int> _allocatedIndexes = [4];
+ List<int> _allocatedIndexes = [2, 4];
var vmo = FakeVmoHolder(_heapSizeBytes);
var heap = LittleBigSlab(vmo, smallOrder: 1, bigOrder: 2);
@@ -132,17 +131,20 @@
sizeHint: 128, allocatedIndexes: _allocatedIndexes);
expect(blocks, hasLength(_allocatedIndexes.length));
- // Frees the only block, now the heap is all free.
- heap.freeBlock(blocks.removeLast());
+ // Frees the only blocks, now the heap is all free.
+ heap..freeBlock(blocks.removeLast())..freeBlock(blocks.removeLast());
// Allocate a smaller block now: it will convert the one big block into
// two smaller ones.
- _allocatedIndexes = [4, 6];
+ _allocatedIndexes = [2, 4, 6];
blocks = _allocateEverything(heap, allocatedIndexes: _allocatedIndexes);
expect(blocks, hasLength(_allocatedIndexes.length));
// Free in reverse order to mix up the list
- heap..freeBlock(blocks.removeLast())..freeBlock(blocks.removeLast());
- // Should get two blocks again
+ heap
+ ..freeBlock(blocks.removeLast())
+ ..freeBlock(blocks.removeLast())
+ ..freeBlock(blocks.removeLast());
+ // Should get three blocks again
blocks = _allocateEverything(heap, allocatedIndexes: _allocatedIndexes);
expect(blocks, hasLength(_allocatedIndexes.length));
});
@@ -159,7 +161,7 @@
}
// Make sure we're actually getting unique blocks
expect(Set.of(blocks.map((block) => block.index)), hasLength(blocks.length));
- // With a heapSize-byte VMO, valid indexes are only 4 and 6 (see comment above).
+ // With a heapSize-byte VMO, valid indexes are only 2, 4, and 6.
for (var block in blocks) {
expect(block.index, isIn(allocatedIndexes));
}
diff --git a/public/dart/fuchsia_inspect/test/vmo/vmo_writer_test.dart b/public/dart/fuchsia_inspect/test/vmo/vmo_writer_test.dart
index 7ab3f71..c348eb4 100644
--- a/public/dart/fuchsia_inspect/test/vmo/vmo_writer_test.dart
+++ b/public/dart/fuchsia_inspect/test/vmo/vmo_writer_test.dart
@@ -33,15 +33,9 @@
createWriter(vmo);
final f = hexChar(BlockType.free.value);
final h = hexChar(BlockType.header.value);
- final n = hexChar(BlockType.nodeValue.value);
- final u = hexChar(BlockType.nameUtf8.value);
- String byte(char) => ascii(char).toRadixString(16).padLeft(2, '0');
- final r = byte('r');
- final t = byte('t');
- final o = byte('o');
compare(vmo, 0x00, '$h 0 000000 494E5350 00000000 00000000');
- compare(vmo, 0x10, '$n 0 000000 20000000 00000000 00000000');
- compare(vmo, 0x20, '$u 1 040000 00000000 $r$o$o$t 00000000');
+ compare(vmo, 0x10, '0 0 000000 00000000 00000000 00000000');
+ compare(vmo, 0x20, '$f 1 0_0000 00000000 00000000 00000000');
compare(vmo, 0x30, '0 0 000000 00000000 00000000 00000000');
compare(vmo, 0x40, '$f 2 0_0000 00000000 00000000 00000000');
compare(vmo, 0x50, '0 0 000000 00000000 00000000 00000000');
@@ -49,8 +43,11 @@
compare(vmo, 0x70, '0 0 000000 00000000 00000000 00000000');
compare(vmo, 0x80, '$f 2 0_0000 00000000 00000000 00000000');
compare(vmo, 0x90, '0 0 000000 00000000 00000000 00000000');
+ compare(vmo, 0xa0, '0 0 000000 00000000 00000000 00000000');
+ compare(vmo, 0xb0, '0 0 000000 00000000 00000000 00000000');
+ compare(vmo, 0xc0, '$f 2 0_0000 00000000 00000000 00000000');
// Number of free blocks has been verified manually here.
- expect(countFreeBlocks(vmo), 3, reason: dumpBlocks(vmo));
+ expect(countFreeBlocks(vmo), 5, reason: dumpBlocks(vmo));
});
test('failed createNode leaves VMO sequence number even (valid VMO)', () {
@@ -85,14 +82,10 @@
final writer = createWriter(vmo);
final checker = Checker(vmo)..check(0, []);
final child = writer.createNode(writer.rootNode, 'child');
- checker.check(1, [
- Test(_nameFor(vmo, child), toByteData('child')),
- Test(writer.rootNode, 1)
- ]);
+ checker.check(2, [Test(_nameFor(vmo, child), toByteData('child'))]);
writer.deleteEntity(child);
// Deleting a node without children should free it and its name.
- // root node should have 0 children.
- checker.check(-2, [Test(writer.rootNode, 0)]);
+ checker.check(-2, []);
});
test('make, modify, and free IntMetric', () {
@@ -100,10 +93,9 @@
final writer = createWriter(vmo);
final checker = Checker(vmo)..check(0, []);
final intMetric = writer.createMetric(writer.rootNode, 'intMetric', 1);
- checker.check(1, [
+ checker.check(2, [
Test(_nameFor(vmo, intMetric), toByteData('intMetric')),
- Test(intMetric, 1, reason: 'int value wrong'),
- Test(writer.rootNode, 1, reason: 'childCount wrong')
+ Test(intMetric, 1, reason: 'int value wrong')
]);
writer.addMetric(intMetric, 2);
checker.check(0, [Test(intMetric, 3)]);
@@ -112,7 +104,7 @@
writer.setMetric(intMetric, 2);
checker.check(0, [Test(intMetric, 2)]);
writer.deleteEntity(intMetric);
- checker.check(-2, [Test(writer.rootNode, 0)]);
+ checker.check(-2, []);
});
test('make, modify, and free DoubleMetric', () {
@@ -121,10 +113,9 @@
final checker = Checker(vmo)..check(0, []);
final doubleMetric =
writer.createMetric(writer.rootNode, 'doubleMetric', 1.5);
- checker.check(1, [
+ checker.check(2, [
Test(_nameFor(vmo, doubleMetric), toByteData('doubleMetric')),
- Test(doubleMetric, 1.5, reason: 'double value wrong'),
- Test(writer.rootNode, 1, reason: 'childCount wrong')
+ Test(doubleMetric, 1.5, reason: 'double value wrong')
]);
writer.addMetric(doubleMetric, 2.0);
checker.check(0, [Test(doubleMetric, 3.5)]);
@@ -133,7 +124,7 @@
writer.setMetric(doubleMetric, 1.5);
checker.check(0, [Test(doubleMetric, 1.5)]);
writer.deleteEntity(doubleMetric);
- checker.check(-2, [Test(writer.rootNode, 0)]);
+ checker.check(-2, []);
});
test('make, modify, and free Property', () {
@@ -142,17 +133,14 @@
final checker = Checker(vmo)..check(0, []);
final property = writer.createProperty(writer.rootNode, 'prop');
- checker.check(1, [
- Test(_nameFor(vmo, property), toByteData('prop')),
- Test(writer.rootNode, 1)
- ]);
+ checker.check(2, [Test(_nameFor(vmo, property), toByteData('prop'))]);
final bytes = ByteData(8)..setFloat64(0, 1.23);
writer.setProperty(property, bytes);
- checker.check(1, [Test(_extentFor(vmo, property), bytes)]);
+ // Same number of free blocks, since a large one is split.
+ checker.check(0, [Test(_extentFor(vmo, property), bytes)]);
writer.deleteEntity(property);
- // Property, its extent, and its name should be freed. Its parent should
- // have one fewer children (0 in this case).
- checker.check(-3, [Test(writer.rootNode, 0)]);
+ // Property, its extent, and its name should be freed.
+ checker.check(-3, []);
});
test('Node delete permutations', () {
@@ -160,16 +148,16 @@
final writer = createWriter(vmo);
final checker = Checker(vmo)..check(0, []);
final parent = writer.createNode(writer.rootNode, 'parent');
- checker.check(1, [Test(writer.rootNode, 1)]);
+ checker.check(2, []);
final child = writer.createNode(parent, 'child');
- checker.check(2, [Test(writer.rootNode, 1), Test(parent, 1)]);
+ checker.check(1, [Test(parent, 1)]);
final metric = writer.createMetric(child, 'metric', 1);
- checker.check(1, [Test(child, 1), Test(parent, 1)]);
+ checker.check(2, [Test(child, 1), Test(parent, 1)]);
writer.deleteEntity(child);
// Now child should be a tombstone; only its name should be freed.
checker.check(-1, [Test(child, 1), Test(parent, 0)]);
writer.deleteEntity(parent);
- checker.check(-2, [Test(writer.rootNode, 0)]);
+ checker.check(-2, []);
writer.deleteEntity(metric);
// Metric, its name, and child should be freed.
checker.check(-3, []);
@@ -179,7 +167,6 @@
checker.check(2, [
Test(_nameFor(vmo, newMetric), toByteData('newIntMetric')),
Test(newMetric, 42),
- Test(writer.rootNode, 1)
]);
});
@@ -273,7 +260,7 @@
// Note that the node and property names are truncated.
final node = writer.createNode(writer.rootNode,
'N012345678901234567890123456789012345678901234567890123456789000');
- checker.check(1, [
+ checker.check(2, [
Test(
_nameFor(vmo, node),
toByteData(
@@ -282,7 +269,7 @@
final property = writer.createProperty(node,
'PP012345678901234567890123456789012345678901234567890123456789000');
- checker.check(2, [
+ checker.check(1, [
Test(
_nameFor(vmo, property),
toByteData(
@@ -302,21 +289,15 @@
createWriter(vmo);
final f = hexChar(BlockType.free.value);
final h = hexChar(BlockType.header.value);
- final n = hexChar(BlockType.nodeValue.value);
- final u = hexChar(BlockType.nameUtf8.value);
- String byte(char) => ascii(char).toRadixString(16).padLeft(2, '0');
- final r = byte('r');
- final t = byte('t');
- final o = byte('o');
compare(vmo, 0x00, '$h 0 000000 494E5350 00000000 00000000');
- compare(vmo, 0x10, '$n 0 000000 20000000 00000000 00000000');
- compare(vmo, 0x20, '$u 1 040000 00000000 $r$o$o$t 00000000');
+ compare(vmo, 0x10, '0 0 000000 00000000 00000000 00000000');
+ compare(vmo, 0x20, '$f 1 0_0000 00000000 00000000 00000000');
compare(vmo, 0x30, '0 0 000000 00000000 00000000 00000000');
compare(vmo, 0x40, '$f 1 0_0000 00000000 00000000 00000000');
compare(vmo, 0x50, '0 0 000000 00000000 00000000 00000000');
compare(vmo, 0x60, '$f 1 0_0000 00000000 00000000 00000000');
compare(vmo, 0x70, '0 0 000000 00000000 00000000 00000000');
- expect(countFreeBlocks(vmo), 6, reason: dumpBlocks(vmo));
+ expect(countFreeBlocks(vmo), 8, reason: dumpBlocks(vmo));
});
test('failed createNode leaves VMO sequence number even (valid VMO)', () {
@@ -351,14 +332,11 @@
final writer = createWriter(vmo);
final checker = Checker(vmo)..check(0, []);
final child = writer.createNode(writer.rootNode, 'child');
- checker.check(2, [
- Test(_nameFor(vmo, child), toByteData('child')),
- Test(writer.rootNode, 1)
- ]);
+ checker.check(2, [Test(_nameFor(vmo, child), toByteData('child'))]);
writer.deleteEntity(child);
// Deleting a node without children should free it and its name.
// root node should have 0 children.
- checker.check(-2, [Test(writer.rootNode, 0)]);
+ checker.check(-2, []);
});
test('make, modify, and free IntMetric', () {
@@ -368,8 +346,7 @@
final intMetric = writer.createMetric(writer.rootNode, 'intMetric', 1);
checker.check(2, [
Test(_nameFor(vmo, intMetric), toByteData('intMetric')),
- Test(intMetric, 1, reason: 'int value wrong'),
- Test(writer.rootNode, 1, reason: 'childCount wrong')
+ Test(intMetric, 1, reason: 'int value wrong')
]);
writer.addMetric(intMetric, 2);
checker.check(0, [Test(intMetric, 3)]);
@@ -378,7 +355,7 @@
writer.setMetric(intMetric, 2);
checker.check(0, [Test(intMetric, 2)]);
writer.deleteEntity(intMetric);
- checker.check(-2, [Test(writer.rootNode, 0)]);
+ checker.check(-2, []);
});
test('make, modify, and free DoubleMetric', () {
@@ -389,8 +366,7 @@
writer.createMetric(writer.rootNode, 'doubleMetric', 1.5);
checker.check(2, [
Test(_nameFor(vmo, doubleMetric), toByteData('doubleMetric')),
- Test(doubleMetric, 1.5, reason: 'double value wrong'),
- Test(writer.rootNode, 1, reason: 'childCount wrong')
+ Test(doubleMetric, 1.5, reason: 'double value wrong')
]);
writer.addMetric(doubleMetric, 2.0);
checker.check(0, [Test(doubleMetric, 3.5)]);
@@ -399,7 +375,7 @@
writer.setMetric(doubleMetric, 1.5);
checker.check(0, [Test(doubleMetric, 1.5)]);
writer.deleteEntity(doubleMetric);
- checker.check(-2, [Test(writer.rootNode, 0)]);
+ checker.check(-2, []);
});
test('make, modify, and free Property', () {
@@ -408,17 +384,14 @@
final checker = Checker(vmo)..check(0, []);
final property = writer.createProperty(writer.rootNode, 'prop');
- checker.check(2, [
- Test(_nameFor(vmo, property), toByteData('prop')),
- Test(writer.rootNode, 1)
- ]);
+ checker.check(2, [Test(_nameFor(vmo, property), toByteData('prop'))]);
final bytes = ByteData(8)..setFloat64(0, 1.23);
writer.setProperty(property, bytes);
checker.check(1, [Test(_extentFor(vmo, property), bytes)]);
writer.deleteEntity(property);
// Property, its extent, and its name should be freed. Its parent should
// have one fewer children (0 in this case).
- checker.check(-3, [Test(writer.rootNode, 0)]);
+ checker.check(-3, []);
});
test('Node delete permutations', () {
@@ -426,9 +399,9 @@
final writer = createWriter(vmo);
final checker = Checker(vmo)..check(0, []);
final parent = writer.createNode(writer.rootNode, 'parent');
- checker.check(2, [Test(writer.rootNode, 1)]);
+ checker.check(2, []);
final child = writer.createNode(parent, 'child');
- checker.check(2, [Test(writer.rootNode, 1), Test(parent, 1)]);
+ checker.check(2, [Test(parent, 1)]);
final metric = writer.createMetric(child, 'metric', 1);
checker.check(2, [Test(child, 1), Test(parent, 1)]);
writer.deleteEntity(child);
@@ -436,7 +409,7 @@
checker.check(-1, [Test(child, 1), Test(parent, 0)]);
writer.deleteEntity(parent);
// Parent, plus its name, should be freed; root should have no children.
- checker.check(-2, [Test(writer.rootNode, 0)]);
+ checker.check(-2, []);
writer.deleteEntity(metric);
// Metric, its name, and child should be freed.
checker.check(-3, []);
@@ -445,8 +418,7 @@
writer.createMetric(writer.rootNode, 'newIntMetric', 42);
checker.check(2, [
Test(_nameFor(vmo, newMetric), toByteData('newIntMetric')),
- Test(newMetric, 42),
- Test(writer.rootNode, 1)
+ Test(newMetric, 42)
]);
});