AOEpeople / geb-spock-reports

Integrates Geb screenshots into the spock-reports library
Apache License 2.0
36 stars 11 forks source link

Unexpected error while creating report for label #34

Open transentia opened 3 years ago

transentia commented 3 years ago

I use gradle:

    testImplementation("com.athaydes:spock-reports:2.0-RC2") { transitive = false }
    testImplementation 'com.aoe:geb-spock-reports:0.3.0-RC1'

I run tests in batches, with the same test code each time, but different parameters for each batch. IE:

task test_batch1(type: Test) {
  systemProperty 'param', 'value1'

filter {
   includeTestsMatching 'my.test.Specs'
}
}

task test_batch2(type: Test) {
  systemProperty 'param', 'value2'

filter {
   includeTestsMatching 'my.test.Specs'
}
}
test.dependsOn test_batch1, test_batch2

All my tests are passing. They report no errors.

The problem is: when I run my tests (via "gradle test") a whole batch may or may not suffer the following:

Unexpected error while creating report for label '001-005-'Sparks' Reason For Call; Normal Path-sparksSafetyWarning: com.google.gson.JsonSyntaxException: com.google.gson.stream.MalformedJsonException: Use JsonReader.setLenient(true) to accept malformed JSON at line 419 column 8 path $.

in this case, no per-spec html files are produced and the index file shows no tests run.

It is apparently random as to when a batch will suffer the issue. If I run "gradle test" 5 times back-to-back (with "gradle clean" between each run) I may see: on run 1 both batches have good reports made; on run 2 batch 1 has a good report but batch 2 suffers the issue; on run 3 batch 1 suffers the issue but batch 2 has a good report generated; on run 4 batch 1 has a good report but batch 2 suffers the issue; on run 5 both batches have good reports made

The reports are very nice when they are made (thank you for the project, BTW!).

I have set:

    systemProperty 'com.athaydes.spockframework.report.aggregatedJsonReportDir', 'build/geb-spock-reports/_batch1'
    systemProperty 'com.athaydes.spockframework.report.outputDir', 'build/geb-spock-reports/_batch1'
    systemProperty 'geb.build.reportsDir', 'build/geb-spock-reports/_batch1'

Each batch has a separate directory, so I set '_batch1', '_batch2' as appropriate for each batch.

I also have resources/META-INF/services/com.athaydes.spockframework.report.IReportCreator.properties:

# output directory relative to working directory
#com.athaydes.spockframework.report.outputDir=build/geb-spock-reports

# let's use the TemplateReportCreator to utilize our custom template
com.athaydes.spockframework.report.IReportCreator=com.athaydes.spockframework.report.template.TemplateReportCreator

# if true, code blocks are shown
com.athaydes.spockframework.report.showCodeBlocks=false

# specific properties to the TemplateReportCreator
# see the mod suggested at: https://github.com/AOEpeople/geb-spock-reports/issues/27
#com.athaydes.spockframework.report.template.TemplateReportCreator.specTemplateFile=/templates/spec-template.html
com.athaydes.spockframework.report.template.TemplateReportCreator.specTemplateFile=/spec-template.html
com.athaydes.spockframework.report.template.TemplateReportCreator.reportFileExtension=html
com.athaydes.spockframework.report.template.TemplateReportCreator.summaryTemplateFile=/templates/summary-template.html
com.athaydes.spockframework.report.template.TemplateReportCreator.summaryFileName=index.html

# Set the name of the project under test so it can be displayed in the report or leave empty and it will be ignored
com.athaydes.spockframework.report.projectName=TCEQ

# Set the version of the project under test so it can be displayed in the report or leave empty and it will be ignored
com.athaydes.spockframework.report.projectVersion=

I note when a problem occurs, the 'aggregated_report.json' is completely empty.

More detailed logging:

Unexpected error while creating report for label '001-005-'Sparks' Reason For Call; Normal Path-sparksSafetyWarning: com.google.gson.JsonSyntaxException: com.google.gson.stream.MalformedJsonException: Use JsonReader.setLenient(true) to accept malformed JSON at line 419 column 8 path $.
Unexpected error while creating report for label '001-006-'Sparks' Reason For Call; Normal Path-sparksLocations: com.google.gson.JsonSyntaxException: com.google.gson.stream.MalformedJsonException: Use JsonReader.setLenient(true) to accept malformed JSON at line 419 column 8 path $.
Unexpected error while creating report for label '001-006-'Sparks' Reason For Call; Normal Path-sparksLocations: com.google.gson.JsonSyntaxException: com.google.gson.stream.MalformedJsonException: Use JsonReader.setLenient(true) to accept malformed JSON at line 419 column 8 path $.
Unexpected error while creating report for label '001-007-'Sparks' Reason For Call; Normal Path-sparksDimFlickeringCheck: com.google.gson.JsonSyntaxException: com.google.gson.stream.MalformedJsonException: Use JsonReader.setLenient(true) to accept malformed JSON at line 419 column 8 path $.
Unexpected error while creating report for label '001-007-'Sparks' Reason For Call; Normal Path-sparksDimFlickeringCheck: com.google.gson.JsonSyntaxException: com.google.gson.stream.MalformedJsonException: Use JsonReader.setLenient(true) to accept malformed JSON at line 419 column 8 path $.
Unexpected error while creating report for label '001-008-'Sparks' Reason For Call; Normal Path-incidentDetails: com.google.gson.JsonSyntaxException: com.google.gson.stream.MalformedJsonException: Use JsonReader.setLenient(true) to accept malformed JSON at line 419 column 8 path $.
Unexpected error while creating report for label '001-008-'Sparks' Reason For Call; Normal Path-incidentDetails: com.google.gson.JsonSyntaxException: com.google.gson.stream.MalformedJsonException: Use JsonReader.setLenient(true) to accept malformed JSON at line 419 column 8 path $.
Unexpected error while creating report for label '001-009-'Sparks' Reason For Call; Normal Path-dogAndAccessDetails: com.google.gson.JsonSyntaxException: com.google.gson.stream.MalformedJsonException: Use JsonReader.setLenient(true) to accept malformed JSON at line 419 column 8 path $.
Unexpected error while creating report for label '001-009-'Sparks' Reason For Call; Normal Path-dogAndAccessDetails: com.google.gson.JsonSyntaxException: com.google.gson.stream.MalformedJsonException: Use JsonReader.setLenient(true) to accept malformed JSON at line 419 column 8 path $.
Unexpected error while creating report for label '001-010-'Sparks' Reason For Call; Normal Path-Verify Main Form: com.google.gson.JsonSyntaxException: com.google.gson.stream.MalformedJsonException: Use JsonReader.setLenient(true) to accept malformed JSON at line 419 column 8 path $.
Unexpected error while creating report for label '001-010-'Sparks' Reason For Call; Normal Path-Verify Main Form: com.google.gson.JsonSyntaxException: com.google.gson.stream.MalformedJsonException: Use JsonReader.setLenient(true) to accept malformed JSON at line 419 column 8 path $.
Unexpected error while creating report for label '001-011-'Sparks' Reason For Call; Normal Path-Verify a Call Can be Logged: com.google.gson.JsonSyntaxException: com.google.gson.stream.MalformedJsonException: Use JsonReader.setLenient(true) to accept malformed JSON at line 419 column 8 path $.
Unexpected error while creating report for label '001-011-'Sparks' Reason For Call; Normal Path-Verify a Call Can be Logged: com.google.gson.JsonSyntaxException: com.google.gson.stream.MalformedJsonException: Use JsonReader.setLenient(true) to accept malformed JSON at line 419 column 8 path $.
[Test worker] WARN com.athaydes.spockframework.report.template.TemplateReportCreator - Unexpected error creating report
com.google.gson.JsonSyntaxException: com.google.gson.stream.MalformedJsonException: Use JsonReader.setLenient(true) to accept malformed JSON at line 419 column 8 path $
    at com.google.gson.Gson.assertFullConsumption(Gson.java:863)
    at com.google.gson.Gson.fromJson(Gson.java:826)
    at com.google.gson.Gson$fromJson$0.call(Unknown Source)
    at com.aoe.gebspockreports.GebReportUtils.readGebReport(GebReportUtils.groovy:76)
    at com.aoe.gebspockreports.GebReportUtils$readGebReport$3.call(Unknown Source)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:47)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:130)
    at groovy.tmp.templates.GStringTemplateScript1$_getTemplate_closure1.doCall(GStringTemplateScript1.groovy:26)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:78)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:567)
    at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:107)
    at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:323)
    at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:263)
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1035)
    at groovy.lang.Closure.call(Closure.java:412)
    at groovy.lang.Closure$WritableClosure.writeTo(Closure.java:912)
    at groovy.lang.Closure$WritableClosure.toString(Closure.java:1039)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:78)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:567)
    at org.codehaus.groovy.runtime.callsite.PlainObjectMetaMethodSite.doInvoke(PlainObjectMetaMethodSite.java:43)
    at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite$PogoCachedMethodSiteNoUnwrapNoCoerce.invoke(PogoMetaMethodSite.java:193)
    at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite.call(PogoMetaMethodSite.java:73)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:47)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:130)
    at com.athaydes.spockframework.report.template.TemplateReportCreator.reportFor(TemplateReportCreator.groovy:126)
    at com.athaydes.spockframework.report.template.TemplateReportCreator$reportFor.callCurrent(Unknown Source)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:51)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:171)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:185)
    at com.athaydes.spockframework.report.template.TemplateReportCreator.createReportFor(TemplateReportCreator.groovy:99)
    at com.athaydes.spockframework.report.IReportCreator$createReportFor.call(Unknown Source)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:47)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:139)
    at com.athaydes.spockframework.report.SpecInfoListener.afterSpec(SpockReportExtension.groovy:181)
    at org.spockframework.runtime.MasterRunListener.afterSpec(MasterRunListener.java:64)
    at org.spockframework.runtime.MasterRunSupervisor.afterSpec(MasterRunSupervisor.java:128)
    at org.spockframework.runtime.PlatformSpecRunner.runCleanupSpec(PlatformSpecRunner.java:155)
    at org.spockframework.runtime.SpecNode.after(SpecNode.java:55)
    at org.spockframework.runtime.SpecNode.after(SpecNode.java:11)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:149)
    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:149)
    at org.spockframework.runtime.SpockNode.sneakyInvoke(SpockNode.java:40)
    at org.spockframework.runtime.SpecNode.lambda$around$0(SpecNode.java:63)
    at org.spockframework.runtime.PlatformSpecRunner.lambda$createMethodInfoForDoRunSpec$0(PlatformSpecRunner.java:62)
    at org.spockframework.runtime.model.MethodInfo.invoke(MethodInfo.java:136)
    at org.spockframework.runtime.PlatformSpecRunner.invokeRaw(PlatformSpecRunner.java:406)
    at org.spockframework.runtime.PlatformSpecRunner.invoke(PlatformSpecRunner.java:389)
    at org.spockframework.runtime.PlatformSpecRunner.runSpec(PlatformSpecRunner.java:56)
    at org.spockframework.runtime.SpecNode.around(SpecNode.java:63)
    at org.spockframework.runtime.SpecNode.around(SpecNode.java:11)
    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 java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:143)
    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.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:108)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:96)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:75)
    at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.processAllTestClasses(JUnitPlatformTestClassProcessor.java:99)
    at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.access$000(JUnitPlatformTestClassProcessor.java:79)
    at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor.stop(JUnitPlatformTestClassProcessor.java:75)
    at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.stop(SuiteTestClassProcessor.java:61)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:78)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:567)
    at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
    at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
    at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
    at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)
    at jdk.proxy1/jdk.proxy1.$Proxy2.stop(Unknown Source)
    at org.gradle.api.internal.tasks.testing.worker.TestWorker.stop(TestWorker.java:135)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:78)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:567)
    at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
    at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
    at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:182)
    at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:164)
    at org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:414)
    at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
    at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:48)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630)
    at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:56)
    at java.base/java.lang.Thread.run(Thread.java:831)
Caused by: com.google.gson.stream.MalformedJsonException: Use JsonReader.setLenient(true) to accept malformed JSON at line 419 column 8 path $
    at com.google.gson.stream.JsonReader.syntaxError(JsonReader.java:1559)
    at com.google.gson.stream.JsonReader.checkLenient(JsonReader.java:1401)
    at com.google.gson.stream.JsonReader.doPeek(JsonReader.java:542)
    at com.google.gson.stream.JsonReader.peek(JsonReader.java:425)
    at com.google.gson.Gson.assertFullConsumption(Gson.java:859)
    ... 110 more

Any thoughts/suggestions gratefully accepted.

transentia commented 2 years ago

I hopefully upgraded to:

    testImplementation('com.athaydes:spock-reports:2.3.0-groovy-3.0') { transitive = false }

    testImplementation group: 'com.google.code.gson', name: 'gson', version: '2.9.0'

Also

# dependency versions
GROOVY_VERSION = 3.0.10
GEB_VERSION = 5.1
SELENIUM_VERSION = 4.1.2
SLF4J_VERSION = 1.7.36
SPOCK_VERSION = 2.1-groovy-3.0

Still getting the same outcome as before, if trying to run in parallel:

CHROME driver created(using Profile 'Default')
Business: ENERGEX
Configuration Properties for tce.flows.eq.ExplosionOrLoudNoiseReasonForCallSpec3@2ef0dd86:
FULL URL: http://localhost:8080/DDA/ENERGEX?csoLoginId=guest&NMI=QB13530496
access_details = Next door to the pub, by the camel pens.
covid = Not Applicable
address = 1 INDUS ST,CAMP HILL,4152
incident_details = Was having some nice 'roo steaks. BBQ got out of hand...
warnings = Warnings[explosionOrLoudNoiseReportSafety]: ADVISED
title = Trouble Call Entry
reason_for_call = Explosion/Loud Noise
url = /DDA/ENERGEX?csoLoginId=guest&NMI=QB13530496
access_details_available_space = 123
caller = Customer
incident_details_available_space = 199
reason_for_call_select_combo_value = Explosion/Loud Noise Report
flow_history = EXPLOSION --> LoudNoiseLocation:PILLAR -- WiresAreExposed:NO
call_type = explosionOrLoudNoiseReport
dog = Not Applicable
noise_location = Pillar
Unexpected error while creating report for label '001-001-'Explosion Or Loud Noise' Reason For Call; Pillar with wires exposed No path-Go to http://localhost:8080/DDA/ENERGEX?csoLoginId=guest&NMI=QB13530496: com.google.gson.JsonSyntaxException: com.google.gson.stream.MalformedJsonException: Use JsonReader.setLenient(true) to accept malformed JSON at line 1086 column 3 path $.
Unexpected error while creating report for label '001-002-'Explosion Or Loud Noise' Reason For Call; Pillar with wires exposed No path-addressCheck: com.google.gson.JsonSyntaxException: com.google.gson.stream.MalformedJsonException: Use JsonReader.setLenient(true) to accept malformed JSON at line 1086 column 3 path $.
Unexpected error while creating report for label '001-003-'Explosion Or Loud Noise' Reason For Call; Pillar with wires exposed No path-contactDetailsCheck: com.google.gson.JsonSyntaxException: com.google.gson.stream.MalformedJsonException: Use JsonReader.setLenient(true) to accept malformed JSON at line 1086 column 3 path $.
Unexpected error while creating report for label '001-004-'Explosion Or Loud Noise' Reason For Call; Pillar with wires exposed No path-reasonForCall: com.google.gson.JsonSyntaxException: com.google.gson.stream.MalformedJsonException: Use JsonReader.setLenient(true) to accept malformed JSON at line 1086 column 3 path $.
Unexpected error while creating report for label '001-005-'Explosion Or Loud Noise' Reason For Call; Pillar with wires exposed No path-explosionOrLoudNoiseReportSafetyWarning: com.google.gson.JsonSyntaxException: com.google.gson.stream.MalformedJsonException: Use JsonReader.setLenient(true) to accept malformed JSON at line 1086 column 3 path $.
Unexpected error while creating report for label '001-006-'Explosion Or Loud Noise' Reason For Call; Pillar with wires exposed No path-explosionOrLoudNoiseReport: com.google.gson.JsonSyntaxException: com.google.gson.stream.MalformedJsonException: Use JsonReader.setLenient(true) to accept malformed JSON at line 1086 column 3 path $.
Unexpected error while creating report for label '001-007-'Explosion Or Loud Noise' Reason For Call; Pillar with wires exposed No path-explosionWiresExposed: com.google.gson.JsonSyntaxException: com.google.gson.stream.MalformedJsonException: Use JsonReader.setLenient(true) to accept malformed JSON at line 1086 column 3 path $.
Unexpected error while creating report for label '001-008-'Explosion Or Loud Noise' Reason For Call; Pillar with wires exposed No path-incidentDetails: com.google.gson.JsonSyntaxException: com.google.gson.stream.MalformedJsonException: Use JsonReader.setLenient(true) to accept malformed JSON at line 1086 column 3 path $.
Unexpected error while creating report for label '001-009-'Explosion Or Loud Noise' Reason For Call; Pillar with wires exposed No path-dogAndAccessDetails: com.google.gson.JsonSyntaxException: com.google.gson.stream.MalformedJsonException: Use JsonReader.setLenient(true) to accept malformed JSON at line 1086 column 3 path $.
Unexpected error while creating report for label '001-010-'Explosion Or Loud Noise' Reason For Call; Pillar with wires exposed No path-Verify Main Form: com.google.gson.JsonSyntaxException: com.google.gson.stream.MalformedJsonException: Use JsonReader.setLenient(true) to accept malformed JSON at line 1086 column 3 path $.
Unexpected error while creating report for label '001-011-'Explosion Or Loud Noise' Reason For Call; Pillar with wires exposed No path-Verify a Call Can be Logged: com.google.gson.JsonSyntaxException: com.google.gson.stream.MalformedJsonException: Use JsonReader.setLenient(true) to accept malformed JSON at line 1086 column 3 path $.
Unexpected error while creating report for label '001-012-'Explosion Or Loud Noise' Reason For Call; Pillar with wires exposed No path-end: com.google.gson.JsonSyntaxException: com.google.gson.stream.MalformedJsonException: Use JsonReader.setLenient(true) to accept malformed JSON at line 1086 column 3 path $.
[Test worker] WARN com.athaydes.spockframework.report.template.TemplateReportCreator - Unexpected error creating report
com.google.gson.JsonSyntaxException: com.google.gson.stream.MalformedJsonException: Use JsonReader.setLenient(true) to accept malformed JSON at line 1086 column 3 path $
    at com.google.gson.Gson.assertFullConsumption(Gson.java:967)
    at com.google.gson.Gson.fromJson(Gson.java:930)
    at com.google.gson.Gson$fromJson.call(Unknown Source)
    at com.aoe.gebspockreports.GebReportUtils.readGebReport(GebReportUtils.groovy:76)
    at com.aoe.gebspockreports.GebReportUtils$readGebReport$0.call(Unknown Source)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:47)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:130)
    at groovy.tmp.templates.GStringTemplateScript1$_getTemplate_closure1.doCall(GStringTemplateScript1.groovy:26)
    at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
    at java.base/java.lang.reflect.Method.invoke(Method.java:577)
    at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:107)
    at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:323)
    at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:274)
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1035)
    at groovy.lang.Closure.call(Closure.java:412)
    at groovy.lang.Closure$WritableClosure.writeTo(Closure.java:912)
    at groovy.lang.Closure$WritableClosure.toString(Closure.java:1039)
    at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
    at java.base/java.lang.reflect.Method.invoke(Method.java:577)
    at org.codehaus.groovy.runtime.callsite.PlainObjectMetaMethodSite.doInvoke(PlainObjectMetaMethodSite.java:43)
    at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite$PogoCachedMethodSiteNoUnwrapNoCoerce.invoke(PogoMetaMethodSite.java:193)
    at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite.call(PogoMetaMethodSite.java:73)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:47)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:130)
    at com.athaydes.spockframework.report.template.TemplateReportCreator.reportFor(TemplateReportCreator.groovy:126)
    at com.athaydes.spockframework.report.template.TemplateReportCreator$reportFor.callCurrent(Unknown Source)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:51)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:171)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:185)
    at com.athaydes.spockframework.report.template.TemplateReportCreator.createReportFor(TemplateReportCreator.groovy:99)
    at com.athaydes.spockframework.report.IReportCreator$createReportFor.call(Unknown Source)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:47)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:139)
    at com.athaydes.spockframework.report.SpecInfoListener.createReport(SpockReportExtension.groovy:283)
    at com.athaydes.spockframework.report.SpecInfoListener.afterSpec(SpockReportExtension.groovy:194)
    at org.spockframework.runtime.MasterRunListener.afterSpec(MasterRunListener.java:64)
    at org.spockframework.runtime.MasterRunSupervisor.afterSpec(MasterRunSupervisor.java:128)
    at org.spockframework.runtime.PlatformSpecRunner.runSpec(PlatformSpecRunner.java:56)
    at org.spockframework.runtime.SpecNode.around(SpecNode.java:63)
    at org.spockframework.runtime.SpecNode.around(SpecNode.java:11)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:107)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
    at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
    at org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:53)
    at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.processAllTestClasses(JUnitPlatformTestClassProcessor.java:99)
    at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.access$000(JUnitPlatformTestClassProcessor.java:79)
    at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor.stop(JUnitPlatformTestClassProcessor.java:75)
    at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.stop(SuiteTestClassProcessor.java:61)
    at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
    at java.base/java.lang.reflect.Method.invoke(Method.java:577)
    at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
    at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
    at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
    at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)
    at jdk.proxy1/jdk.proxy1.$Proxy2.stop(Unknown Source)
    at org.gradle.api.internal.tasks.testing.worker.TestWorker$3.run(TestWorker.java:193)
    at org.gradle.api.internal.tasks.testing.worker.TestWorker.executeAndMaintainThreadName(TestWorker.java:129)
    at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:100)
    at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:60)
    at org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:56)
    at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:133)
    at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:71)
    at worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69)
    at worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74)
Caused by: com.google.gson.stream.MalformedJsonException: Use JsonReader.setLenient(true) to accept malformed JSON at line 1086 column 3 path $
    at com.google.gson.stream.JsonReader.syntaxError(JsonReader.java:1597)
    at com.google.gson.stream.JsonReader.checkLenient(JsonReader.java:1404)
    at com.google.gson.stream.JsonReader.doPeek(JsonReader.java:542)
    at com.google.gson.stream.JsonReader.peek(JsonReader.java:425)
    at com.google.gson.Gson.assertFullConsumption(Gson.java:963)
    ... 88 more
[Test worker] WARN com.athaydes.spockframework.report.internal.ConfigLoader - Invalid property value for property 'testSourceRoots'
[Test worker] INFO com.athaydes.spockframework.report.SpockReportExtension - Got configuration from Spock: com.athaydes.spockframework.report.internal.SpockReportsConfiguration([:])
[Test worker] INFO com.athaydes.spockframework.report.internal.ConfigLoader - SpockReports config loaded: {com.athaydes.spockframework.report.projectVersion=UNDEFINED, com.athaydes.spockframework.report.aggregatedJsonReportDir=build/geb-spock-reports/ENERGEX, com.athaydes.spockframework.report.template.TemplateReportCreator.enabled=true, com.athaydes.spockframework.report.internal.HtmlReportCreator.printThrowableStackTrace=false, com.athaydes.spockframework.report.template.TemplateReportCreator.specTemplateFile=/geb-spock-reports/spec-template.html, com.athaydes.spockframework.report.template.TemplateReportCreator.reportFileExtension=html, com.athaydes.spockframework.report.hideEmptyBlocks=false, com.athaydes.spockframework.report.template.TemplateReportCreator.summaryTemplateFile=/templates/summary-template.html, com.athaydes.spockframework.report.template.TemplateReportCreator.summaryFileName=index.html, com.athaydes.spockframework.report.internal.HtmlReportCreator.enabled=true, com.athaydes.spockframework.report.outputDir=build/geb-spock-reports/ENERGEX, com.athaydes.spockframework.report.projectName=TCEQ, com.athaydes.spockframework.report.showCodeBlocks=false, com.athaydes.spockframework.report.internal.HtmlReportCreator.specSummaryNameOption=class_name_and_title, com.athaydes.spockframework.report.internal.HtmlReportCreator.inlineCss=true, com.athaydes.spockframework.report.internal.HtmlReportCreator.featureReportCss=spock-feature-report.css, com.athaydes.spockframework.report.testSourceRoots=src/test/groovy, com.athaydes.spockframework.report.internal.HtmlReportCreator.summaryReportCss=spock-summary-report.css, com.athaydes.spockframework.report.internal.HtmlReportCreator.excludeToc=false, com.athaydes.spockframework.report.IReportCreator=com.athaydes.spockframework.report.template.TemplateReportCreator}
[Test worker] WARN com.athaydes.spockframework.report.internal.ConfigLoader - Invalid property value for property 'testSourceRoots'
[Test worker] INFO com.athaydes.spockframework.report.template.TemplateReportAggregator - Writing summary report to D:\DEV\EQ\TCEQTests\build\geb-spock-reports\ENERGEX\index.html
[org.spockframework.runtime.RunContext.stop()] INFO com.athaydes.spockframework.report.template.TemplateReportAggregator - Writing summary report to D:\DEV\EQ\TCEQTests\build\geb-spock-reports\ENERGEX\index.html
[AsyncHttpClient-1-4] WARN org.asynchttpclient.netty.handler.WebSocketHandler - onError
java.net.SocketException: Connection reset
    at java.base/sun.nio.ch.SocketChannelImpl.throwConnectionReset(SocketChannelImpl.java:394)
    at java.base/sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:426)
    at io.netty.buffer.PooledByteBuf.setBytes(PooledByteBuf.java:258)
    at io.netty.buffer.AbstractByteBuf.writeBytes(AbstractByteBuf.java:1132)
    at io.netty.channel.socket.nio.NioSocketChannel.doReadBytes(NioSocketChannel.java:350)
    at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:151)
    at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:722)
    at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:658)
    at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:584)
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:496)
    at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:986)
    at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
    at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
    at java.base/java.lang.Thread.run(Thread.java:833)
[Test worker] INFO com.athaydes.spockframework.report.template.TemplateReportAggregator - Writing summary report to D:\DEV\EQ\TCEQTests\build\geb-spock-reports\ENERGEX\index.html
[Test worker] INFO com.athaydes.spockframework.report.SpockReportExtension - Got configuration from Spock: com.athaydes.spockframework.report.internal.SpockReportsConfiguration([:])
[Test worker] INFO com.athaydes.spockframework.report.internal.ConfigLoader - SpockReports config loaded: {com.athaydes.spockframework.report.projectVersion=UNDEFINED, com.athaydes.spockframework.report.aggregatedJsonReportDir=build/geb-spock-reports/ENERGEX, com.athaydes.spockframework.report.template.TemplateReportCreator.enabled=true, com.athaydes.spockframework.report.internal.HtmlReportCreator.printThrowableStackTrace=false, com.athaydes.spockframework.report.template.TemplateReportCreator.specTemplateFile=/geb-spock-reports/spec-template.html, com.athaydes.spockframework.report.template.TemplateReportCreator.reportFileExtension=html, com.athaydes.spockframework.report.hideEmptyBlocks=false, com.athaydes.spockframework.report.template.TemplateReportCreator.summaryTemplateFile=/templates/summary-template.html, com.athaydes.spockframework.report.template.TemplateReportCreator.summaryFileName=index.html, com.athaydes.spockframework.report.internal.HtmlReportCreator.enabled=true, com.athaydes.spockframework.report.outputDir=build/geb-spock-reports/ENERGEX, com.athaydes.spockframework.report.projectName=TCEQ, com.athaydes.spockframework.report.showCodeBlocks=false, com.athaydes.spockframework.report.internal.HtmlReportCreator.specSummaryNameOption=class_name_and_title, com.athaydes.spockframework.report.internal.HtmlReportCreator.inlineCss=true, com.athaydes.spockframework.report.internal.HtmlReportCreator.featureReportCss=spock-feature-report.css, com.athaydes.spockframework.report.testSourceRoots=src/test/groovy, com.athaydes.spockframework.report.internal.HtmlReportCreator.summaryReportCss=spock-summary-report.css, com.athaydes.spockframework.report.internal.HtmlReportCreator.excludeToc=false, com.athaydes.spockframework.report.IReportCreator=com.athaydes.spockframework.report.template.TemplateReportCreator}
[org.spockframework.runtime.RunContext.stop()] INFO com.athaydes.spockframework.report.template.TemplateReportAggregator - Writing summary report to D:\DEV\EQ\TCEQTests\build\geb-spock-reports\ENERGEX\index.html
[AsyncHttpClient-1-4] WARN org.asynchttpclient.netty.handler.WebSocketHandler - onError
java.net.SocketException: Connection reset
    at java.base/sun.nio.ch.SocketChannelImpl.throwConnectionReset(SocketChannelImpl.java:394)
    at java.base/sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:426)
    at io.netty.buffer.PooledByteBuf.setBytes(PooledByteBuf.java:258)
    at io.netty.buffer.AbstractByteBuf.writeBytes(AbstractByteBuf.java:1132)
    at io.netty.channel.socket.nio.NioSocketChannel.doReadBytes(NioSocketChannel.java:350)
    at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:151)
    at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:722)
    at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:658)
    at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:584)
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:496)
    at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:986)
    at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
    at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
    at java.base/java.lang.Thread.run(Thread.java:833)
[Test worker] WARN com.athaydes.spockframework.report.internal.ConfigLoader - Invalid property value for property 'testSourceRoots'
transentia commented 2 years ago

Also, sometimes, I get a partial report, ie:

image

104 tests successfully executed in parallel, 2 reported on :-(

The aggregated_report.json file is (in total):

{
  "tce.flows.eq.CardOperatedMeterFaultReasonForCallSpec7": {
    "executedFeatures": [
      "'Card Operated Meter Fault' Reason For Call; Maintain Meter Path"
    ],
    "ignoredFeatures": [],
    "stats": {
      "failures": 0,
      "errors": 0,
      "skipped": 0,
      "totalRuns": 1,
      "totalFeatures": 1,
      "passed": 1,
      "successRate": 1.0,
      "time": 20323
    },
    "title": "Card Operated Meter Fault Reason For Call",
    "narrative": "As a COO\nI want to exercise the 'Card Operated Meter Fault' Reason for Call\nSo that I can log an accurate 'Card Operated Meter Fault' call on behalf of the caller"
  },
  "tce.flows.eq.ENERGEX_LossOfSupplyReasonForCallSpec11": {
    "executedFeatures": [
      "'Loss Of Supply' Reason For Call; Existing call in Pon"
    ],
    "ignoredFeatures": [],
    "stats": {
      "failures": 0,
      "errors": 0,
      "skipped": 0,
      "totalRuns": 1,
      "totalFeatures": 1,
      "passed": 1,
      "successRate": 1.0,
      "time": 10156
    },
    "title": "Loss Of Supply Reason For Call",
    "narrative": "REQUIRES AN EXISTING CALL IN PON ON QB04958659\nAs a COO\nI want to exercise the 'Loss Of Supply' Reason for Call\nSo that I can log an accurate 'Loss Of Supply' call on behalf of the caller"
  }
}
transentia commented 2 years ago

Been doing some more unsuccessful debugging.

1. I can see that com.aoe.gebspockreports.GebReportUtils#readGebReport attempts to parse bad JSON.

A document always has extra chars at end, such as:

}         ]
        }
      ],
      "unassignedArtifacts": []
    }
  ]
}
}  ]
}
}   "tce\\flows\\eq\\TreeReasonForCallSpec4\\001-003-_Tree__Reason_For_Call__Other-reasonForCall.png"
]
}
]
}
],
"unassignedArtifacts": []
}
]
}

In each case, the document SHOULD end with that first '}' but there are extra chars. Can't work out how that gets there...I can't see anything obvious like a buffer that is being reused.

I've tried fiddling with writeGebReport/readGebReport, eg:

    static synchronized void writeGebReport(GebReport gebReport) {
        def gebReportFile = new File(GEB_CONF.reportsDir.path, GEB_REPORT_JSON_FILE)

        gebReportFile.delete()

        // gebReportFile.write(gson.toJson(gebReport))

        try (FileOutputStream file = new FileOutputStream(gebReportFile)
             FileChannel channel = file.getChannel()
             FileLock fileLock = channel.lock()) {
            file.write(gson.toJson(gebReport).getBytes(StandardCharsets.UTF_8))
        }
    }

    static synchronized GebReport readGebReport() {
        def gebReportFile = new File(GEB_CONF.reportsDir.path, GEB_REPORT_JSON_FILE)

        // gebReportFile.exists() ? gson.fromJson(new FileReader(gebReportFile), GebReport.class) : new GebReport()

        if (gebReportFile.exists())
            try (RandomAccessFile file = new RandomAccessFile(gebReportFile, "rw");
                 FileChannel channel = file.getChannel();
                 FileLock fileLock = channel.lock()) {
                file.seek(0);

                byte[] ba = new byte[file.length()];
                file.readFully(ba)
                def s = new String(ba)

                try {
                    return gson.fromJson(s, GebReport.class)
                } catch (JsonSyntaxException e) {
                    println "JsonSyntaxException; message: '${e.message}'"
                    e.printStackTrace()

                    println "BAD READ: buf: ${s}"
                    def m = e.message =~ /line\s*(?<line>\d+)/
                    if (m) {
                        def line = m.group('line').toInteger()

                        println "*** line: ${line}"

                        s = s.readLines()[0..<(line - 1)].join('\n') + '}'

                        println "JsonSyntaxException RETRY S: ${s}"
                        try {
                            return gson.fromJson(s, GebReport.class)
                        } catch (JsonSyntaxException exx) {
                            println "JsonSyntaxException CONT with empty GebReport"
                            return new GebReport()
                        }
                    }
                } catch (Exception eee) {
                    println "Exception; message: '${eee.message}'"
                    eee.printStackTrace()

                    println "BAD READ: buf: ${s}"

                    def lines = s.readLines()
                    def nlines = []
                    for (String l in lines) {
                        if (l.matches(/^}.*$/)) {
                            nlines << '}'
                            break;
                        }
                        nlines << l
                    }
                    s = nlines.join('\n')
                    println "Exception RETRY S: ${s}"
                    try {
                        return gson.fromJson(s, GebReport.class)
                    } catch (JsonSyntaxException exx) {
                        println "Exception CONT with empty GebReport"
                        return new GebReport()
                    }
                }
            }
        else
            return new GebReport()
    }

Such Heath Robinson-ish horridness!

I'm trying to put aside my shame/sense of embarrasment, I'm trying anything that might affect synchronisation...;-)

2. I also note that each time this happens, some entry/entries are missing...I can see an image has been taken, but not referenced in the string that is being parsed.

I can compensate for 1. by throwing away the extra chars and re-parsing the resulting string. (treating the symptom, rather than the cause but...hey medical doctors do this all the time ;-)) Sadly, I still end up with (partially) a rubbish report 'cos of 2. Sigh.

renatoathaydes commented 2 years ago

Do you still see this issue if you ask Gradle to run the tests without any concurrency?