browserstack / browserstack-local-java

Java bindings for BrowserStack Local
https://www.browserstack.com
MIT License
18 stars 34 forks source link

bug: random ".browserstack/BrowserStackLocal": error=26, Text file busy" when running tests on CI #60

Closed dacloutier-logmein closed 3 years ago

dacloutier-logmein commented 3 years ago

My setup consist of a series of JUnit5 tests, that are run in concurrent mode. Locally, if I try to execute the tests, I have no issues. (I have had up to 15 concurrent tests running without problem).

Expected Behavior

The Browserstacklocal process should start just fine, regardless of its location (local laptop or CI server (Jenkins in my case))

Actual Behavior

The same suite of tests will on a random fashion throw out errors of this type if ran from the CI server:

org.opentest4j.AssertionFailedError: java.io.IOException: Cannot run program "/home/gradle/.browserstack/BrowserStackLocal": error=26, Text file busy
[com.browserstack.local.LocalBinary.validateBinary(LocalBinary.java:107), com.browserstack.local.LocalBinary.checkBinary(LocalBinary.java:75), com.browserstack.local.LocalBinary.<init>(LocalBinary.java:30), com.browserstack.local.Local.start(Local.java:59), utils.webdrivers.BrowserStackWebDriverProvider.startBrowserStackLocalProcess(BrowserStackWebDriverProvider.java:156), utils.webdrivers.BrowserStackWebDriverProvider.setupWebDriver(BrowserStackWebDriverProvider.java:121), utils.webdrivers.BrowserStackWebDriverProvider.getBrowserStackWebDriver(BrowserStackWebDriverProvider.java:177), com.mycompany.project.e2e.BaseTest.setWebDriver(BaseTest.java:100), com.mycompany.project.e2e.ExampleBrowserBasedTest.executeTestContent(ExampleBrowserBasedTest.java:77), com.mycompany.project.e2e.ExampleBrowserBasedTest.lambda$exampleTestThatRunsInAllTags$0(ExampleBrowserBasedTest.java:45), org.junit.jupiter.engine.descriptor.DynamicTestTestDescriptor.lambda$execute$0(DynamicTestTestDescriptor.java:52), org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131), org.junit.jupiter.api.extension.InvocationInterceptor.interceptDynamicTest(InvocationInterceptor.java:161), org.junit.jupiter.engine.descriptor.DynamicTestTestDescriptor.lambda$execute$1(DynamicTestTestDescriptor.java:58), org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptorCall.lambda$ofVoid$0(InvocationInterceptorChain.java:78), org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106), org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64), org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45), org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37), org.junit.jupiter.engine.descriptor.DynamicTestTestDescriptor.execute(DynamicTestTestDescriptor.java:57), org.junit.jupiter.engine.descriptor.DynamicTestTestDescriptor.execute(DynamicTestTestDescriptor.java:31), org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139), org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73), org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:129), org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137), org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:127), org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73), org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:126), org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:84), org.junit.platform.engine.support.hierarchical.ForkJoinPoolHierarchicalTestExecutorService$ExclusiveTask.compute(ForkJoinPoolHierarchicalTestExecutorService.java:185), java.base/java.util.concurrent.RecursiveAction.exec(RecursiveAction.java:189), java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:290), java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1020), java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1656), java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1594), java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:177)]
    at org.junit.jupiter.api.AssertionUtils.fail(AssertionUtils.java:39)
    at org.junit.jupiter.api.Assertions.fail(Assertions.java:117)
    at utils.webdrivers.BrowserStackWebDriverProvider.startBrowserStackLocalProcess(BrowserStackWebDriverProvider.java:165)
    at utils.webdrivers.BrowserStackWebDriverProvider.setupWebDriver(BrowserStackWebDriverProvider.java:121)
    at utils.webdrivers.BrowserStackWebDriverProvider.getBrowserStackWebDriver(BrowserStackWebDriverProvider.java:177)
    at com.mycompany.project.e2e.BaseTest.setWebDriver(BaseTest.java:100)
    at com.mycompany.project.e2e.ExampleBrowserBasedTest.executeTestContent(ExampleBrowserBasedTest.java:77)
    at com.mycompany.project.e2e.ExampleBrowserBasedTest.lambda$exampleTestThatRunsInAllTags$0(ExampleBrowserBasedTest.java:45)
    at org.junit.jupiter.engine.descriptor.DynamicTestTestDescriptor.lambda$execute$0(DynamicTestTestDescriptor.java:52)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
    at org.junit.jupiter.api.extension.InvocationInterceptor.interceptDynamicTest(InvocationInterceptor.java:161)
    at org.junit.jupiter.engine.descriptor.DynamicTestTestDescriptor.lambda$execute$1(DynamicTestTestDescriptor.java:58)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptorCall.lambda$ofVoid$0(InvocationInterceptorChain.java:78)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
    at org.junit.jupiter.engine.descriptor.DynamicTestTestDescriptor.execute(DynamicTestTestDescriptor.java:57)
    at org.junit.jupiter.engine.descriptor.DynamicTestTestDescriptor.execute(DynamicTestTestDescriptor.java:31)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:129)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:127)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:126)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:84)
    at org.junit.platform.engine.support.hierarchical.ForkJoinPoolHierarchicalTestExecutorService$ExclusiveTask.compute(ForkJoinPoolHierarchicalTestExecutorService.java:185)
    at java.base/java.util.concurrent.RecursiveAction.exec(RecursiveAction.java:189)
    at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:290)
    at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1020)
    at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1656)
    at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1594)
    at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:177)

Steps to Reproduce the Problem

  1. Create a Junit5 Based suite of that that will run in Concurrent manner.
  2. Push build on the CI server (I used a gradle build, but I am pretty sure Maven would also do)
  3. You should get random failures (The more parallel tests you have the more likely it is to occur)

browserstack local arguments

better yet, here's the initialization code:

final Local browserstackLocal = new Local();
    Map<String, String> options = new HashMap<>();
    options.put("key", accessKey);
    String localIdentifier = UUID.randomUUID().toString();
    options.put("localIdentifier", localIdentifier);
    options.put("forcelocal", "true");
    capabilities.setCapability("browserstack.localIdentifier", localIdentifier);

    browserstackLocal.start(options);  

Platform details

  1. browserstack-local-java version: 1.0.6
  2. java version: adoptOpenJDK => jdk-11.0.7_10-1
  3. os type and version: This is running from a Jenkins server, os is linux what flavor though, I cannot say as I am not exposed to such details.

details

issue doesn't see to be specific to jenkins as someone else had the issue with CircleCI: https://discuss.circleci.com/t/parallel-access-to-binary-file/35853

dacloutier-logmein commented 3 years ago

So, I managed to fix the issue. Solution was to start the browserstacklocal process in the @BeforeAll of my test suite, so, that way, it would open the tunnel just once for the whose suite.

Then each tests had to supply their desired capabilities.