package lt.emasina.resthub.server;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import lombok.extern.log4j.Log4j;
import lt.emasina.resthub.model.DataResponse;
import lt.emasina.resthub.model.QueryManager;
import static lt.emasina.resthub.server.ServerSetup.EXCLUDE_HEADERS;
import lt.emasina.resthub.support.TestRequest;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONTokener;
import org.restlet.data.Header;
import org.restlet.data.MediaType;
import org.restlet.representation.Representation;
import org.restlet.resource.ClientResource;
import org.restlet.util.Series;
import org.skyscreamer.jsonassert.JSONAssert;
import static junit.framework.TestCase.assertEquals;
@Log4j
public class ServerChecks {
private final static String HEADER_FILE = "client_header";
private final static String DATA_FILE = "client_data";
public void check(QueryManager qm) throws IOException, JSONException {
log.debug("Cheking query headers");
Map headers = qm.options();
// Checking headers file
InputStream inputStream = getResultStream(HEADER_FILE);
if (inputStream == null) {
headersToFile(headers, HEADER_FILE);
} else {
compareHeaders(headers, inputStream);
}
log.debug("Cheking query data");
inputStream = getResultStream(DATA_FILE);
boolean loaded = inputStream != null;
Properties prop = new Properties();
if (loaded) {
prop.load(inputStream);
}
// Getting available content types
String ct = (String) headers.get("X-Content-Types");
String[] contentTypes = ct.split(",");
// Check each contentType
for (String contentType : contentTypes) {
DataResponse dr = qm.getData(contentType);
String data = dr.getString();
if (!loaded) {
prop.setProperty(contentType, data);
} else {
log.info(String.format("Comparing data: %s @ %s...", contentType, DATA_FILE));
compareData(contentType, prop.getProperty(contentType), data);
}
}
if (!loaded) {
prop.store(new FileOutputStream(getResultFile(DATA_FILE)), "Query data");
}
}
public void check(TestRequest query) throws IOException, URISyntaxException, org.json.JSONException {
check(query, Boolean.FALSE);
}
public void check(TestRequest query, Boolean skipData) throws IOException, URISyntaxException, org.json.JSONException {
ClientResource client = query.options();
String headerFile = query.getPrefix() + "_headers";
Series headers = (Series) client.getResponse().getAttributes().get("org.restlet.http.headers");
// Checking headers
InputStream inputStream = getResultStream(headerFile);
if (inputStream == null) {
headersToFile(headers, headerFile);
} else {
compareHeaders(headers, inputStream);
}
if (skipData) return;
// Checking data
Properties prop = new Properties();
String dataFile = query.getPrefix() + "_data";
inputStream = getResultStream(dataFile);
boolean loaded = inputStream != null;
if (loaded) {
prop.load(inputStream);
}
// Check query count
client = query.count();
if (client != null) {
String count = client.getResponseEntity().getText();
if (!loaded) {
prop.setProperty("count", count);
} else {
assertEquals(prop.getProperty("count"), count);
}
}
// Delete query cache
query.deleteCache();
String[] contentTypes = headers.getValues("X-Content-Types").split(",");
ArrayList<String> mimeTypes = new ArrayList<>();
// Check each contentType
for (String contentType : contentTypes) {
long t = System.currentTimeMillis();
client = query.get(MediaType.valueOf(contentType));
log.info(String.format("GET took: %d ms @%d", System.currentTimeMillis() - t, System.currentTimeMillis()));
Representation get = client.getResponseEntity();
String data = get.getText();
get.exhaust();
if (!loaded) {
prop.setProperty(contentType, data);
} else {
log.info(String.format("Comparing data: %s @ %s...", get.getMediaType().toString(), dataFile));
compareData(get.getMediaType().toString(), prop.getProperty(contentType), data);
// Get unique content types
headers = (Series) client.getResponse().getAttributes().get("org.restlet.http.headers");
String type = headers.getValues("Content-Type");
if(!mimeTypes.contains(type)) {
mimeTypes.add(type);
}
}
}
// Check cache size
client = query.cache();
if (client != null) {
String data = client.getResponseEntity().getText();
JSONObject jsonObj = new JSONObject(data);
log.debug("Comparing cache:" + jsonObj);
int test_value = Integer.parseInt(jsonObj.getString("size"));
assertEquals((int) 1, test_value);
}
// Delete query
query.deleteQuery();
if (!loaded) {
prop.store(new FileOutputStream(getResultFile(dataFile)), "Query data");
}
}
private InputStream getResultStream(String fileName) {
return ServerSetup.class.getResourceAsStream("/lt/emasina/server/results/" + fileName);
}
private File getResultFile(String fileName) {
return new File("src/test/resources/lt/emasina/server/results/" + fileName);
}
private void compareData(String contentType, String expected, String received) throws JSONException {
if (contentType.equals("application/json")) {
Object je = new JSONTokener(expected).nextValue();
Object jr = new JSONTokener(received).nextValue();
assertEquals(je.getClass(), jr.getClass());
if (je instanceof JSONObject) {
JSONAssert.assertEquals((JSONObject) je, (JSONObject) jr, false);
} else if (je instanceof JSONArray) {
JSONAssert.assertEquals((JSONArray) je, (JSONArray) jr, false);
}
} else {
assertEquals(expected.length(), received.length());
}
}
private void headersToFile(Series headers, String fileName) throws IOException {
Map map = new HashMap();
for (Object header1 : headers) {
Header header = (Header) header1;
map.put(header.getName(), header.getValue());
}
headersToFile(map, fileName);
}
private void headersToFile(Map headers, String fileName) throws IOException {
Properties prop = new Properties();
for (Object key: headers.keySet()) {
String name = (String) key;
String value = (String) headers.get(key);
prop.setProperty(name, value);
}
prop.store(new FileOutputStream(getResultFile(fileName)), "Headers");
}
private void compareHeaders(Series headers, InputStream inputStream) throws IOException {
Map map = new HashMap();
for (Object header1 : headers) {
Header header = (Header) header1;
map.put(header.getName(), header.getValue());
}
compareHeaders(map, inputStream);
}
private void compareHeaders(Map headers, InputStream inputStream) throws IOException {
Properties prop = new Properties();
prop.load(inputStream);
for (Object key: headers.keySet()) {
String name = (String) key;
String current_value = (String) headers.get(key);
String test_value = prop.getProperty(name);
if (!Arrays.asList(EXCLUDE_HEADERS).contains(name)) {
assertEquals(String.format("[%s] header value", name), test_value, current_value);
}
}
}
}