private BufferMgr init(int bufferCnt, int growCnt) throws Exception {

		BufferMgr bufferMgr = null;
		boolean success = false;
		try {

			LocalBufferFile bf = PrivateDatabase.createDatabase(testDir, new DBFileListener() {
				@Override
				public void versionCreated(Database db, int version) {

				}
			}, BUFFER_SIZE);

			bufferMgr = new BufferMgr(BUFFER_SIZE, 16 * 1024, 4);

			// Add data buffers to original file
			for (int i = 0; i < bufferCnt; i++) {
				DataBuffer buf = bufferMgr.createBuffer();
				buf.putInt(0, -i); // store negative index value
				bufferMgr.releaseBuffer(buf);
			}

			bufferMgr.saveAs(bf, true, TaskMonitor.DUMMY);

			// Grow file if requested
			int modCnt = 0;
			int newBufferCnt = bufferCnt + growCnt;
			for (int i = bufferCnt; i < newBufferCnt; i++) {
				DataBuffer buf = bufferMgr.createBuffer();
				buf.putInt(0, -i); // store negative index value
				bufferMgr.releaseBuffer(buf);
				++modCnt;
			}
			bufferCnt = newBufferCnt;
			System.out.println("Added " + modCnt + " buffers");
			bufferMgr.checkpoint();

			bufferMgr.takeRecoverySnapshot(null, TaskMonitor.DUMMY);

			assertTrue(RecoveryMgr.canRecover(bf));

			// Remove every other buffer (build-up free list)
			modCnt = 0;
			for (int i = 1; i < bufferCnt; i += 2) {
				bufferMgr.deleteBuffer(i);
				++modCnt;
			}
			System.out.println("Deleted " + modCnt + " buffers");

			modCnt = 0;
			for (int i = 0; i < bufferCnt; i += 40) {
				DataBuffer buf = bufferMgr.getBuffer(i);
				buf.putInt(0, i); // store positive index value
				bufferMgr.releaseBuffer(buf);
				++modCnt;
			}
			System.out.println("Modified " + modCnt + " buffers");
			bufferMgr.checkpoint();

			bufferMgr.takeRecoverySnapshot(null, TaskMonitor.DUMMY);

			assertTrue(RecoveryMgr.canRecover(bf));

			modCnt = 0;
			for (int i = 20; i < bufferCnt; i += 40) {
				DataBuffer buf = bufferMgr.getBuffer(i);
				buf.putInt(0, i); // store positive index value
				bufferMgr.releaseBuffer(buf);
				++modCnt;
			}
			System.out.println("Modified " + modCnt + " buffers");
			bufferMgr.checkpoint();

			assertTrue(bufferMgr.takeRecoverySnapshot(null, TaskMonitor.DUMMY));

			assertTrue(RecoveryMgr.canRecover(bf));

			modCnt = 0;
			for (int i = 10; i < bufferCnt; i += 20) {
				DataBuffer buf = bufferMgr.getBuffer(i);
				buf.putInt(0, i); // store positive index value
				bufferMgr.releaseBuffer(buf);
				++modCnt;
			}
			System.out.println("Modified " + modCnt + " buffers");
			bufferMgr.checkpoint();

			assertTrue(bufferMgr.takeRecoverySnapshot(null, TaskMonitor.DUMMY));

			assertTrue(RecoveryMgr.canRecover(bf));

			success = true;
		}
		finally {
			if (!success && bufferMgr != null) {
				bufferMgr.dispose();
			}
		}

		return bufferMgr;
	}
File created:
  bufferCnt buffers are filled with data, -bufferID stored at offset 0

Recovery snapshot taken after each transaction.
Transaction 1:
  growCnt buffers are added with data, -bufferID stored at offset 0
Transaction 2:
  all odd numbered buffers between 1 and bufferCnt-1 are deleted/freed
  +bufferID stored at offset 0 for buffers 0, 40, 80 ... <bufferCnt-1>
Transaction 3:
  +bufferID stored at offset 0 for buffers 20, 60, 100 ... <bufferCnt-1>
Transaction 4:
  +bufferID stored at offset 0 for buffers 10, 30, 50 ... <bufferCnt-1>

@param bufferCnt
@param growCnt
@return
@throws Exception
Ghidra/Framework/FileSystem/src/test.slow/java/db/buffers/RecoveryFileTest.java