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

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

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

		addTextMapping(target1, text, program);

		addProgramBreakpoints(program);
		addTargetSoftwareBreakpoint(target1, text);
		addTargetSoftwareBreakpoint(target1, text);
		waitOn(mappingService.changesSettled());
		waitOn(breakpointService.changesSettled());

		assertEquals(2, breakpointService.getAllBreakpoints().size());

		LogicalBreakpoint lb = Unique.assertOne(
			breakpointService.getBreakpointsAt(program, addr(program, 0x00400123)));
		assertEquals(program, lb.getProgram());
		assertEquals(Set.of(trace), lb.getMappedTraces());

		assertEquals(2, lb.getTraceBreakpoints().size());

		Set<TraceBreakpoint> locs = lb.getTraceBreakpoints();

		long snap = getSnap(target1);
		TraceBreakpoint bpt0 = findLoc(snap, locs, 0);
		TraceBreakpoint bpt1 = findLoc(snap, locs, 1);
		CompletableFuture<Void> disable = breakpointService.disableLocs(Set.of(bpt0));
		handleToggleBreakpointInvocation(target1, bpt0, false);
		waitOn(disable);
		waitForDomainObject(trace);
		waitOn(breakpointService.changesSettled());

		assertEquals(State.INCONSISTENT_ENABLED, lb.computeState());
		assertEquals(State.INCONSISTENT_MIXED, lb.computeStateForTrace(trace));
		assertEquals(State.INCONSISTENT_DISABLED, lb.computeStateForLocation(bpt0));
		assertEquals(State.ENABLED, lb.computeStateForLocation(bpt1));
	}
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