@Test
public void testFailureMode_MalformedTransactionNoValidScnsInMiddleOfMiddleFile()
  throws Exception
{

  final Logger log = Logger.getLogger("TestTrailFilePositionSetter.testFailureMode_MalformedTransactionNoValidScns");
  log.info("starting");
  File dir = createTempDir();
  // corrupt both SCNs in each of six transactions:
  HashSet<Long> corruptedScns = new HashSet<Long>(10);
  corruptedScns.add(new Long(100));  // case 1
  corruptedScns.add(new Long(101));  // case 1
  corruptedScns.add(new Long(204));  // case 2
  corruptedScns.add(new Long(205));  // case 2
  corruptedScns.add(new Long(206));  // case 3
  corruptedScns.add(new Long(207));  // case 3
  corruptedScns.add(new Long(250));  // case 4
  corruptedScns.add(new Long(251));  // case 4
  corruptedScns.add(new Long(310));  // case 5
  corruptedScns.add(new Long(311));  // case 5
  corruptedScns.add(new Long(398));  // case 6
  corruptedScns.add(new Long(399));  // case 6
  createTrailFiles(dir.getAbsolutePath(), TRAIL_FILENAME_PREFIX, 150 /* numTxns, 24 lines each */,
                   1250 /* numLinesPerFile */, 1 /* numLinesPerNewline */, "\n", 0,
                   corruptedScns, "blargh", false, "");
  TrailFilePositionSetter posSetter = new TrailFilePositionSetter(dir.getAbsolutePath(), TRAIL_FILENAME_PREFIX);
  GGXMLTrailTransactionFinder finder = new GGXMLTrailTransactionFinder();
  FilePositionResult res;
  // SCN 101 is before the earliest (valid) SCN present, so expect ERROR:
  res = posSetter.locateFilePosition(101, finder);
  Assert.assertEquals(res.getStatus(), FilePositionResult.Status.ERROR,
                      "expected error for exact-match SCN that's 'too old'.");
  // For SCN <= the earliest transactions maxSCN, we throw error
  finder.reset();
  res = posSetter.locateFilePosition(102, finder);
  Assert.assertEquals(res.getStatus(), FilePositionResult.Status.ERROR,
                    "expected error for exact-match SCN that's 'too old'.");
  // expect first non-corrupted SCN here, not first "transaction SCN":
  finder.reset();
  res = posSetter.locateFilePosition(TrailFilePositionSetter.USE_EARLIEST_SCN, finder);
  assertFilePositionResult(res, dir, 102, FilePositionResult.Status.FOUND);
  // 107 = max SCN of its transaction = "transaction SCN" => should get FOUND
  finder.reset();
  res = posSetter.locateFilePosition(107, finder);
  assertFilePositionResult(res, dir, 107, FilePositionResult.Status.FOUND);
  // 203 = last valid SCN in first file = max SCN of its transaction = "transaction SCN"
  // => should be FOUND
  finder.reset();
  res = posSetter.locateFilePosition(203, finder);
  assertFilePositionResult(res, dir, 203, FilePositionResult.Status.FOUND);
  // SCN 204 is invalid and is part of a transaction split across first/second files;
  // 209 = next "transaction SCN" and is near the top of the middle file
  finder.reset();
  res = posSetter.locateFilePosition(204, finder);
  assertFilePositionResult(res, dir, 209, FilePositionResult.Status.EXACT_SCN_NOT_FOUND);
  // SCN 250 is invalid (as is 251); expect 253 since max SCN of following transaction
  finder.reset();
  res = posSetter.locateFilePosition(250, finder);
  assertFilePositionResult(res, dir, 253, FilePositionResult.Status.EXACT_SCN_NOT_FOUND);
  // SCN 251 is invalid (as is 250); expect 253 since max SCN of following transaction
  finder.reset();
  res = posSetter.locateFilePosition(251, finder);
  assertFilePositionResult(res, dir, 253, FilePositionResult.Status.EXACT_SCN_NOT_FOUND);
  // SCN 252 is valid and present, but weird corner case => still EXACT_SCN_NOT_FOUND
  finder.reset();
  res = posSetter.locateFilePosition(252, finder);
  assertFilePositionResult(res, dir, 252, FilePositionResult.Status.EXACT_SCN_NOT_FOUND);
  // SCN 253 is valid and present and max SCN of its transaction => FOUND
  finder.reset();
  res = posSetter.locateFilePosition(253, finder);
  assertFilePositionResult(res, dir, 253, FilePositionResult.Status.FOUND);
  // SCN 309 is valid and present and max SCN of its transaction => FOUND (even though
  // split across second/third files, and following transaction is corrupted)
  finder.reset();
  res = posSetter.locateFilePosition(309, finder);
  assertFilePositionResult(res, dir, 309, FilePositionResult.Status.FOUND);
  // SCN 310 is invalid (as is 311); expect 313
  finder.reset();
  res = posSetter.locateFilePosition(310, finder);
  assertFilePositionResult(res, dir, 313, FilePositionResult.Status.EXACT_SCN_NOT_FOUND);
  // SCN 311 is invalid (as is 310); expect 313
  finder.reset();
  res = posSetter.locateFilePosition(311, finder);
  assertFilePositionResult(res, dir, 313, FilePositionResult.Status.EXACT_SCN_NOT_FOUND);
  // SCN 398 is invalid (as is 399) and is in last transaction of last file, but since
  // trail file is expected to continue growing (i.e., eventually to have a valid SCN
  // that's larger than the request), expect EXACT_SCN_NOT_FOUND rather than ERROR.  SCN
  // returned will be that of last valid transaction, i.e., 397.
  // [checks beginning of last valid transaction == 396/397 one at byte offset 35650]
  finder.reset();
  res = posSetter.locateFilePosition(398, finder);
  assertFilePositionResult(res, dir, 397, FilePositionResult.Status.EXACT_SCN_NOT_FOUND);
  // SCN 405 is completely missing (would be after last transaction of last file); expect
  // same behavior as previous case
  finder.reset();
  res = posSetter.locateFilePosition(405, finder);
  assertFilePositionResult(res, dir, 397, FilePositionResult.Status.EXACT_SCN_NOT_FOUND);
  // last valid transaction-SCN is 397
  finder.reset();
  res = posSetter.locateFilePosition(TrailFilePositionSetter.USE_LATEST_SCN, finder);
  assertFilePositionResult(res, dir, 397, FilePositionResult.Status.FOUND);
  log.info(DONE_STRING);
}