Skip to content

Commit f2daad6

Browse files
committed
Fixed initialization loop and some thread issues
1 parent 9303f6b commit f2daad6

11 files changed

Lines changed: 255 additions & 142 deletions

File tree

Ports/JavaScriptPort/src/main/java/com/codename1/impl/html5/HTML5Implementation.java

Lines changed: 1 addition & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -7469,44 +7469,13 @@ public InputStream getArrayBufferInputStream(String url){
74697469
return out;
74707470
}
74717471
final XMLHttpRequest req = XMLHttpRequest.create();
7472-
final Object lock = new Object();
7473-
final boolean[] complete = new boolean[1];
74747472
if (url.indexOf("assets/") == 0 && url.indexOf("?") == -1) {
74757473
url = url + "?v=" + getBuildVersion();
74767474
}
7477-
req.open("get", url, true);
7478-
req.setOnReadyStateChange(new ReadyStateChangeHandler() {
7479-
7480-
@Override
7481-
public void stateChanged() {
7482-
if ( req.getReadyState() == XMLHttpRequest.DONE ){
7483-
7484-
new Thread() {
7485-
@Override
7486-
public void run() {
7487-
complete[0]=true;
7488-
synchronized(lock){
7489-
lock.notifyAll();
7490-
}
7491-
}
7492-
}.start();
7493-
}
7494-
}
7495-
});
7475+
req.open("get", url, false);
74967476
req.setResponseType("arraybuffer");
7497-
74987477
req.send();
74997478

7500-
while (!complete[0]){
7501-
synchronized(lock){
7502-
try {
7503-
lock.wait();
7504-
} catch (InterruptedException ex) {
7505-
//Log.e(ex);
7506-
}
7507-
}
7508-
}
7509-
75107479
if (req.getResponse() == null ){
75117480
System.out.println(req.getAllResponseHeaders());
75127481
System.out.println(req.getStatusText());

Ports/JavaScriptPort/src/main/java/com/codename1/impl/html5/JavaScriptPortBootstrap.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public static void bootstrap(Lifecycle lifecycle) {
2525
com.codename1.impl.ImplementationFactory.setInstance(new com.codename1.impl.ImplementationFactory());
2626
JavaScriptPortBootstrap bootstrap = new JavaScriptPortBootstrap(lifecycle);
2727
Display.init(bootstrap);
28-
Display.getInstance().callSerially(bootstrap);
28+
bootstrap.run();
2929
}
3030

3131
public static Lifecycle createLifecycle(String className) {

Ports/JavaScriptPort/src/main/java/com/codename1/impl/html5/NetworkConnection.java

Lines changed: 1 addition & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ private static interface XHRBlob extends JSObject {
7272
private void open(){
7373
if (!isOpen){
7474
isOpen = true;
75-
req.open(httpMethod, url, true);
75+
req.open(httpMethod, url, false);
7676
req.setResponseType("arraybuffer");
7777
}
7878
}
@@ -124,32 +124,10 @@ public InputStream openInputStream() throws IOException {
124124
return inputStream;
125125
}
126126

127-
final Object lock = new Object();
128127
open();
129128
for (Header h : headers) {
130129
req.setRequestHeader(h.name, h.value);
131130
}
132-
final boolean[] complete = new boolean[1];
133-
req.setOnReadyStateChange(new ReadyStateChangeHandler(){
134-
135-
@Override
136-
public void stateChanged() {
137-
138-
if ( req.getReadyState() == XMLHttpRequest.DONE){
139-
new Thread() {
140-
@Override
141-
public void run() {
142-
143-
complete[0] = true;
144-
synchronized (lock){
145-
lock.notifyAll();
146-
}
147-
}
148-
}.start();
149-
}
150-
}
151-
152-
});
153131
//req.setResponseType("arraybuffer");
154132
if ( body != null ){
155133

@@ -158,15 +136,6 @@ public void run() {
158136
} else {
159137
req.send();
160138
}
161-
if (!complete[0]){
162-
synchronized(lock){
163-
try {
164-
lock.wait(timeout);
165-
} catch (InterruptedException ex) {
166-
Log.e(ex);
167-
}
168-
}
169-
}
170139

171140

172141
if (req.getResponse() == null || req.getStatus() == 0 ){

Ports/JavaScriptPort/src/main/java/com/codename1/impl/html5/ParparVMBootstrap.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ public static void bootstrap(Lifecycle lifecycle) {
2727
// For ParparVM, native bindings are provided by parparvm_runtime.js
2828
ParparVMBootstrap bootstrap = new ParparVMBootstrap(lifecycle);
2929
Display.init(bootstrap);
30-
Display.getInstance().callSerially(bootstrap);
30+
bootstrap.run();
3131
}
3232

3333
@Override
@@ -39,4 +39,4 @@ public void run() {
3939
Log.e(t);
4040
}
4141
}
42-
}
42+
}

scripts/hellocodenameone/common/src/main/java/com/codenameone/examples/hellocodenameone/tests/BaseTest.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,7 @@ protected Form createForm(String title, Layout layout, final String imageName) {
3434
@Override
3535
protected void onShowCompleted() {
3636
registerReadyCallback(this, () -> {
37-
Cn1ssDeviceRunnerHelper.emitCurrentFormScreenshot(imageName);
38-
done();
37+
Cn1ssDeviceRunnerHelper.emitCurrentFormScreenshot(imageName, BaseTest.this::done);
3938
});
4039
}
4140
};
@@ -53,4 +52,4 @@ protected synchronized void done() {
5352
public synchronized boolean isDone() {
5453
return done;
5554
}
56-
}
55+
}

scripts/hellocodenameone/common/src/main/java/com/codenameone/examples/hellocodenameone/tests/Cn1ssDeviceRunner.java

Lines changed: 48 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package com.codenameone.examples.hellocodenameone.tests;
22

3-
import com.codename1.io.Util;
43
import com.codename1.testing.DeviceRunner;
54
import com.codename1.testing.TestReporting;
65
import com.codename1.ui.CN;
@@ -39,6 +38,9 @@
3938
import java.util.List;
4039

4140
public final class Cn1ssDeviceRunner extends DeviceRunner {
41+
private static final int TEST_TIMEOUT_MS = 30000;
42+
private static final int TEST_POLL_INTERVAL_MS = 50;
43+
4244
private static final List<BaseTest> TEST_CLASSES = new ArrayList<>(Arrays.asList(
4345
new MainScreenScreenshotTest(),
4446
new DrawLine(),
@@ -102,35 +104,59 @@ public void runSuite() {
102104
}
103105
});
104106
});
105-
for (BaseTest testClass : TEST_CLASSES) {
106-
final String testName = testClass.getClass().getSimpleName();
107-
CN.callSerially(() -> {
108-
log("CN1SS:INFO:suite starting test=" + testName);
109-
try {
110-
testClass.prepare();
111-
testClass.runTest();
112-
} catch (Throwable t) {
113-
log("CN1SS:ERR:suite test=" + testName + " failed=" + t);
114-
t.printStackTrace();
115-
}
116-
});
117-
int timeout = 30000;
118-
while (!testClass.isDone() && timeout > 0) {
119-
Util.sleep(3);
120-
timeout -= 3;
107+
runNextTest(0);
108+
}
109+
110+
private void runNextTest(int index) {
111+
if (index >= TEST_CLASSES.size()) {
112+
finishSuite();
113+
return;
114+
}
115+
BaseTest testClass = TEST_CLASSES.get(index);
116+
String testName = testClass.getClass().getSimpleName();
117+
CN.callSerially(() -> {
118+
log("CN1SS:INFO:suite starting test=" + testName);
119+
try {
120+
testClass.prepare();
121+
testClass.runTest();
122+
} catch (Throwable t) {
123+
log("CN1SS:ERR:suite test=" + testName + " failed=" + t);
124+
t.printStackTrace();
125+
testClass.fail(String.valueOf(t));
121126
}
127+
awaitTestCompletion(index, testClass, testName, System.currentTimeMillis() + TEST_TIMEOUT_MS);
128+
});
129+
}
130+
131+
private void awaitTestCompletion(int index, BaseTest testClass, String testName, long deadline) {
132+
if (testClass.isDone()) {
133+
finalizeTest(index, testClass, testName, false);
134+
return;
135+
}
136+
if (System.currentTimeMillis() >= deadline) {
137+
finalizeTest(index, testClass, testName, true);
138+
return;
139+
}
140+
CN.setTimeout(TEST_POLL_INTERVAL_MS, () -> awaitTestCompletion(index, testClass, testName, deadline));
141+
}
142+
143+
private void finalizeTest(int index, BaseTest testClass, String testName, boolean timedOut) {
144+
try {
122145
testClass.cleanup();
123-
if(timeout == 0) {
146+
if (timedOut) {
124147
log("CN1SS:ERR:suite test=" + testName + " failed due to timeout waiting for DONE");
125148
} else if (testClass.isFailed()) {
126149
log("CN1SS:ERR:suite test=" + testName + " failed: " + testClass.getFailMessage());
127-
} else {
128-
if (!testClass.shouldTakeScreenshot()) {
129-
log("CN1SS:INFO:test=" + testName + " screenshot=none");
130-
}
150+
} else if (!testClass.shouldTakeScreenshot()) {
151+
log("CN1SS:INFO:test=" + testName + " screenshot=none");
131152
}
132153
log("CN1SS:INFO:suite finished test=" + testName);
154+
} finally {
155+
runNextTest(index + 1);
133156
}
157+
}
158+
159+
private void finishSuite() {
134160
log("CN1SS:SUITE:FINISHED");
135161
TestReporting.getInstance().testExecutionFinished(getClass().getName());
136162
if (CN.isSimulator()) {

scripts/hellocodenameone/common/src/main/java/com/codenameone/examples/hellocodenameone/tests/Cn1ssDeviceRunnerHelper.java

Lines changed: 53 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -24,65 +24,67 @@ static void runOnEdtSync(Runnable runnable) {
2424
Display display = Display.getInstance();
2525
if (display.isEdt()) {
2626
runnable.run();
27+
} else if (isHtml5()) {
28+
display.callSerially(runnable);
2729
} else {
2830
display.callSeriallyAndWait(runnable);
2931
}
3032
}
3133

3234
static void emitCurrentFormScreenshot(String testName) {
35+
emitCurrentFormScreenshot(testName, null);
36+
}
37+
38+
static void emitCurrentFormScreenshot(String testName, Runnable onComplete) {
3339
String safeName = sanitizeTestName(testName);
3440
Form current = Display.getInstance().getCurrent();
3541
if (current == null) {
3642
println("CN1SS:ERR:test=" + safeName + " message=Current form is null");
3743
println("CN1SS:END:" + safeName);
44+
complete(onComplete);
45+
return;
3846
}
3947
int width = Math.max(1, current.getWidth());
4048
int height = Math.max(1, current.getHeight());
41-
Image[] img = new Image[1];
42-
Display.getInstance().screenshot(screen -> img[0] = screen);
43-
long time = System.currentTimeMillis();
44-
Display.getInstance().invokeAndBlock(() -> {
45-
while(img[0] == null) {
46-
Util.sleep(50);
47-
// timeout
48-
if (System.currentTimeMillis() - time > 2000) {
49+
Display.getInstance().screenshot(screen -> {
50+
if (screen == null) {
51+
println("CN1SS:ERR:test=" + safeName + " message=Screenshot callback returned null");
52+
println("CN1SS:END:" + safeName);
53+
complete(onComplete);
54+
return;
55+
}
56+
Image screenshot = screen;
57+
try {
58+
ImageIO io = ImageIO.getImageIO();
59+
if (io == null || !io.isFormatSupported(ImageIO.FORMAT_PNG)) {
60+
println("CN1SS:ERR:test=" + safeName + " message=PNG encoding unavailable");
61+
println("CN1SS:END:" + safeName);
4962
return;
5063
}
51-
}
52-
});
53-
if (img[0] == null) {
54-
println("CN1SS:ERR:test=" + safeName + " message=Screenshot process timed out");
55-
println("CN1SS:END:" + safeName);
56-
}
57-
Image screenshot = img[0];
58-
try {
59-
ImageIO io = ImageIO.getImageIO();
60-
if (io == null || !io.isFormatSupported(ImageIO.FORMAT_PNG)) {
61-
println("CN1SS:ERR:test=" + safeName + " message=PNG encoding unavailable");
64+
if(Display.getInstance().isSimulator()) {
65+
io.save(screenshot, Storage.getInstance().createOutputStream(safeName + ".png"), ImageIO.FORMAT_PNG, 1);
66+
}
67+
ByteArrayOutputStream pngOut = new ByteArrayOutputStream(Math.max(1024, width * height / 2));
68+
io.save(screenshot, pngOut, ImageIO.FORMAT_PNG, 1f);
69+
byte[] pngBytes = pngOut.toByteArray();
70+
println("CN1SS:INFO:test=" + safeName + " png_bytes=" + pngBytes.length);
71+
emitChannel(pngBytes, safeName, "");
72+
73+
byte[] preview = encodePreview(io, screenshot, safeName);
74+
if (preview != null && preview.length > 0) {
75+
emitChannel(preview, safeName, PREVIEW_CHANNEL);
76+
} else {
77+
println("CN1SS:INFO:test=" + safeName + " preview_jpeg_bytes=0 preview_quality=0");
78+
}
79+
} catch (IOException ex) {
80+
println("CN1SS:ERR:test=" + safeName + " message=" + ex);
81+
Log.e(ex);
6282
println("CN1SS:END:" + safeName);
83+
} finally {
84+
screenshot.dispose();
85+
complete(onComplete);
6386
}
64-
if(Display.getInstance().isSimulator()) {
65-
io.save(screenshot, Storage.getInstance().createOutputStream(safeName + ".png"), ImageIO.FORMAT_PNG, 1);
66-
}
67-
ByteArrayOutputStream pngOut = new ByteArrayOutputStream(Math.max(1024, width * height / 2));
68-
io.save(screenshot, pngOut, ImageIO.FORMAT_PNG, 1f);
69-
byte[] pngBytes = pngOut.toByteArray();
70-
println("CN1SS:INFO:test=" + safeName + " png_bytes=" + pngBytes.length);
71-
emitChannel(pngBytes, safeName, "");
72-
73-
byte[] preview = encodePreview(io, screenshot, safeName);
74-
if (preview != null && preview.length > 0) {
75-
emitChannel(preview, safeName, PREVIEW_CHANNEL);
76-
} else {
77-
println("CN1SS:INFO:test=" + safeName + " preview_jpeg_bytes=0 preview_quality=0");
78-
}
79-
} catch (IOException ex) {
80-
println("CN1SS:ERR:test=" + safeName + " message=" + ex);
81-
Log.e(ex);
82-
println("CN1SS:END:" + safeName);
83-
} finally {
84-
screenshot.dispose();
85-
}
87+
});
8688
}
8789

8890
static byte[] encodePreview(ImageIO io, Image screenshot, String safeName) throws IOException {
@@ -188,4 +190,14 @@ static String zeroPad(int value, int width) {
188190
static void println(String line) {
189191
System.out.println(line);
190192
}
193+
194+
static void complete(Runnable runnable) {
195+
if (runnable != null) {
196+
runnable.run();
197+
}
198+
}
199+
200+
static boolean isHtml5() {
201+
return "HTML5".equals(Display.getInstance().getPlatformName());
202+
}
191203
}

scripts/hellocodenameone/common/src/main/java/com/codenameone/examples/hellocodenameone/tests/OrientationLockScreenshotTest.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,10 @@ protected void onShowCompleted() {
1818
CN.lockOrientation(false);
1919
waitForOrientation(this, false, () -> {
2020
waitFor(50);
21-
Cn1ssDeviceRunnerHelper.emitCurrentFormScreenshot("landscape");
22-
CN.lockOrientation(true);
23-
waitForOrientation(this, true, OrientationLockScreenshotTest.this::done);
21+
Cn1ssDeviceRunnerHelper.emitCurrentFormScreenshot("landscape", () -> {
22+
CN.lockOrientation(true);
23+
waitForOrientation(this, true, OrientationLockScreenshotTest.this::done);
24+
});
2425
});
2526
}
2627
};

scripts/hellocodenameone/common/src/main/kotlin/com/codenameone/examples/hellocodenameone/HelloCodenameOne.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package com.codenameone.examples.hellocodenameone
22

33
import com.codename1.system.Lifecycle
44
import com.codename1.testing.TestReporting
5+
import com.codename1.ui.CN
56
import com.codename1.ui.Display
67
import com.codenameone.examples.hellocodenameone.tests.Cn1ssDeviceRunner
78
import com.codenameone.examples.hellocodenameone.tests.Cn1ssDeviceRunnerReporter
@@ -28,7 +29,7 @@ open class HelloCodenameOne : Lifecycle() {
2829
println("CN1JS:HelloCodenameOne.runner.end")
2930
}
3031
if (Display.getInstance().platformName == "HTML5") {
31-
runner.run()
32+
CN.callSerially(runner)
3233
} else {
3334
Thread(runner, "CN1SS-Runner").start()
3435
}

0 commit comments

Comments
 (0)