@Test
	public void testMergeFunctionWithForcedIndirectParameter() throws Exception {

		mtf.initialize("DiffTestPgm1_X86_64", new ProgramModifierListener() {

			// should apply diff on parameter data type.

			@Override
			public void modifyLatest(ProgramDB program) {
				try {
					Function func = getFunction(program, "0x1000");
					Parameter parameter1 =
						new ParameterImpl("stuff", new ByteDataType(), 4, program);
					func.addParameter(parameter1, SourceType.USER_DEFINED);
				}
				catch (Exception e) {
					e.printStackTrace();
					Assert.fail(e.getMessage());
				}
				Function func = getFunction(program, "0x1000");
				assertEquals("void bob(byte stuff)", func.getPrototypeString(true, false));
			}

			@Override
			public void modifyPrivate(ProgramDB program) {
				// Forced indirect for the return.
				try {
					Structure struct = new StructureDataType("struct", 20);
					Function func = getFunction(program, "0x1000");
					Parameter parameter1 = new ParameterImpl("stuff", struct, 4, program);
					func.addParameter(parameter1, SourceType.USER_DEFINED);
				}
				catch (Exception e) {
					e.printStackTrace();
					Assert.fail(e.getMessage());
				}
				Function func = getFunction(program, "0x1000");
				assertEquals("void bob(struct stuff)", func.getPrototypeString(true, false));
				Parameter parameter = func.getParameter(0);
				assertEquals("[struct * stuff@RCX:8 (ptr)]", parameter.toString());
			}
		});

		p1 = mtf.getResultProgram();
		p2 = mtf.getPrivateProgram();

		int txId = p1.startTransaction("Merge into Program 1");
		boolean commit = false;
		try {
			AddressSet setToDiff = new AddressSet();
			setToDiff.addRange(addr(p1, "0x1000"), addr(p1, "0x1000"));
			programMerge = new ProgramMergeManager(p1, p2, setToDiff);

			programMerge.setDiffFilter(new ProgramDiffFilter(ProgramDiffFilter.FUNCTION_DIFFS));
			programMerge.setMergeFilter(
				new ProgramMergeFilter(ProgramMergeFilter.FUNCTIONS, ProgramMergeFilter.MERGE));
			AddressSet expectedDiffsBefore = new AddressSet();
			expectedDiffsBefore.addRange(addr(p1, "0x1000"), addr(p1, "0x1000"));
			assertEquals(expectedDiffsBefore, programMerge.getFilteredDifferences());

			AddressSet mergeSet = new AddressSet();
			mergeSet.addRange(addr(p1, "0x1000"), addr(p1, "0x1000"));
			programMerge.merge(mergeSet, TaskMonitor.DUMMY);

			AddressSet expectedDiffsAfter = new AddressSet();
			assertEquals(expectedDiffsAfter, programMerge.getFilteredDifferences());

			SymbolTable st = p1.getSymbolTable();
			Symbol[] syms;
			syms = st.getSymbols(addr(p1, "0x1000"));
			assertEquals(1, syms.length);
			assertEquals("bob", syms[0].getName());
			assertEquals(p1.getGlobalNamespace(), syms[0].getParentNamespace());

			Function func = getFunction(p1, "0x1000");
			assertEquals("void bob(struct stuff)", func.getPrototypeString(true, false));
			Parameter parameter = func.getParameter(0);
			assertEquals("[struct * stuff@RCX:8 (ptr)]", parameter.toString());
			commit = true;
		}
		finally {
			p1.endTransaction(txId, commit);
		}
	}
<CODE>ProgramMerge2Test</CODE> tests the <CODE>ProgramMerge</CODE> class
to verify it correctly merges various types of program differences.
The tests modify copies of the same program to cause differences
between these two programs, which can then be merged.
Ghidra/Features/Base/src/test.slow/java/ghidra/program/util/ProgramMerge2Test.java