@Test
	public void testObjectDelete() throws Exception {
		populateModel(3);

		// Delete a leaf
		TraceObject t1 = targets.get(1);
		assertFalse(t1.isDeleted());
		assertEquals(3, targetContainer.getValues(Lifespan.ALL).size());
		assertEquals(t1, Unique.assertOne(
			manager.getObjectsByPath(Lifespan.ALL, KeyPath.parse("Targets[1]"))));
		assertEquals(t1, t1.getAttribute(1, "self").getValue());
		assertEquals(t1, root.getValue(1, "curTarget").getValue());

		try (Transaction tx = b.startTransaction()) {
			t1.delete();
		}

		assertTrue(t1.isDeleted());
		assertTrue(t1.getParents(Lifespan.ALL).isEmpty());
		assertEquals(2, targetContainer.getValues(Lifespan.ALL).size());
		assertEquals(0,
			manager.getObjectsByPath(Lifespan.ALL, KeyPath.parse("Targets[1]")).count());
		assertNull(t1.getAttribute(2, "self"));
		assertNull(root.getValue(1, "curTarget"));

		// Delete a branch (leaves stay, but detached)
		TraceObject t0 = targets.get(0);
		assertEquals(2,
			manager.getObjectsByPath(Lifespan.ALL, KeyPath.parse("Targets[]")).count());
		assertTrue(
			t0.getParents(Lifespan.ALL).stream().anyMatch(v -> v.getParent() == targetContainer));
		assertEquals(2, targetContainer.getValues(Lifespan.ALL).size());

		b.trace.undo();
		b.trace.redo();

		assertEquals(2, targetContainer.getValues(Lifespan.ALL).size());

		try (Transaction tx = b.startTransaction()) {
			targetContainer.delete();
		}

		assertEquals(0,
			manager.getObjectsByPath(Lifespan.ALL, KeyPath.parse("Targets[]")).count());
		assertFalse(t0.isDeleted());
		assertFalse(
			t0.getParents(Lifespan.ALL).stream().anyMatch(v -> v.getParent() == targetContainer));
		// A little odd, but allows branch to be replaced and successors restored later
		assertEquals(t0, root.getValue(0, "curTarget").getValue());
	}
Fails because you cannot create a second root object.
Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/target/DBTraceObjectManagerTest.java