Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit e6ea17b

Browse files
committed
Merge cucumber#978 'Double-check for directory exists in ...'.
Also update History.md.
2 parents 631eb24 + cf811be commit e6ea17b

File tree

3 files changed

+88
-1
lines changed

3 files changed

+88
-1
lines changed

History.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
## [1.2.5-SNAPSHOT](https://github.com/cucumber/cucumber-jvm/compare/v1.2.4...master) (In Git)
22

3+
* [Core] Double-check for directory exists in the ensureParentDirExists(File) ([#978](https://github.com/cucumber/cucumber-jvm/pull/978) Pavel Ordenko)
34
* [picocontainer] Picocontainer lifecycle support([#994](https://github.com/cucumber/cucumber-jvm/pull/994), [#993](https://github.com/cucumber/cucumber-jvm/issues/993), [#992](https://github.com/cucumber/cucumber-jvm/pull/992) Richard Bradley)
45
* [Core] Specifying plugins on the command line via `--plugin` clobbers settings in the code ([#860](https://github.com/cucumber/cucumber-jvm/pull/860) Björn Rasmusson)
56
* [Core] Make test assertion OS agnostic ([#897](https://github.com/cucumber/cucumber-jvm/pull/897/files) sid)

core/src/main/java/cucumber/runtime/io/URLOutputStream.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ public URLOutputStream(URL url, String method, Map<String, String> headers, int
4848

4949
private void ensureParentDirExists(File file) throws IOException {
5050
if (file.getParentFile() != null && !file.getParentFile().isDirectory()) {
51-
boolean ok = file.getParentFile().mkdirs();
51+
boolean ok = file.getParentFile().mkdirs() || file.getParentFile().isDirectory();
5252
if (!ok) {
5353
throw new IOException("Failed to create directory " + file.getParentFile().getAbsolutePath());
5454
}

core/src/test/java/cucumber/runtime/io/URLOutputStreamTest.java

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44
import gherkin.util.FixJava;
55
import org.junit.After;
66
import org.junit.Before;
7+
import org.junit.Rule;
78
import org.junit.Test;
9+
import org.junit.rules.TemporaryFolder;
810
import org.webbitserver.HttpControl;
911
import org.webbitserver.HttpHandler;
1012
import org.webbitserver.HttpRequest;
@@ -27,17 +29,28 @@
2729
import java.nio.charset.Charset;
2830
import java.nio.file.Files;
2931
import java.nio.file.Path;
32+
import java.util.ArrayList;
33+
import java.util.List;
3034
import java.util.concurrent.BlockingQueue;
35+
import java.util.concurrent.CountDownLatch;
3136
import java.util.concurrent.ExecutionException;
3237
import java.util.concurrent.Executors;
3338
import java.util.concurrent.LinkedBlockingDeque;
3439
import java.util.concurrent.TimeUnit;
3540

3641
import static org.junit.Assert.assertEquals;
42+
import static org.junit.Assert.assertTrue;
3743
import static org.junit.Assert.fail;
3844

3945
public class URLOutputStreamTest {
4046
private WebServer webbit;
47+
private final int threadsCount = 100;
48+
private final long waitTimeoutMillis = 30000L;
49+
private final List<File> tmpFiles = new ArrayList<File>();
50+
private final List<String> threadErrors = new ArrayList<String>();
51+
52+
@Rule
53+
public TemporaryFolder tempFolder = new TemporaryFolder();
4154

4255
@Before
4356
public void startWebbit() throws ExecutionException, InterruptedException {
@@ -127,7 +140,80 @@ public void handleHttpRequest(HttpRequest req, HttpResponse res, HttpControl ctl
127140
}
128141
}
129142

143+
@Test
144+
public void do_not_throw_ioe_if_parent_dir_created_by_another_thread() {
145+
final CountDownLatch countDownLatch = new CountDownLatch(1);
146+
List<Thread> testThreads = getThreadsWithLatchForFile(countDownLatch, threadsCount);
147+
startThreadsFromList(testThreads);
148+
countDownLatch.countDown();
149+
waitAllThreadsFromList(testThreads);
150+
assertTrue("Not all parent folders were created for tmp file or tmp file was not created", isAllFilesCreated());
151+
assertTrue("Some thread get error during work. Error list:" + threadErrors.toString(), threadErrors.isEmpty());
152+
}
153+
130154
private Reader openUTF8FileReader(final File file) throws IOException {
131155
return new InputStreamReader(new FileInputStream(file), Charset.forName("UTF-8"));
132156
}
157+
158+
private List<Thread> getThreadsWithLatchForFile(final CountDownLatch countDownLatch, int threadsCount) {
159+
List<Thread> result = new ArrayList<Thread>();
160+
String ballast = "" + System.currentTimeMillis();
161+
for (int i = 0; i < threadsCount; i++) {
162+
final int curThreadNo = i;
163+
// It useful when 2-3 threads (not more) tries to create the same directory for the report
164+
final File tmp = (i % 3 == 0 || i % 3 == 2) ?
165+
new File(tempFolder.getRoot().getAbsolutePath() + "/cuce" + ballast + i + "/tmpFile.tmp") :
166+
new File(tempFolder.getRoot().getAbsolutePath() + "/cuce" + ballast + (i - 1) + "/tmpFile.tmp");
167+
tmpFiles.add(tmp);
168+
result.add(new Thread() {
169+
@Override
170+
public void run() {
171+
try {
172+
// Every thread should wait command to run
173+
countDownLatch.await();
174+
new URLOutputStream(tmp.toURI().toURL());
175+
} catch (IOException e) {
176+
threadErrors.add("Thread" + curThreadNo + ": parent dir not created. " + e.getMessage());
177+
} catch (InterruptedException e) {
178+
threadErrors.add("Thread" + curThreadNo + ": not started on time. " + e.getMessage());
179+
}
180+
}
181+
});
182+
}
183+
return result;
184+
}
185+
186+
private void startThreadsFromList(List<Thread> threads) {
187+
for (Thread thread : threads) {
188+
thread.start();
189+
}
190+
}
191+
192+
private void waitAllThreadsFromList(List<Thread> threads) {
193+
long timeStart = System.currentTimeMillis();
194+
do {
195+
// Protection from forever loop
196+
if (System.currentTimeMillis() - timeStart > waitTimeoutMillis) {
197+
assertTrue("Some threads are still alive", false);
198+
}
199+
} while (hasListAliveThreads(threads));
200+
}
201+
202+
private boolean hasListAliveThreads(List<Thread> threads) {
203+
for (Thread thread : threads) {
204+
if (thread.isAlive()) {
205+
return true;
206+
}
207+
}
208+
return false;
209+
}
210+
211+
private boolean isAllFilesCreated() {
212+
for (File tmpFile : tmpFiles) {
213+
if (tmpFile.getParentFile() == null || !tmpFile.getParentFile().isDirectory() || !tmpFile.exists()) {
214+
return false;
215+
}
216+
}
217+
return true;
218+
}
133219
}

0 commit comments

Comments
 (0)