### Question:
TailFile extends AbstractProcessor { Map<String, TailFileObject> getState() { return states; }  @Override Set<Relationship> getRelationships(); @Override void onPropertyModified(final PropertyDescriptor descriptor, final String oldValue, final String newValue); @OnScheduled void recoverState(final ProcessContext context); @OnStopped void cleanup(); @Override void onTrigger(final ProcessContext context, final ProcessSession session);  }### Answer:
@Test public void testConsumeWhenNewLineFound() throws IOException, InterruptedException { runner.run(); runner.assertAllFlowFilesTransferred(TailFile.REL_SUCCESS, 0); Thread.sleep(1100L); raf.write("Hello, World".getBytes()); runner.run(); runner.assertAllFlowFilesTransferred(TailFile.REL_SUCCESS, 0); raf.write("\r\n".getBytes()); runner.run(); runner.assertAllFlowFilesTransferred(TailFile.REL_SUCCESS, 1); final TailFileState state = ((TailFile) runner.getProcessor()).getState().get("target/log.txt").getState(); assertNotNull(state); assertEquals("target/log.txt", state.getFilename()); assertTrue(state.getTimestamp() <= System.currentTimeMillis()); assertEquals(14, state.getPosition()); runner.getFlowFilesForRelationship(TailFile.REL_SUCCESS).get(0).assertContentEquals("Hello, World\r\n"); runner.clearTransferState(); raf.write("12345".getBytes()); runner.run(); runner.assertAllFlowFilesTransferred(TailFile.REL_SUCCESS, 0); raf.write("\n".getBytes()); runner.run(); runner.assertAllFlowFilesTransferred(TailFile.REL_SUCCESS, 1); runner.getFlowFilesForRelationship(TailFile.REL_SUCCESS).get(0).assertContentEquals("12345\n"); runner.clearTransferState(); raf.write("carriage\rreturn\r".getBytes()); runner.run(); runner.assertAllFlowFilesTransferred(TailFile.REL_SUCCESS, 1); runner.getFlowFilesForRelationship(TailFile.REL_SUCCESS).get(0).assertContentEquals("carriage\r"); runner.clearTransferState(); raf.write("\r\n".getBytes()); runner.run(); runner.assertAllFlowFilesTransferred(TailFile.REL_SUCCESS, 1); runner.getFlowFilesForRelationship(TailFile.REL_SUCCESS).get(0).assertContentEquals("return\r\r\n"); }
@Test public void testMigrateFrom100To110() throws IOException { runner.setProperty(TailFile.FILENAME, "target/existing-log.txt"); final MockStateManager stateManager = runner.getStateManager(); final Map<String, String> state = new HashMap<>(); state.put("filename", "target/existing-log.txt"); state.put("checksum", "2279929157"); state.put("position", "14"); state.put("timestamp", "1480639134000"); stateManager.setState(state, Scope.LOCAL); runner.run(); runner.assertAllFlowFilesTransferred(TailFile.REL_SUCCESS, 1); final MockFlowFile flowFile = runner.getFlowFilesForRelationship(TailFile.REL_SUCCESS).iterator().next(); final ByteArrayOutputStream bos = new ByteArrayOutputStream(); try (final BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(bos))) { writer.write("Line 3"); writer.newLine(); } flowFile.assertContentEquals(bos.toByteArray()); final StateMap updatedState = stateManager.getState(Scope.LOCAL); assertNull(updatedState.get("filename")); assertNull(updatedState.get("checksum")); assertNull(updatedState.get("position")); assertNull(updatedState.get("timestamp")); assertEquals("target/existing-log.txt", updatedState.get("file.0.filename")); assertEquals("3380848603", updatedState.get("file.0.checksum")); assertEquals("21", updatedState.get("file.0.position")); assertNotNull(updatedState.get("file.0.timestamp")); runner.clearTransferState(); runner.run(); runner.assertAllFlowFilesTransferred(TailFile.REL_SUCCESS, 0); }