/*
* Copyright (c) 2013, the Dart project authors.
*
* Licensed under the Eclipse Public License v1.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.eclipse.org/legal/epl-v10.html
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.dart.tools.debug.core.pubserve;
import com.google.dart.engine.sdk.DirectoryBasedDartSdk;
import com.google.dart.tools.core.generator.WebAppSample;
import com.google.dart.tools.core.model.DartSdkManager;
import com.google.dart.tools.core.test.util.PlainTestProject;
import com.google.dart.tools.core.utilities.net.NetUtils;
import junit.framework.TestCase;
import org.eclipse.core.resources.IProject;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
public class PubConnectionTest extends TestCase {
// pub ==> {"id":1,"method":"pathToUrls","params":{"path":"web/foo.html"},"jsonrpc":"2.0"}
// pub <== {"id":1,"result":{"urls":["http://127.0.0.1:8080/foo.html"]},"jsonrpc":"2.0"}
// pub ==> {"id":2,"method":"urlToAssetId","params":{"url":"http://127.0.0.1:8080/foo.html"},"jsonrpc":"2.0"}
// pub <== {"id":2,"result":{"path":"web/foo.html","package":"foo"},"jsonrpc":"2.0"}
// pub ==> {"id":3,"method":"serveDirectory","params":{"path":"test"},"jsonrpc":"2.0"}
// pub <== {"id":3,"result":{"url":"http://127.0.0.1:8081"},"jsonrpc":"2.0"}
private PubCallback<String> serveDirectoryCallback = new PubCallback<String>() {
@Override
public void handleResult(PubResult<String> result) {
assertTrue(!result.isError());
assertTrue(result.getResult().matches("http://.*"));
latch.countDown();
}
};
private PubCallback<String> assetToUrlCallback = new PubCallback<String>() {
@Override
public void handleResult(PubResult<String> result) {
assertTrue(!result.isError());
assertTrue(result.getResult().matches("http://.*"));
assertTrue(result.getResult().contains("foo.html"));
latch.countDown();
}
};
private PubCallback<PubAsset> urlToAssestCallback = new PubCallback<PubAsset>() {
@Override
public void handleResult(PubResult<PubAsset> result) {
assertTrue(!result.isError());
assertEquals("foo", result.getResult().getPackageStr());
assertEquals("web/foo.html", result.getResult().getPath());
latch.countDown();
}
};
protected PubConnection connection;
private PlainTestProject testProject;
private Process process;
private String port;
private PubConnection pubConnection;
private StringBuilder stdOut = new StringBuilder();
private static CountDownLatch latch;
/**
* An integration test of pub protocol support.
*/
public void testPubProtocolIntegration() throws Exception {
PubCommands command = pubConnection.getCommands();
latch = new CountDownLatch(1);
command.pathToUrl("web/foo.html", assetToUrlCallback);
if (!latch.await(3000, TimeUnit.MILLISECONDS)) {
throw new Exception("No response from pub command assetIdToUrl");
}
latch = new CountDownLatch(1);
command.urlToAssetId("http://localhost:8080/foo.html", urlToAssestCallback);
if (!latch.await(5000, TimeUnit.MILLISECONDS)) {
throw new Exception("No response from pub command urlToAssestId");
}
// TODO(keertip): get test passing and enable
latch = new CountDownLatch(1);
command.serveDirectory("test", serveDirectoryCallback);
if (!latch.await(3000, TimeUnit.MILLISECONDS)) {
throw new Exception("No response from pub command serveDirectory");
}
}
@Override
protected void setUp() throws Exception {
testProject = new PlainTestProject("webby");
IProject project = testProject.getProject();
WebAppSample generator = new WebAppSample();
generator.generateInto(project, "foo");
testProject.setFileContent("pubspec.lock", "packages:\n"
+ " browser:\n description: browser\n source: hosted\n version: \"0.10.0\"");
testProject.createFolder("test");
testProject.setFileContent("test/test.dart", "main() {}");
List<String> args = buildPubServeCommand();
ProcessBuilder builder = new ProcessBuilder();
builder.command(args);
builder.directory(project.getLocation().toFile());
process = builder.start();
Thread stdoutThread = new Thread(new Runnable() {
@Override
public void run() {
try {
copyStream(process.getInputStream(), stdOut);
} catch (IOException e) {
processDestroy();
fail("Exception while reading pub serve stdout");
}
}
});
stdoutThread.start();
// Increased timeout 3 -> 30 sec for buildbots
long endTime = System.currentTimeMillis() + 30 * 1000;
while (!isTerminated() && !stdOut.toString().contains("127.0.0.1")
&& System.currentTimeMillis() < endTime) {
try {
Thread.sleep(200);
} catch (InterruptedException exception) {
// do nothing, continue
}
}
if (isTerminated()) {
fail("Pub serve process terminated");
}
if (!stdOut.toString().contains("127.0.0.1")) {
fail("Timeout: pub serve did not start in 3 secs");
processDestroy();
}
pubConnection = new PubConnection(new URI("ws://127.0.0.1:" + port + "/"));
pubConnection.connect();
}
@Override
protected void tearDown() throws Exception {
try {
testProject.dispose();
} catch (Exception e) {
processDestroy();
fail("Exception while deleting test project");
}
processDestroy();
}
private List<String> buildPubServeCommand() {
DirectoryBasedDartSdk sdk = DartSdkManager.getManager().getSdk();
File pubFile = sdk.getPubExecutable();
List<String> args = new ArrayList<String>();
args.add(pubFile.getAbsolutePath());
args.add("serve");
args.add("--admin-port");
port = Integer.toString(NetUtils.findUnusedPort(8080));
args.add(port);
args.add("--hostname");
args.add("127.0.0.1");
// args.add("--verbose");
return args;
}
private void copyStream(InputStream in, StringBuilder stringBuilder) throws IOException {
byte[] buffer = new byte[2048];
try {
int count = in.read(buffer);
while (count != -1) {
if (count > 0) {
String str = new String(buffer, 0, count);
stringBuilder.append(str);
}
count = in.read(buffer);
}
in.close();
} catch (IOException ioe) {
in.close();
process.destroy();
fail("IOException while reading pub serve stream");
}
}
private boolean isTerminated() {
try {
if (process != null) {
process.exitValue();
}
} catch (IllegalThreadStateException exception) {
return false;
}
return true;
}
private void processDestroy() {
if (process != null) {
process.destroy();
}
}
}