public boolean canPlayback() { return _scene.isReadable(); }
public String getSceneName() { return _scene.getName(); }
public Scene(SceneConfiguration sceneConfiguration) { this(sceneConfiguration.getSceneName(), sceneConfiguration.getSceneMode(), sceneConfiguration.getSceneRoot(), new ArrayList<>()); }
/** * Helper method that will be used for unit test * */ static Scene create(SceneConfiguration sceneConfiguration, SceneReader sceneReader) throws IOException { Scene sceneResult = null; Scene sceneFromLocal = sceneReader.readScene(sceneConfiguration.getSceneRoot(), sceneConfiguration.getSceneName()); if (sceneFromLocal == null) { if (sceneConfiguration.getSceneMode() == SceneMode.PLAYBACK || sceneConfiguration.getSceneMode() == SceneMode.SEQUENTIAL_PLAYBACK) { throw new IllegalStateException(String.format("No Scene is found at %s/%s", sceneConfiguration.getSceneRoot(), sceneConfiguration.getSceneName())); } else { sceneResult = new Scene(sceneConfiguration); } } else { List<RecordedHttpExchange> recordedHttpExchanges = sceneFromLocal.getRecordedHttpExchangeList(); // In sequential record mode, start with an empty scene if (sceneConfiguration.getSceneMode() == SceneMode.SEQUENTIAL_RECORD) { recordedHttpExchanges = new ArrayList<>(); } sceneResult = new Scene(sceneConfiguration.getSceneName(), sceneConfiguration.getSceneMode(), sceneConfiguration.getSceneRoot(), recordedHttpExchanges); } return sceneResult; } }
/** * here is the place to be used in test case and within this runnable flashback will use the scene according to the sceneName. * * @param sceneName the scene name, will be loaded into flashback using PLAYBACK mode and default scene path. * @param runnable to call after the scene loaded. */ protected void withScene(String sceneName, Runnable runnable) { SceneConfiguration sceneConfiguration = new SceneConfiguration(_defaultScenePath, _defaultSceneMode, sceneName); withScene(sceneConfiguration, runnable); }
/** * Given incoming http request, find matched response from the scene and return response from the scene * @param request http request from client * @return matched http response from the scene * * */ public RecordedHttpResponse playback(RecordedHttpRequest request) { if (!_scene.isReadable()) { throw new IllegalStateException(THE_SCENE_IS_NOT_READABLE); } int position = findMatchRequest(request); if (position < 0) { throw new IllegalStateException(NO_MATCHING_RECORDING_FOUND); } if (_scene.isSequential()) { _sequencePosition++; } List<RecordedHttpExchange> recordedHttpExchangeList = _scene.getRecordedHttpExchangeList(); return recordedHttpExchangeList.get(position).getRecordedHttpResponse(); }
@Test public void testCreateSceneNotExistInRecordMode() throws Exception { Scene result = runTestGetResult(SceneMode.RECORD, null); Assert.assertNotNull(result); Assert.assertEquals(result.getName(), NAME); Assert.assertEquals(result.getSceneRoot(), ROOT); Assert.assertFalse(result.isReadable()); }
@Test public void testCanReplayScene() { SceneConfiguration sceneConfiguration1 = new SceneConfiguration(ROOT_PATH, SceneMode.PLAYBACK, SCENE_NAME); Scene scene1 = new Scene(sceneConfiguration1); SceneAccessLayer sceneAccessLayer = new SceneAccessLayer(scene1, EasyMock.createStrictMock(SceneWriter.class), EasyMock.createStrictMock(MatchRule.class)); Assert.assertTrue(sceneAccessLayer.canPlayback()); Scene scene2 = new Scene(new SceneConfiguration(ROOT_PATH, SceneMode.RECORD, SCENE_NAME)); sceneAccessLayer.setScene(scene2); Assert.assertFalse(sceneAccessLayer.canPlayback()); Scene scene3 = new Scene(new SceneConfiguration(ROOT_PATH, SceneMode.SEQUENTIAL_PLAYBACK, SCENE_NAME)); sceneAccessLayer.setScene(scene3); Assert.assertTrue(sceneAccessLayer.canPlayback()); Scene scene4 = new Scene(new SceneConfiguration(ROOT_PATH, SceneMode.SEQUENTIAL_RECORD, SCENE_NAME)); sceneAccessLayer.setScene(scene4); Assert.assertFalse(sceneAccessLayer.canPlayback()); }
/** * Record request and response to the scene. Updates will be performed in-memory and will be written to disk * when flush() is called, or when the Scene is changed. * @param recordedHttpRequest http request from client * @param recordedHttpResponse http response from upstream service * * */ public void record(RecordedHttpRequest recordedHttpRequest, RecordedHttpResponse recordedHttpResponse) { List<RecordedHttpExchange> recordedHttpExchangeList = _scene.getRecordedHttpExchangeList(); RecordedHttpExchange recordedHttpExchange = new RecordedHttpExchange(recordedHttpRequest, recordedHttpResponse, new Date()); if (!_scene.isSequential()) { int position = findMatchRequest(recordedHttpRequest); if (position >= 0) { recordedHttpExchangeList.set(position, recordedHttpExchange); } else { recordedHttpExchangeList.add(recordedHttpExchange); } } else { recordedHttpExchangeList.add(recordedHttpExchange); } _dirty = true; }
public void serialize(Scene scene, Writer writer) throws IOException { _jsonGenerator = JSON_FACTORY.createGenerator(writer); _jsonGenerator.setPrettyPrinter(new DefaultPrettyPrinter()); _jsonGenerator.writeStartObject(); _jsonGenerator.writeStringField(SceneSerializationConstant.SCENE_TAG_NAME, scene.getName()); writeHttpExchanges(scene.getRecordedHttpExchangeList()); _jsonGenerator.writeEndObject(); _jsonGenerator.close(); }
/** * Store scene in file * */ public void writeScene(Scene scene) throws IOException { File file = new File(scene.getSceneRoot(), scene.getName()); File parent = file.getParentFile(); if (!parent.exists() && !parent.mkdirs()) { throw new IllegalStateException("Failed to create new directory: " + parent); } BufferedWriter bufferedWriter = Files.newWriter(file, Charset.forName(SceneSerializationConstant.FILE_CHARSET)); SceneSerializer sceneSerializer = new SceneSerializer(); sceneSerializer.serialize(scene, bufferedWriter); } }
public Scene deserialize(Reader reader) throws IOException { _jsonParser = JSON_FACTORY.createParser(reader); skipStartObject(); _jsonParser.nextToken(); validateRequiredField(SceneSerializationConstant.SCENE_TAG_NAME); _jsonParser.nextToken(); String name = _jsonParser.getValueAsString(); return new Scene(name, null, ".", createHttpExchangeList()); }
public static SceneMode fromString(String text) { if (text != null) { for (SceneMode sceneMode : SceneMode.values()) { if (text.equalsIgnoreCase(sceneMode._text)) { return sceneMode; } } } return null; } }
public SceneAccessLayer() { this(new DummyScene(), new SceneWriter(), new DummyMatchRule()); }
/** * here is the place to be used in test case and within this callable flashback will use the scene specified by sceneName. * * @param sceneName the scene name, will be loaded into flashback using PLAYBACK mode and default scene path. * @param callable to call after the scene changed in flashback. * @param <T> return type of the callable. * @return return callable result. * @throws Exception */ protected <T> T withScene(String sceneName, Callable<T> callable) throws Exception { SceneConfiguration sceneConfiguration = new SceneConfiguration(_defaultScenePath, _defaultSceneMode, sceneName); return withScene(sceneConfiguration, callable); }
/** * find matched request from scene * @param request incoming request that we'd like match in existing scene * @return position of list of HttpExchanges from the scene. return -1 if no match found * * */ private int findMatchRequest(final RecordedHttpRequest request) { if (_scene.isSequential()) { List<RecordedHttpExchange> exchangeList = _scene.getRecordedHttpExchangeList(); // In sequential playback mode, only test the request at the current sequence index if (_sequencePosition < exchangeList.size() && _matchRule .test(request, exchangeList.get(_sequencePosition).getRecordedHttpRequest())) { return _sequencePosition; } return -1; } else { return Iterables.indexOf(_scene.getRecordedHttpExchangeList(), input -> _matchRule.test(request, input.getRecordedHttpRequest())); } } }
@Test(expectedExceptions = IllegalStateException.class, expectedExceptionsMessageRegExp = SceneAccessLayer.THE_SCENE_IS_NOT_READABLE) public void testPlaybackNotReadable() throws IOException { Scene scene = EasyMock.createStrictMock(Scene.class); EasyMock.expect(scene.isReadable()).andReturn(false); SceneWriter sceneWriter = EasyMock.createStrictMock(SceneWriter.class); MatchRule matchRule = EasyMock.createStrictMock(MatchRule.class); RecordedHttpRequest incomingHttpRequest = EasyMock.createStrictMock(RecordedHttpRequest.class); EasyMock.replay(scene); SceneAccessLayer sceneAccessLayer = new SceneAccessLayer(scene, sceneWriter, matchRule); sceneAccessLayer.playback(incomingHttpRequest); EasyMock.verify(scene); }
/** * Read scene from file and construct Scene object * @param name scene name * @return scene object de-serialized from file * * */ public Scene readScene(String rootPath, String name) throws IOException { File file = new File(rootPath, name); if (file.isFile()) { if (file.length() == 0) { return new Scene(name, null, rootPath, new ArrayList<>()); } BufferedReader reader = Files.newReader(file, Charset.forName(SceneSerializationConstant.FILE_CHARSET)); SceneDeserializer sceneDeserializer = new SceneDeserializer(); return sceneDeserializer.deserialize(reader); } return null; } }
private Scene runTestGetResult(SceneMode scenMode, Scene expectedScene) throws IOException { _sceneReader = EasyMock.createStrictMock(SceneReader.class); SceneConfiguration sceneConfiguration = new SceneConfiguration(ROOT, scenMode, NAME); EasyMock.expect(_sceneReader.readScene(EasyMock.anyString(), EasyMock.anyString())).andReturn(expectedScene); EasyMock.replay(_sceneReader); Scene result = SceneFactory.create(sceneConfiguration, _sceneReader); return result; }
@Action(name = "changeScene") public void changeScene(@ActionParam("sceneName") String sceneName) { validate(); SceneConfiguration sceneConfiguration = new SceneConfiguration(_scenePath, _currSceneMode, sceneName); try { _flashbackRunner.setScene(SceneFactory.create(sceneConfiguration)); } catch (IOException e) { throw new RestLiServiceException(HttpStatus.S_500_INTERNAL_SERVER_ERROR, e); } }