I managed to test forks by creating 3 reg test nodes. One node is used to interface with my software, and two other nodes are used to hold competing blockchains. The regtest mode starts each node with no connections to begin with, so they are completely isolated. I can use “sendrawtransaction” and “setgenerate” on these isolated nodes to create competing chains. However, the nodes need to sync to test fork scenarios.
It turned out to be easy to synchronise nodes. I sync the competing nodes with the interface node with help of the RPC command “disconnectpeer” which you can find here. My synchronisation code is as follows in pseudocode:
function sync (node1, node2)
if node2.height < node1.height then
sync(node2, node1)
return
node1.rpc("addnode", "localhost:" + node2.port, "onetry")
wait while node1.rpc("get_info")["blocks"] is not node1.height
node1.height = node2.height
node1.rpc("disconnectpeer", node1.rpc("getpeerinfo")[0]["id"])
After the function is complete the nodes will remain isolated once again so that you can work on creating new competing chains.