@@ -121,7 +121,8 @@ public void synchronousPublisher_shouldNotHang() throws Exception {
121121 @ Test
122122 void noConfiguration_fileAlreadyExists_shouldThrowException () throws Exception {
123123 Path testPath = testFs .getPath ("test_file.txt" );
124- Files .write (testPath , RandomStringUtils .random (1000 ).getBytes (StandardCharsets .UTF_8 ));
124+ String existingContent = RandomStringUtils .randomAlphanumeric (1000 );
125+ Files .write (testPath , existingContent .getBytes (StandardCharsets .UTF_8 ));
125126 assertThat (testPath ).exists ();
126127
127128 String content = RandomStringUtils .randomAlphanumeric (30000 );
@@ -131,6 +132,7 @@ void noConfiguration_fileAlreadyExists_shouldThrowException() throws Exception {
131132 transformer .onResponse ("foobar" );
132133 transformer .onStream (testPublisher (content ));
133134 assertThatThrownBy (() -> future .join ()).hasRootCauseInstanceOf (FileAlreadyExistsException .class );
135+ assertThat (testPath ).hasContent (existingContent );
134136 }
135137
136138 @ Test
@@ -186,6 +188,73 @@ void createOrAppendExisting_fileExists_shouldAppend() throws Exception {
186188 assertThat (testPath ).hasContent (existingString + content );
187189 }
188190
191+ @ ParameterizedTest
192+ @ MethodSource ("deleteConfigurations" )
193+ void exceptionOccurred_beforeFileOpened_shouldPreserveExistingFile (FileTransformerConfiguration configuration )
194+ throws Exception {
195+ Path testPath = testFs .getPath ("test_file.txt" );
196+ String existingContent = RandomStringUtils .randomAlphanumeric (1000 );
197+ Files .write (testPath , existingContent .getBytes (StandardCharsets .UTF_8 ));
198+
199+ FileAsyncResponseTransformer <String > transformer = new FileAsyncResponseTransformer <>(testPath , configuration );
200+ CompletableFuture <String > future = transformer .prepare ();
201+ RuntimeException exception = new RuntimeException ("oops" );
202+ transformer .exceptionOccurred (exception );
203+
204+ assertThat (future ).failsWithin (1 , TimeUnit .SECONDS )
205+ .withThrowableOfType (ExecutionException .class )
206+ .withCause (exception );
207+ assertThat (testPath ).hasContent (existingContent );
208+ }
209+
210+ @ Test
211+ void exceptionOccurred_beforeFileOpenedOnRetry_shouldPreserveExistingFile () throws Exception {
212+ Path testPath = testFs .getPath ("test_file.txt" );
213+ FileAsyncResponseTransformer <String > transformer = new FileAsyncResponseTransformer <>(testPath );
214+
215+ stubException (transformer );
216+ assertThat (testPath ).doesNotExist ();
217+
218+ String existingContent = RandomStringUtils .randomAlphanumeric (1000 );
219+ Files .write (testPath , existingContent .getBytes (StandardCharsets .UTF_8 ));
220+ CompletableFuture <String > future = transformer .prepare ();
221+ RuntimeException exception = new RuntimeException ("oops" );
222+ transformer .exceptionOccurred (exception );
223+
224+ assertThat (future ).failsWithin (1 , TimeUnit .SECONDS )
225+ .withThrowableOfType (ExecutionException .class )
226+ .withCause (exception );
227+ assertThat (testPath ).hasContent (existingContent );
228+ }
229+
230+ @ Test
231+ void exceptionOccurred_afterFileOpened_shouldAllowRetry () throws Exception {
232+ Path testPath = testFs .getPath ("test_file.txt" );
233+ FileAsyncResponseTransformer <String > transformer = new FileAsyncResponseTransformer <>(testPath );
234+
235+ stubException (transformer );
236+ assertThat (testPath ).doesNotExist ();
237+
238+ String content = RandomStringUtils .randomAlphanumeric (1000 );
239+ stubSuccessfulStreaming (content , transformer );
240+ assertThat (testPath ).hasContent (content );
241+ }
242+
243+ @ Test
244+ void exceptionOccurred_calledTwice_shouldNotDeleteReplacement () throws Exception {
245+ Path testPath = testFs .getPath ("test_file.txt" );
246+ FileAsyncResponseTransformer <String > transformer = new FileAsyncResponseTransformer <>(testPath );
247+
248+ stubException (transformer );
249+ assertThat (testPath ).doesNotExist ();
250+
251+ String replacementContent = RandomStringUtils .randomAlphanumeric (1000 );
252+ Files .write (testPath , replacementContent .getBytes (StandardCharsets .UTF_8 ));
253+ transformer .exceptionOccurred (new RuntimeException ("second callback" ));
254+
255+ assertThat (testPath ).hasContent (replacementContent );
256+ }
257+
189258 @ ParameterizedTest
190259 @ MethodSource ("configurations" )
191260 void exceptionOccurred_deleteFileBehavior (FileTransformerConfiguration configuration ) throws Exception {
@@ -203,6 +272,17 @@ void exceptionOccurred_deleteFileBehavior(FileTransformerConfiguration configura
203272 }
204273 }
205274
275+ private static List <FileTransformerConfiguration > deleteConfigurations () {
276+ List <FileTransformerConfiguration > conf = new ArrayList <>();
277+ for (FileWriteOption fileWriteOption : FileWriteOption .values ()) {
278+ conf .add (FileTransformerConfiguration .builder ()
279+ .fileWriteOption (fileWriteOption )
280+ .failureBehavior (DELETE )
281+ .build ());
282+ }
283+ return conf ;
284+ }
285+
206286 private static List <FileTransformerConfiguration > configurations () {
207287 List <FileTransformerConfiguration > conf = new ArrayList <>();
208288 conf .add (FileTransformerConfiguration .defaultCreateNew ());
0 commit comments