@Test
	public void testAddTraceBreakpointSetSleighThenMapThenSaveToProgramCopiesSleigh()
			throws Throwable {
		DebuggerControlService controlService =
			addPlugin(tool, DebuggerControlServicePlugin.class);

		// TODO: What if already mapped?
		// Not sure I care about tb.setEmuSleigh() out of band

		createTrace();
		traceManager.openTrace(tb.trace);
		controlService.setCurrentMode(tb.trace, ControlMode.RW_EMULATOR);
		createProgramFromTrace();
		intoProject(program);
		programManager.openProgram(program);

		try (Transaction tid = tb.startTransaction()) {
			TraceBreakpoint bpt = tb.trace.getBreakpointManager()
					.addBreakpoint("Processes[1].Breakpoints[0]", Lifespan.nowOn(0),
						tb.addr(0x55550123), Set.of(), Set.of(TraceBreakpointKind.SW_EXECUTE),
						false /* emuEnabled defaults to true */, "");
			bpt.setEmuSleigh(0, "r0=0xbeef;");
		}
		waitForDomainObject(tb.trace);
		waitOn(mappingService.changesSettled());
		waitOn(breakpointService.changesSettled());
		LogicalBreakpoint lb = Unique.assertAtMostOne(
			breakpointService.getBreakpointsAt(tb.trace, tb.addr(0x55550123)));

		assertEquals("r0=0xbeef;", lb.getEmuSleigh());

		addTextMappingDead(0, program, tb);
		waitOn(mappingService.changesSettled());
		waitOn(breakpointService.changesSettled());

		lb = Unique
				.assertOne(breakpointService.getBreakpointsAt(program, addr(program, 0x00400123)));
		assertTrue(lb.getMappedTraces().contains(tb.trace));

		lb.enableForProgram();
		waitForDomainObject(tb.trace);
		waitOn(breakpointService.changesSettled());

		assertEquals("{\"sleigh\":\"r0\\u003d0xbeef;\"}", lb.getProgramBookmark().getComment());
	}
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