jaroslav@50: /* jaroslav@264: * Quoridor server and related libraries jaroslav@264: * Copyright (C) 2009-2010 Jaroslav Tulach jaroslav@50: * jaroslav@264: * This program is free software: you can redistribute it and/or modify jaroslav@264: * it under the terms of the GNU General Public License as published by jaroslav@264: * the Free Software Foundation, either version 3 of the License. jaroslav@50: * jaroslav@264: * This program is distributed in the hope that it will be useful, jaroslav@264: * but WITHOUT ANY WARRANTY; without even the implied warranty of jaroslav@264: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the jaroslav@264: * GNU General Public License for more details. jaroslav@50: * jaroslav@264: * You should have received a copy of the GNU General Public License jaroslav@264: * along with this program. Look for COPYING file in the top folder. jaroslav@264: * If not, see http://www.gnu.org/licenses/. jaroslav@50: */ jaroslav@50: package cz.xelfi.quoridor.freemarkerdor; jaroslav@50: jaroslav@282: import org.glassfish.grizzly.http.server.HttpServer; jaroslav@276: import java.util.Collection; jaroslav@276: import java.util.Arrays; jaroslav@50: import com.sun.jersey.api.client.Client; jaroslav@73: import com.sun.jersey.api.client.ClientResponse; jaroslav@50: import com.sun.jersey.api.client.WebResource; jaroslav@50: import com.sun.jersey.core.header.MediaTypes; jaroslav@73: import com.sun.jersey.core.util.MultivaluedMapImpl; jaroslav@126: import cz.xelfi.quoridor.webidor.resources.Quoridor; jaroslav@50: import java.io.File; jaroslav@73: import java.io.FileOutputStream; jaroslav@50: import java.io.IOException; jaroslav@106: import java.io.InputStream; jaroslav@50: import java.net.URI; jaroslav@276: import java.util.HashSet; jaroslav@62: import java.util.Locale; jaroslav@50: import java.util.concurrent.Callable; jaroslav@106: import java.util.regex.Matcher; jaroslav@106: import java.util.regex.Pattern; jaroslav@51: import javax.ws.rs.core.Cookie; jtulach@82: import javax.ws.rs.core.MediaType; jaroslav@73: import javax.ws.rs.core.MultivaluedMap; jaroslav@73: import org.junit.AfterClass; jaroslav@50: import org.junit.Before; jaroslav@62: import org.junit.BeforeClass; jaroslav@50: import org.junit.Test; jaroslav@50: import static org.junit.Assert.*; jaroslav@50: jaroslav@50: /** jaroslav@50: * jaroslav@50: * @author Jaroslav Tulach jaroslav@50: */ jaroslav@50: public class UITest extends Object { jaroslav@73: private static File dir; jaroslav@126: private static HttpServer stopAPI; martin@180: private static HttpServer stopStatistics; jaroslav@73: private static Callable stop; jaroslav@272: jaroslav@50: private WebResource webResource; jaroslav@121: private WebResource apiResource; martin@180: private WebResource statResource; jaroslav@50: jaroslav@50: public UITest() throws Exception { jaroslav@50: } jaroslav@50: jaroslav@62: @BeforeClass jaroslav@73: public static void localeEnglish() throws Exception { jaroslav@62: Locale.setDefault(Locale.ENGLISH); jaroslav@73: dir = File.createTempFile("quoridor", ".dir"); jaroslav@73: dir.delete(); jaroslav@73: dir.mkdirs(); jaroslav@272: jaroslav@272: File games = new File(dir, "games"); jaroslav@272: copyResource("wrong.encoding", new File(games, "fdcc275c-55ad-4b7e-a776-bde3876b2f2c")); jaroslav@272: jaroslav@272: jaroslav@73: System.setProperty("quoridor.dir", dir.getPath()); jaroslav@126: stopAPI = Quoridor.start(9990); martin@180: stopStatistics = Quoridor.start(9992); jaroslav@234: stop = UI.startServers(9991, "http://localhost:9990", "http://localhost:9992", null); jaroslav@73: jaroslav@73: File passwd = new File(dir, "passwd"); jaroslav@73: FileOutputStream os = new FileOutputStream(passwd); jtulach@82: os.write("test=pes\nJarda=darda\n".getBytes("UTF-8")); jaroslav@73: os.close(); jaroslav@62: } jaroslav@62: jaroslav@50: @Before jaroslav@50: public void setUp() throws Exception { jaroslav@50: jaroslav@50: Client client = new Client(); jaroslav@68: webResource = client.resource(new URI("http://localhost:9991/")); jaroslav@124: apiResource = client.resource(new URI("http://localhost:9990/")); martin@180: statResource = client.resource(new URI("http://localhost:9992/")); jaroslav@50: } jaroslav@50: jaroslav@73: @AfterClass jaroslav@73: public static void cleanUpAll() throws Exception { jaroslav@50: deleteRec(dir); jaroslav@50: if (stop != null) { jaroslav@50: stop.call(); jaroslav@50: } jaroslav@126: if (stopAPI != null) { jaroslav@282: stopAPI.stop(); jaroslav@126: } jaroslav@50: } jaroslav@50: jaroslav@50: static void deleteRec(File dir) throws IOException { jaroslav@50: if (dir == null) { jaroslav@50: return; jaroslav@50: } jaroslav@50: File[] arr = dir.listFiles(); jaroslav@50: if (arr != null) { jaroslav@50: for (File f : arr) { jaroslav@50: deleteRec(f); jaroslav@50: } jaroslav@50: } jaroslav@50: dir.delete(); jaroslav@50: } jaroslav@50: jaroslav@50: @Test public void testApplicationWadl() { jaroslav@50: String serviceWadl = webResource.path("application.wadl"). jaroslav@50: accept(MediaTypes.WADL).get(String.class); jaroslav@50: assertTrue(serviceWadl.length() > 0); jaroslav@50: } jaroslav@50: jaroslav@124: @Test public void testAPIWadl() { jaroslav@124: String serviceWadl = apiResource.path("application.wadl"). jaroslav@124: accept(MediaTypes.WADL).get(String.class); jaroslav@124: assertTrue(serviceWadl.length() > 0); jaroslav@124: } jaroslav@124: martin@180: @Test public void testStatWadl() { martin@180: String serviceWadl = statResource.path("application.wadl"). martin@180: accept(MediaTypes.WADL).get(String.class); martin@180: assertTrue(serviceWadl.length() > 0); martin@180: } martin@180: jaroslav@50: @Test public void testGetIndexPage() throws Exception { jaroslav@121: String logJarda = apiResource.path("login"). jtulach@82: queryParam("name", "Jarda"). jtulach@82: queryParam("password", "darda"). jtulach@82: accept(MediaType.TEXT_PLAIN). jtulach@82: put(String.class); jtulach@82: assertNotNull("Logged in OK", logJarda); jtulach@82: jaroslav@50: String res = webResource.accept("text/html").get(String.class); jaroslav@50: if (res.indexOf("Quoridor") == -1) { jaroslav@50: fail("Wrong index.html:\n" + res); jaroslav@50: } jaroslav@51: if (res.indexOf("Login") == -1) { jaroslav@51: fail("Wrong index.html:\n" + res); jaroslav@51: } jaroslav@72: if (res.indexOf("action=\"/login\"") == -1) { jaroslav@51: fail("Wrong index.html:\n" + res); jaroslav@51: } jtulach@54: if (res.toLowerCase().indexOf("error") != -1) { jtulach@54: fail("There was an error:\n" + res); jtulach@54: } jtulach@82: res = webResource.cookie(Cookie.valueOf("login=" + logJarda)).accept("text/html").get(String.class); jtulach@74: if (res.indexOf("action=\"/games/create\"") == -1) { jaroslav@51: fail(res); jaroslav@51: } jaroslav@50: } jaroslav@50: jaroslav@73: @Test public void testLogin() throws Exception { jaroslav@73: MultivaluedMap formData = new MultivaluedMapImpl(); jaroslav@73: formData.add("name", "test"); jaroslav@73: formData.add("password", "pes"); jaroslav@73: ClientResponse response = webResource.path("login"). jaroslav@73: accept("text/html").type("application/x-www-form-urlencoded"). jaroslav@73: post(ClientResponse.class, formData); jaroslav@73: final String res = response.getEntity(String.class); jaroslav@73: assertEquals("OK", ClientResponse.Status.OK, response.getClientResponseStatus()); jtulach@81: if (res.indexOf("You are logged in as test") == -1) { jaroslav@73: fail("res: " + res); jaroslav@73: } jaroslav@73: } jaroslav@73: jaroslav@73: jaroslav@73: @Test public void testCreateGameWrongUsers() throws Exception { jaroslav@121: String logTest = apiResource.path("login"). jtulach@82: queryParam("name", "test"). jtulach@82: queryParam("password", "pes"). jtulach@82: accept(MediaType.TEXT_PLAIN). jtulach@82: put(String.class); jaroslav@73: ClientResponse res = webResource.path("games/create"). jaroslav@73: queryParam("white", "unknown1"). jaroslav@73: queryParam("black", "unknown2"). jtulach@82: cookie(Cookie.valueOf("login=" + logTest)). jaroslav@73: accept("text/html"). jaroslav@73: get(ClientResponse.class); jaroslav@73: final String txt = res.getEntity(String.class); jaroslav@73: assertEquals("Rejected, unknown user\n" + txt, ClientResponse.Status.NOT_FOUND, res.getClientResponseStatus()); jaroslav@73: if (txt.indexOf("You (test) must be") == -1) { jaroslav@73: fail(txt); jaroslav@73: } jaroslav@73: } jaroslav@73: jaroslav@73: @Test public void testCreateGameOK() throws Exception { jaroslav@276: Collection origGamesNames= Arrays.asList(new File(dir, "games").list()); jaroslav@276: int origGames = origGamesNames.size(); jaroslav@272: jaroslav@121: String logTest = apiResource.path("login"). jtulach@82: queryParam("name", "test"). jtulach@82: queryParam("password", "pes"). jtulach@82: accept(MediaType.TEXT_PLAIN). jtulach@82: put(String.class); jaroslav@121: String logJarda = apiResource.path("login"). jaroslav@106: queryParam("name", "Jarda"). jaroslav@106: queryParam("password", "darda"). jaroslav@106: accept(MediaType.TEXT_PLAIN). jaroslav@106: put(String.class); jaroslav@73: ClientResponse res = webResource.path("games/create"). jaroslav@106: queryParam("white", "Jarda"). jaroslav@73: queryParam("black", "test"). jtulach@82: cookie(Cookie.valueOf("login=" + logTest)). jaroslav@73: accept("text/html"). jaroslav@73: get(ClientResponse.class); jaroslav@73: jaroslav@73: final String txt = res.getEntity(String.class); jaroslav@73: assertEquals("OK\n" + txt, ClientResponse.Status.OK, res.getClientResponseStatus()); jaroslav@73: jaroslav@276: jaroslav@276: String myGame; jaroslav@276: { jaroslav@276: String[] games = new File(dir, "games").list(); jaroslav@276: assertEquals("One new game", origGames + 1, games.length); jaroslav@276: jaroslav@276: HashSet newNames = new HashSet(); jaroslav@276: newNames.addAll(Arrays.asList(games)); jaroslav@276: newNames.removeAll(origGamesNames); jaroslav@276: assertEquals("Just one name left: " + newNames, 1, newNames.size()); jaroslav@276: myGame = newNames.iterator().next(); jaroslav@73: } jaroslav@106: jaroslav@276: if (txt.indexOf(myGame) == -1) { jaroslav@276: fail(myGame + " expected inside of:\n" + txt); jaroslav@276: } jaroslav@276: jaroslav@276: ClientResponse page = webResource.path("games/" + myGame). jaroslav@106: cookie(Cookie.valueOf("login=" + logJarda)). jaroslav@106: get(ClientResponse.class); jaroslav@106: String ptxt = page.getEntity(String.class); jaroslav@106: assertEquals("OK:\n" + ptxt, ClientResponse.Status.OK, page.getClientResponseStatus()); jaroslav@106: jaroslav@113: Pattern p = Pattern.compile(".*]*src=\"([^\"]*)\""); jaroslav@106: Matcher m = p.matcher(ptxt); jaroslav@106: assertTrue("image found\n" + ptxt, m.find()); jaroslav@106: jaroslav@106: InputStream img1 = webResource.path(m.group(1)).get(InputStream.class); jaroslav@106: assertNotNull("image found", img1); jaroslav@106: jaroslav@276: ClientResponse move = apiResource.path("games/" + myGame). jaroslav@106: queryParam("loginID", logJarda). jaroslav@106: queryParam("player", "Jarda").queryParam("move", "N").put(ClientResponse.class); jaroslav@106: assertEquals("Move OK:\n" + move.getEntity(String.class), ClientResponse.Status.OK, move.getClientResponseStatus()); jaroslav@106: jaroslav@106: InputStream img2 = webResource.path(m.group(1)).get(InputStream.class); jaroslav@106: assertNotNull("image found", img2); jaroslav@106: jaroslav@276: ClientResponse page2 = webResource.path("games/" + myGame). jaroslav@106: cookie(Cookie.valueOf("login=" + logJarda)). jaroslav@106: get(ClientResponse.class); jaroslav@106: String ptxt2 = page2.getEntity(String.class); jaroslav@106: assertEquals("OK:\n" + ptxt2, ClientResponse.Status.OK, page2.getClientResponseStatus()); jaroslav@106: jaroslav@106: Matcher m2 = p.matcher(ptxt2); jaroslav@106: assertTrue("image found\n" + ptxt2, m2.find()); jaroslav@106: jaroslav@106: InputStream img3 = webResource.path(m2.group(1)).get(InputStream.class); jaroslav@106: assertNotNull("image found", img3); jaroslav@106: jaroslav@106: int diff = 0; jaroslav@106: int cnt = 0; jaroslav@106: for (;;) { jaroslav@106: cnt++; jaroslav@106: int b1 = img1.read(); jaroslav@106: int b2 = img2.read(); jaroslav@106: int b3 = img3.read(); jaroslav@106: assertEquals(b1, b2); jaroslav@106: if (b3 != b1) { jaroslav@106: diff++; jaroslav@106: } jaroslav@106: if (b1 == -1 || b3 == -1) break; jaroslav@106: jaroslav@106: } jaroslav@106: if (diff == 0) { jaroslav@106: // fail("There shall be difference in the streams. Read bytes " + cnt); jaroslav@106: } jaroslav@73: } jaroslav@272: jaroslav@272: @Test public void testGetWrongGame() throws Exception { jaroslav@272: String logTest = apiResource.path("login"). jaroslav@272: queryParam("name", "test"). jaroslav@272: queryParam("password", "pes"). jaroslav@272: accept(MediaType.TEXT_PLAIN). jaroslav@272: put(String.class); jaroslav@272: jaroslav@272: String xml = apiResource.path("games/fdcc275c-55ad-4b7e-a776-bde3876b2f2c"). jaroslav@272: queryParam("name", "test"). jaroslav@272: queryParam("password", "pes"). jaroslav@272: accept(MediaType.TEXT_XML). jaroslav@272: get(String.class); jaroslav@272: jaroslav@272: if (xml.indexOf((char)0x1b) >= 0) { jaroslav@272: fail(xml.replace((char)0x1b, 'X')); jaroslav@272: } jaroslav@272: jaroslav@272: ClientResponse res = webResource.path("games/fdcc275c-55ad-4b7e-a776-bde3876b2f2c"). jaroslav@272: queryParam("white", "Jarda"). jaroslav@272: queryParam("black", "test"). jaroslav@272: cookie(Cookie.valueOf("login=" + logTest)). jaroslav@272: accept("text/html"). jaroslav@272: get(ClientResponse.class); jaroslav@272: final String txt = res.getEntity(String.class); jaroslav@272: assertEquals("OK\n" + txt, ClientResponse.Status.OK, res.getClientResponseStatus()); jaroslav@272: } jaroslav@272: jaroslav@73: jaroslav@272: private static void copyResource(String res, File file) throws IOException { jaroslav@272: InputStream is = UITest.class.getResourceAsStream(res); jaroslav@272: file.getParentFile().mkdirs(); jaroslav@272: FileOutputStream os = new FileOutputStream(file); jaroslav@272: byte[] arr = new byte[4092]; jaroslav@272: for (;;) { jaroslav@272: int len = is.read(arr); jaroslav@272: if (len == -1) { jaroslav@272: break; jaroslav@272: } jaroslav@272: os.write(arr, 0, len); jaroslav@272: } jaroslav@272: is.close(); jaroslav@272: os.close(); jaroslav@272: } jaroslav@272: jaroslav@50: }