karate: JS / Multi threaded access error when using karate.callSingle()
I mentioned this issue here: https://github.com/intuit/karate/issues/1373#issuecomment-788636073
Thought it might be fixed in #1480 in 1.0 but it appears not having tried the release version this morning.
Here is a minimal repro repo: https://github.com/JoshSchreuder/karate-repro
0.9.6
java "-Dkarate.config.dir=C:\Temp\karaterepro" -jar "C:\temp\karate0.9.6.jar" "C:\Temp\karaterepro\demo\api"
is working with no issues
1.0.0
java "-Dkarate.config.dir=C:\Temp\karaterepro" -jar "C:\temp\karate1.0.jar" "C:\Temp\karaterepro\demo\api"
fails with
org.graalvm.polyglot.PolyglotException: java.io.FileNotFoundException: C:\Temp\karaterepro\demo\api\C:\Temp\karaterepro\features\auth\auth.feature (The filename, directory name, or volume label syntax is incorrect)
- com.intuit.karate.resource.FileResource.getStream(FileResource.java:98)
- com.intuit.karate.core.FeatureParser.parse(FeatureParser.java:73)
- com.intuit.karate.core.Feature.read(Feature.java:67)
- com.intuit.karate.core.ScenarioFileReader.readFile(ScenarioFileReader.java:64)
- com.intuit.karate.core.ScenarioBridge.read(ScenarioBridge.java:625)
- com.intuit.karate.core.ScenarioBridge.callSingle(ScenarioBridge.java:209)
- com.intuit.karate.core.ScenarioBridge.callSingle(ScenarioBridge.java:155)
It looks like it’s appending the test directory to the start of the callSingle call? Couldn’t find anything in the breaking changes about this, so not sure if it’s intentional or a bug.
I’m on Windows 10 x64 21H1. Java:
openjdk 11.0.10 2021-01-19
OpenJDK Runtime Environment AdoptOpenJDK (build 11.0.10+9)
Eclipse OpenJ9 VM AdoptOpenJDK (build openj9-0.24.0, JRE 11 Windows 10 amd64-64-Bit Compressed References 20210120_899 (JIT enabled, AOT enabled)
OpenJ9 - 345e1b09e
OMR - 741e94ea8
JCL - 0a86953833 based on jdk-11.0.10+9)
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Comments: 60 (49 by maintainers)
Commits related to this issue
- added a callSingle() in config to the test in our suite that tries to simulate edge cases that the graal engine dont like ref: https://stackoverflow.com/q/66651979/143475 and #1515 — committed to karatelabs/karate by ptrthomas 3 years ago
- added a callSingle within a feature to the dicsussion #1515 — committed to karatelabs/karate by ptrthomas 3 years ago
- add callSingle to all scenarios for good measure #1515 — committed to karatelabs/karate by ptrthomas 3 years ago
- Try to reproduce https://github.com/intuit/karate/issues/1515 — committed to aleruz/karate-call-single-bug by deleted user 3 years ago
- Adding tests to reproduce #1515 — committed to joelpramos/karate by joelpramos 3 years ago
- part 1 - solving js context / thread-switching issues #1515 as suspected callSingle() with an argument that has a function in it making this commit so it is a very minimal delta, there may be 2 or 3 m... — committed to karatelabs/karate by ptrthomas 3 years ago
- part 2 - but looks like previous commit was the entire fix #1515 here added a second callSingle which uses results of the first callSingle and the first callSingle includes a function in the results — committed to karatelabs/karate by ptrthomas 3 years ago
- part 3 hopefully the final fix for #1515 problem 1: very bad bug in initMagicVariables where we were setting __arg to a wrapper not the raw object problem 2: we had completely missed hydrating / re-at... — committed to karatelabs/karate by ptrthomas 3 years ago
- part 4 - make sure callSingle() runs thread-safe for entire routine #1515 and also make sure that cached result if an exception is detached from the js engine — committed to karatelabs/karate by ptrthomas 3 years ago
- part 5 - after more investigation a deep clone is needed #1515 when we re-attach a callSingle result into the context explanation: when we detach, we just patch any js functions and replace them with ... — committed to karatelabs/karate by ptrthomas 3 years ago
- part 6 - after learning from this, some other mods #1515 - make sure that when we detach, it is always a deep-clone - use the same attach routine for a callonce - make sure that the async scenario-lis... — committed to karatelabs/karate by ptrthomas 3 years ago
- part 7 - more thinking and optimization #1515 dont un-necessarily attach for callonce now we dont need the extra synchronize for callsingle — committed to karatelabs/karate by ptrthomas 3 years ago
- weird formatting for prev commit #1515 — committed to karatelabs/karate by ptrthomas 3 years ago
- one more small tweak for #1515 — committed to karatelabs/karate by ptrthomas 3 years ago
- better comments to make life easier for future maintainers #1515 — committed to karatelabs/karate by ptrthomas 3 years ago
thank you @aleruz ! I think we are ready to release
Oh and finally… getting an exception when running in multi threaded mode with my
callSingleinkarate.config.js(I think that’s why).I’ll try and repro this minimally also.
1.0.1 released
@ptrthomas 🎉 seems this time is THE time 🎉 In my case no more issue! 👏🏻 Sad I could not reproduce it in an own separate example.
Tested the scenarios I had with that additional fix and works great. Thanks @ptrthomas , will check in a few things on top of that test for completeness that I tried in my local. @aleruz keep us posted on your results.
okay one more time, my last commit is again a simple one but with one critical fix for “magic variables” that I really hope is the end of it
would be great if everyone here can try this version
@aleruz question on your scenario, you said your feature called by callSingle() does a call twice to the same feature with different parameters.
Few questions on that - are those parameters reused within that call and how does that loop work? Any chance you can drop a screenshot here of that piece only and take out any private names / paths you might have?
one more question for all, we now think that one of the causes could be the use of
configure headers = funorkarate.configure('headers', fun)and wherefunis a JS functioncan y’all have a look whether that was involved. the other suspects are:
karate.callSingle()where you have passed some value as the second argumentBackgroundcalloncecallonceorkarate.callSingle()threw anExceptionI started from the blueprint, as suggested in https://github.com/intuit/karate/wiki/How-to-Submit-an-Issue. Using the
ParallelTest.java, trying to create a main feature which calls a sub-feature which calls another sub-feature. I also added some “Thread.sleep” to simulate a slow API (that is actually my real case). In parallel, trying to understand what in my current tests can be a reason for the failure.My current status is in this repo: https://github.com/aleruz/karate-call-single-bug
@ptrthomas I am on Mac as well. I am trying to debug right now, and found two things which seems to change the result of my test making it pass. But I need a bit more time to test it. At the moment, my suspicion is on two parallel runners which I created with different tags but which may be interfering in some tests (that was an experiment I did and that did not create issue with 0.9.6). Removing one of the two, seems to let the test pass now. But, I want to be sure. Will keep you posted here.
reopening and making sure @aleruz is part of the conversation 😃
@JoshSchreuder & @joelpramos - we have another report of the
callSingle()issue here: https://stackoverflow.com/q/66651979/143475I’ve asked the OP to comment in this thread. and meanwhile I tried my best to replicate the situation of a callSingle + feature + HTTP call in our “parallel” test that already mixes a
callonce, here is the commit: https://github.com/intuit/karate/commit/89f68168a43343975ce5d986811ba1d814d39b1dand it still seems to work fine. but hopefully y’all will be able to see what’s that extra bit in your tests that causing this problem.
ugh yes, that’s an edge case with the
matchparser which I hadn’t considered.just for completeness, this should work (long story):
* match (response.data.length) == 50will see if this can be improvedand the exception is very bad news 😐 cc @joelpramos
if your callSingle is setting up functions, try removing those and stick to pure data. else well. we need to dig
Oh I worked out the length thing, needed to change to
And assert response.data.length == 50cc @kirksl to be aware of VS Code extension usage
actually we prefer
karate.sizeOf(array)since we don’t want to trust the JS engine to do array length calcs@ptrthomas yeah my apologies, I didn’t have anything setup to build a new JAR off the source at the time.
Anyway, switching to
file:seems to work quite well I think, I will try it out with my main project. If overridingkarate.config.diris not supported and for internal use only I’m fine if you want to close this if the workaround works just as well.