@Test
	public void testChangeLatestFunction() throws Exception {

		mtf.initialize("NotepadMergeListingTest_X86", new OriginalProgramModifierListener() {

			@Override
			public void modifyOriginal(ProgramDB program) {
				try {
					Function applesFunction =
						createExternalFunction(program, new String[] { "user32.dll", "apples" });
					addStackParameter(applesFunction, "P1", SourceType.USER_DEFINED,
						new DWordDataType(), 4, "Test Parameter Comment");
					addStackParameter(applesFunction, "P2", SourceType.USER_DEFINED,
						new DWordDataType(), 8, "Test Parameter Comment");
				}
				catch (Exception e) {
					Assert.fail(e.getMessage());
				}

				// Check the function just created.
				Function function =
					getExternalFunction(program, new String[] { "user32.dll", "apples" });
				assertEquals("apples", function.getName());
				assertEquals(SourceType.USER_DEFINED, function.getSymbol().getSource());
				checkDataType(DataType.DEFAULT, function.getReturnType());
				assertEquals(SourceType.DEFAULT, function.getReturn().getSource());
				assertEquals("unknown", function.getCallingConventionName());
				assertEquals(new AddressSet(), function.getBody());
				assertEquals(null, function.getComment());
				assertEquals(null, function.getRepeatableComment());
				assertEquals(false, function.hasCustomVariableStorage());
				assertEquals(SourceType.USER_DEFINED, function.getSignatureSource());
				assertEquals(false, function.hasVarArgs());
				assertEquals(true, function.isExternal());
				assertEquals(false, function.isInline());
				assertEquals(false, function.isThunk());
				assertEquals(SourceType.USER_DEFINED, function.getSignatureSource());
				assertEquals(2, function.getParameterCount());

				Parameter parameter1 = function.getParameter(0);
				assertEquals("P1", parameter1.getName());
				checkDataType(new DWordDataType(), parameter1.getDataType());
				assertEquals("Test Parameter Comment", parameter1.getComment());
				assertEquals(SourceType.USER_DEFINED, parameter1.getSource());
				assertEquals(4, parameter1.getLength());
				assertEquals(4, parameter1.getStackOffset());
				assertEquals(null, parameter1.getRegister());

				Parameter parameter2 = function.getParameter(1);
				assertEquals("P2", parameter2.getName());
				checkDataType(new DWordDataType(), parameter2.getDataType());
				assertEquals("Test Parameter Comment", parameter2.getComment());
				assertEquals(SourceType.USER_DEFINED, parameter2.getSource());
				assertEquals(4, parameter2.getLength());
				assertEquals(8, parameter2.getStackOffset());
				assertEquals(null, parameter2.getRegister());
			}

			@Override
			public void modifyLatest(ProgramDB program) {
				try {
					Function function =
						getExternalFunction(program, new String[] { "user32.dll", "apples" });

					function.setName("FRED", SourceType.USER_DEFINED);
					function.setReturnType(new FloatDataType(), SourceType.ANALYSIS);
//					function.setCallingConvention();
//					function.setBody();
//					function.setComment();
					function.setCustomVariableStorage(true);
//					function.setRepeatableComment();
//					function.setSignatureSource();
					function.setVarArgs(true);

					Parameter parameter1 = function.getParameter(0);
					parameter1.setComment("New Parameter1 Comment");
					parameter1.setName("Amount", SourceType.ANALYSIS);
					parameter1.setDataType(new FloatDataType(), SourceType.IMPORTED);

					Parameter parameter2 = function.getParameter(1);
					parameter2.setComment("New P2 Comment");
					parameter2.setDataType(new ByteDataType(), SourceType.ANALYSIS);
					parameter2.setName("Value", SourceType.IMPORTED);

					addStackParameter(function, "P3", SourceType.IMPORTED,
						new PointerDataType(new CharDataType()), 12, "Test Parameter3 Comment");
				}
				catch (Exception e) {
					Assert.fail(e.getMessage());
				}

				// Check the function just changed.
				Function applesFunction =
					getExternalFunction(program, new String[] { "user32.dll", "apples" });
				assertNull(applesFunction);
				Function function =
					getExternalFunction(program, new String[] { "user32.dll", "FRED" });
				assertEquals("FRED", function.getName());
				assertEquals(SourceType.USER_DEFINED, function.getSymbol().getSource());
				checkDataType(new FloatDataType(), function.getReturnType());
				assertEquals(SourceType.USER_DEFINED, function.getReturn().getSource());
				assertEquals("unknown", function.getCallingConventionName());
				assertEquals(new AddressSet(), function.getBody());
				assertEquals(null, function.getComment());
				assertEquals(null, function.getRepeatableComment());
				assertEquals(true, function.hasCustomVariableStorage());
				assertEquals(SourceType.USER_DEFINED, function.getSignatureSource());
				assertEquals(true, function.hasVarArgs());
				assertEquals(true, function.isExternal());
				assertEquals(false, function.isInline());
				assertEquals(false, function.isThunk());
				assertEquals(SourceType.USER_DEFINED, function.getSignatureSource());
				assertEquals(3, function.getParameterCount());

				Parameter parameter1 = function.getParameter(0);
				assertEquals("Amount", parameter1.getName());
				checkDataType(new FloatDataType(), parameter1.getDataType());
				assertEquals("New Parameter1 Comment", parameter1.getComment());
				assertEquals(SourceType.ANALYSIS, parameter1.getSource());
				assertEquals(4, parameter1.getLength());
				assertEquals(4, parameter1.getStackOffset());
				assertEquals(null, parameter1.getRegister());

				Parameter parameter2 = function.getParameter(1);
				assertEquals("Value", parameter2.getName());
				checkDataType(new ByteDataType(), parameter2.getDataType());
				assertEquals("New P2 Comment", parameter2.getComment());
				assertEquals(SourceType.IMPORTED, parameter2.getSource());
				assertEquals(1, parameter2.getLength());
				assertEquals(8, parameter2.getStackOffset());
				assertEquals(null, parameter2.getRegister());

				Parameter parameter3 = function.getParameter(2);
				assertEquals("P3", parameter3.getName());
				checkDataType(new PointerDataType(new CharDataType()), parameter3.getDataType());
				assertEquals("Test Parameter3 Comment", parameter3.getComment());
				assertEquals(SourceType.IMPORTED, parameter3.getSource());
				assertEquals(4, parameter3.getLength());
				assertEquals(12, parameter3.getStackOffset());
				assertEquals(null, parameter3.getRegister());
			}

			@Override
			public void modifyPrivate(ProgramDB program) {
				// No Changes
			}
		});

		executeMerge(ASK_USER);
		waitForMergeCompletion();

		assertNull(getExternalFunction(resultProgram, new String[] { "user32.dll", "apples" }));
		Function function =
			getExternalFunction(resultProgram, new String[] { "user32.dll", "FRED" });
		assertNotNull(function);
		assertEquals("FRED", function.getName());
		assertEquals(SourceType.USER_DEFINED, function.getSymbol().getSource());
		checkDataType(new FloatDataType(), function.getReturnType());
		assertEquals(SourceType.USER_DEFINED, function.getReturn().getSource());
		assertEquals("unknown", function.getCallingConventionName());
		assertEquals(new AddressSet(), function.getBody());
		assertEquals(null, function.getComment());
		assertEquals(null, function.getRepeatableComment());
		assertEquals(true, function.hasCustomVariableStorage());
		assertEquals(SourceType.USER_DEFINED, function.getSignatureSource());
		assertEquals(true, function.hasVarArgs());
		assertEquals(true, function.isExternal());
		assertEquals(false, function.isInline());
		assertEquals(false, function.isThunk());
		assertEquals(SourceType.USER_DEFINED, function.getSignatureSource());
		assertEquals(3, function.getParameterCount());

		Parameter parameter1 = function.getParameter(0);
		assertEquals("Amount", parameter1.getName());
		checkDataType(new FloatDataType(), parameter1.getDataType());
		assertEquals("New Parameter1 Comment", parameter1.getComment());
//		assertEquals(SourceType.ANALYSIS, parameter1.getSource());
		assertEquals(4, parameter1.getLength());
		assertEquals(4, parameter1.getStackOffset());
		assertEquals(null, parameter1.getRegister());

		Parameter parameter2 = function.getParameter(1);
		assertEquals("Value", parameter2.getName());
		checkDataType(new ByteDataType(), parameter2.getDataType());
		assertEquals("New P2 Comment", parameter2.getComment());
//		assertEquals(SourceType.IMPORTED, parameter2.getSource());
		assertEquals(1, parameter2.getLength());
		assertEquals(8, parameter2.getStackOffset());
		assertEquals(null, parameter2.getRegister());

		Parameter parameter3 = function.getParameter(2);
		assertEquals("P3", parameter3.getName());
		checkDataType(new PointerDataType(new CharDataType()), parameter3.getDataType());
		assertEquals("Test Parameter3 Comment", parameter3.getComment());
//		assertEquals(SourceType.IMPORTED, parameter3.getSource());
		assertEquals(4, parameter3.getLength());
		assertEquals(12, parameter3.getStackOffset());
		assertEquals(null, parameter3.getRegister());
	}
Test the merge of external function variables.
Ghidra/Features/Base/src/test.slow/java/ghidra/app/merge/listing/ExternalFunctionMergeManagerTest.java