public void testUndoRedoAddBreakpointAndMapping() throws Throwable {
		createTarget1();
		Trace trace = getTrace(target1);
		traceManager.openTrace(trace);

		createProgramFromTrace(trace);
		intoProject(program);
		programManager.openProgram(program);

		addProgramTextBlock(program);
		MR text = addTargetTextRegion(target1);

		try (Transaction tx = trace.openTransaction("Will undo")) {
			addTargetSoftwareBreakpoint(target1, text);
			addTextMapping(target1, text, program);
		}
		waitForDomainObject(program);
		waitOn(mappingService.changesSettled());
		waitOn(breakpointService.changesSettled());

		// Sanity
		assertLogicalBreakpointForMappedSoftwareBreakpoint(trace);

		undo(trace);
		waitOn(mappingService.changesSettled());
		waitOn(breakpointService.changesSettled());

		// NB. The bookmark remains
		LogicalBreakpoint one = Unique.assertOne(breakpointService.getAllBreakpoints());
		assertTrue(one.getTraceBreakpoints().isEmpty());

		redo(trace);
		waitOn(mappingService.changesSettled());
		waitOn(breakpointService.changesSettled());

		// Mapping, breakpoint may be processed in whatever order
		assertLogicalBreakpointForMappedSoftwareBreakpoint(trace);
	}
NB. The target could still be mid transaction. If we open this transaction too soon, then
the breakpoint gets aborted as well.
Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/service/breakpoint/AbstractDebuggerLogicalBreakpointServiceTest.java