Java tutorial
/* * fi.helsinki.cs.iot.hub.IotHubHTTPDTest * v0.1 * 2015 * * Copyright 2015 University of Helsinki * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 * 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 fi.helsinki.cs.iot.hub; import static org.junit.Assert.*; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import org.junit.After; import org.junit.Before; import org.junit.Test; import fi.helsinki.cs.iot.hub.database.IotHubDataAccess; import fi.helsinki.cs.iot.hub.jsengine.DuktapeJavascriptEngineWrapper; import fi.helsinki.cs.iot.hub.model.enabler.PluginInfo; import fi.helsinki.cs.iot.hub.utils.ScriptUtils; import fi.helsinki.cs.iot.hub.model.enabler.BasicPluginInfo; import fi.helsinki.cs.iot.hub.model.enabler.BasicPluginInfo.Type; import fi.helsinki.cs.iot.hub.webserver.IotHubHTTPD; import fi.helsinki.cs.iot.kahvihub.database.sqliteJdbc.IotHubDbHandlerSqliteJDBCImpl; /** * @author mineraud * */ public class IotHubHTTPDTest { private IotHubHTTPD iotHubHTTPD; private int port = 8081; private Path libdir; /** * @throws java.lang.Exception */ @Before public void setUp() throws Exception { libdir = Files.createTempDirectory("IotHubHTTPDTest"); libdir.toFile().deleteOnExit(); iotHubHTTPD = new IotHubHTTPD(port, libdir); File dbFile = File.createTempFile("IotHubHTTPDTest", ".db"); dbFile.deleteOnExit(); IotHubDataAccess.setInstance(new IotHubDbHandlerSqliteJDBCImpl(dbFile.getAbsolutePath(), 1, true)); try { iotHubHTTPD.start(); } catch (IOException ioe) { fail("Couldn't start server:\n" + ioe.getMessage()); } } /** * @throws java.lang.Exception */ @After public void tearDown() throws Exception { iotHubHTTPD.stop(); } private File makePluginFile(String pluginName) { String pluginScript = String.format("var %s = {};", pluginName); //My plugin needConfiguration pluginScript += String.format("%s.needConfiguration = true;", pluginName); //Set config to null pluginScript += String.format("%s.config = null;", pluginName); //The configuration is a dictionary of json object with fields are answering the different methods String checkConfigurationFunction = "function(data) { " //+ " print(data);" + " var config = JSON.parse(data); " + " if (typeof(config.name) == 'undefined') { return false; }" + " if (typeof(config.value) == 'undefined') { return false; }" + " if (typeof(config.isSupported) !== 'boolean') { return false; }" + " if (typeof(config.isAvailable) !== 'boolean') { return false; }" + " if (typeof(config.isReadable) !== 'boolean') { return false; }" + " if (typeof(config.isWritable) !== 'boolean') { return false; }" + " if (typeof(config.getNumberOfFeatures) !== 'number') { return false; }" + " if (typeof(config.getFeatureDescription) !== 'string') { return false; }" + " return true; }"; pluginScript += String.format("%s.checkConfiguration = %s;", pluginName, checkConfigurationFunction); pluginScript += String.format( "%s.configure = function(config) { if (this.checkConfiguration(config)) {this.config = JSON.parse(config);}};", pluginName); pluginScript += String.format( "%s.isFeatureSupported = function(name) { if (this.config && this.config.name == name) { return this.config.isSupported;}};", pluginName); pluginScript += String.format( "%s.isFeatureAvailable = function(name) { if (this.config && this.config.name == name) { return this.config.isAvailable;}};", pluginName); pluginScript += String.format( "%s.isFeatureReadable = function(name) { if (this.config && this.config.name == name) { return this.config.isReadable;}};", pluginName); pluginScript += String.format( "%s.isFeatureWritable = function(name) { if (this.config && this.config.name == name) { return this.config.isWritable;}};", pluginName); pluginScript += String.format( "%s.getNumberOfFeatures = function() { if (this.config) { return 1; } else { return 0; } };", pluginName); pluginScript += String.format( "%s.getFeatureDescription = function(index) { if (this.config) { return JSON.stringify({name: this.config.name, type: \"whatever\"});}};", pluginName); pluginScript += String.format( "%s.getFeatureValue = function(name) { if (this.config && this.config.name == name) {return JSON.stringify(this.config.value);} else {return null;} };", pluginName); pluginScript += String.format( "%s.postFeatureValue = function(name, data) { if (this.config && this.config.name == name) {" + "this.config.value = JSON.parse(data); makeConfigurationPersistant(JSON.stringify(this.config)); return true;} else { return false;} };", pluginName); File temp = null; try { temp = File.createTempFile("tempfile", ".tmp"); temp.deleteOnExit(); BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(temp)); bufferedWriter.write(pluginScript); bufferedWriter.close(); } catch (IOException e) { fail(e.getMessage()); } PluginInfo info = new PluginInfo(1, Type.JAVASCRIPT, pluginName, null, temp.getAbsolutePath()); assertNotNull(info); return temp; } private JSONObject makeJsonObjectForPlugin(String pluginName, String packageName, BasicPluginInfo.Type type, File file, boolean isService) { JSONObject json = new JSONObject(); try { json.put("plugin", pluginName); json.put("package", packageName); json.put("type", type.name()); String encoded = ScriptUtils.encodeBase64FromFile(file); json.put("file", encoded); if (isService) { json.put("isService", true); } return json; } catch (JSONException | IOException e) { // TODO Auto-generated catch block e.printStackTrace(); return null; } } @Test public void testPluginAPI() { //At this point, the list should be empty String res = DuktapeJavascriptEngineWrapper.performJavaHttpRequest("GET", "http://127.0.0.1:" + port + "/plugins/", null); assertEquals("[]", res.trim()); String pluginName = "MyPlugin"; //now I want to had a javascript plugin File pluginFile = makePluginFile(pluginName); JSONObject jsonObject = makeJsonObjectForPlugin(pluginName, null, Type.JAVASCRIPT, pluginFile, false); assertNotNull(jsonObject); //First check the if I can had it with get res = DuktapeJavascriptEngineWrapper.performJavaHttpRequest("GET", "http://127.0.0.1:" + port + "/plugins/", jsonObject.toString()); assertEquals("[]", res.trim()); PluginInfo pluginInfo = new PluginInfo(1, Type.JAVASCRIPT, pluginName, null, null); res = DuktapeJavascriptEngineWrapper.performJavaHttpRequest("POST", "http://127.0.0.1:" + port + "/plugins/", jsonObject.toString()); try { assertEquals(pluginInfo.toJSON().toString(), res.trim()); } catch (JSONException e) { // TODO Auto-generated catch block e.printStackTrace(); fail(e.getMessage()); } assertEquals(1, IotHubDataAccess.getInstance().getPlugins().size()); //Now going to delete the plugininfo res = DuktapeJavascriptEngineWrapper.performJavaHttpRequest("DELETE", "http://127.0.0.1:" + port + "/plugins?id=1&type=enabler", null); try { assertEquals(pluginInfo.toJSON().toString(), res.trim()); } catch (JSONException e) { // TODO Auto-generated catch block e.printStackTrace(); fail(e.getMessage()); } assertEquals(0, IotHubDataAccess.getInstance().getPlugins().size()); } @Test public void testEnablerAPI() { String res = DuktapeJavascriptEngineWrapper.performJavaHttpRequest("GET", "http://127.0.0.1:" + port + "/enablers/", null); assertEquals("[]", res.trim()); //Now I want to create a javascript plugin to attach to my enabler String pluginName = "MyPlugin"; //now I want to had a javascript plugin File pluginFile = makePluginFile(pluginName); JSONObject jsonObject = makeJsonObjectForPlugin(pluginName, null, Type.JAVASCRIPT, pluginFile, false); assertNotNull(jsonObject); String myPluginString = DuktapeJavascriptEngineWrapper.performJavaHttpRequest("POST", "http://127.0.0.1:" + port + "/plugins/", jsonObject.toString()); JSONObject jPlugin = null; try { jPlugin = new JSONObject(myPluginString); long pluginId = jPlugin.getLong("id"); String name = "MyEnabler"; String metadata = "A freshly created enabler"; JSONObject jEnabler = new JSONObject(); jEnabler.put("plugin", pluginId); jEnabler.put("name", "fakeName"); jEnabler.put("metadata", metadata); // I should get an enable with no features as it is not configured res = DuktapeJavascriptEngineWrapper.performJavaHttpRequest("POST", "http://127.0.0.1:" + port + "/enablers/", jEnabler.toString()); JSONObject jexpectedEnabler = new JSONObject(); jexpectedEnabler.put("id", 1); jexpectedEnabler.put("name", "fakeName"); jexpectedEnabler.put("metadata", metadata); jexpectedEnabler.put("plugin", jPlugin); JSONArray array = new JSONArray(); jexpectedEnabler.put("features", array); assertEquals(jexpectedEnabler.toString(), res.trim()); String featureName = "MyFeature"; JSONObject config = new JSONObject(); config.put("name", featureName); config.put("isSupported", true); config.put("isAvailable", true); config.put("isReadable", true); config.put("isWritable", true); config.put("getNumberOfFeatures", 1); config.put("getFeatureDescription", featureName); config.put("value", "Uksomatonta"); JSONObject data = new JSONObject(); data.put("configuration", config); res = DuktapeJavascriptEngineWrapper.performJavaHttpRequest("PUT", "http://127.0.0.1:" + port + "/enablers/fakeName", data.toString()); JSONObject expectedFeature = new JSONObject(); expectedFeature.put("id", 1); expectedFeature.put("isSupported", true); expectedFeature.put("isAtomicFeed", false); expectedFeature.put("name", featureName); expectedFeature.put("isWritable", true); expectedFeature.put("isReadable", true); expectedFeature.put("type", "whatever"); expectedFeature.put("isAvailable", true); array.put(expectedFeature); jexpectedEnabler.put("features", array); jexpectedEnabler.put("config", config.toString()); assertEquals(jexpectedEnabler.toString().length(), res.trim().length()); //Now just change quicky the configuration config.put("value", "Hard to believe"); data.put("configuration", config); data.put("name", name); res = DuktapeJavascriptEngineWrapper.performJavaHttpRequest("PUT", "http://127.0.0.1:" + port + "/enablers/fakeName", data.toString()); jexpectedEnabler.put("name", name); jexpectedEnabler.put("config", config.toString()); assertEquals(jexpectedEnabler.toString().length(), res.trim().length()); //Now I want to change the feature as an atomic feed data = new JSONObject(); data.put("enableAsAtomicFeed", true); res = DuktapeJavascriptEngineWrapper.performJavaHttpRequest("PUT", "http://127.0.0.1:" + port + "/enablers/" + name + "/" + featureName, data.toString()); expectedFeature.put("id", 2); expectedFeature.put("isAtomicFeed", true); assertEquals(expectedFeature.toString(), res.trim()); //Now I will check for feeds res = DuktapeJavascriptEngineWrapper.performJavaHttpRequest("GET", "http://127.0.0.1:" + port + "/feeds/", null); JSONArray feedArray = new JSONArray(res); assertEquals(1, feedArray.length()); JSONObject feed1 = feedArray.getJSONObject(0); String feedName = feed1.getString("name"); res = DuktapeJavascriptEngineWrapper.performJavaHttpRequest("GET", "http://127.0.0.1:" + port + "/feeds/" + feedName, null); assertEquals("\"Hard to believe\"", res.trim()); JSONObject toPostToFeed = new JSONObject("{\"test\": \"Unbelievable\"}"); res = DuktapeJavascriptEngineWrapper.performJavaHttpRequest("POST", "http://127.0.0.1:" + port + "/feeds/" + feedName, toPostToFeed.toString()); assertEquals(toPostToFeed.toString(), res.trim()); res = DuktapeJavascriptEngineWrapper.performJavaHttpRequest("GET", "http://127.0.0.1:" + port + "/feeds/" + feedName, null); assertEquals(toPostToFeed.toString(), res.trim()); data.put("enableAsAtomicFeed", false); res = DuktapeJavascriptEngineWrapper.performJavaHttpRequest("PUT", "http://127.0.0.1:" + port + "/enablers/" + name + "/" + featureName, data.toString()); expectedFeature.put("isAtomicFeed", false); assertEquals(expectedFeature.toString(), res.trim()); res = DuktapeJavascriptEngineWrapper.performJavaHttpRequest("GET", "http://127.0.0.1:" + port + "/feeds/" + feedName, null); JSONObject jerror = new JSONObject(res); assertEquals("Error", jerror.getString("status")); } catch (JSONException e) { // TODO Auto-generated catch block e.printStackTrace(); fail(e.getMessage()); } } private File makePluginFileForService(String pluginName) { String pluginScript = String.format("var %s = {};", pluginName); //My plugin needConfiguration pluginScript += String.format("%s.needConfiguration = true;", pluginName); //Set config to null pluginScript += String.format("%s.config = null;", pluginName); String checkConfigurationFunction = "function(data) { " //+ " print(data);" + " var config = JSON.parse(data); " + " if (typeof(config.value) == 'undefined') { return false; }" + " return true; }"; pluginScript += String.format("%s.checkConfiguration = %s;", pluginName, checkConfigurationFunction); pluginScript += String.format( "%s.configure = function(config) { if (this.checkConfiguration(config)) {this.config = JSON.parse(config);}};", pluginName); pluginScript += String.format("%s.run = function() { setTimeout(function() { return null; }, 1000);};", pluginName); File temp = null; try { temp = File.createTempFile("tempfile", ".tmp"); temp.deleteOnExit(); BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(temp)); bufferedWriter.write(pluginScript); bufferedWriter.close(); } catch (IOException e) { fail(e.getMessage()); } PluginInfo info = new PluginInfo(1, Type.JAVASCRIPT, pluginName, null, temp.getAbsolutePath()); assertNotNull(info); return temp; } @Test public void testServiceAPI() { String res = DuktapeJavascriptEngineWrapper.performJavaHttpRequest("GET", "http://127.0.0.1:" + port + "/services/", null); assertEquals("[]", res.trim()); //Now I want to create a javascript plugin to attach to my service String pluginName = "MyPlugin"; //now I want to had a javascript plugin File pluginFile = makePluginFileForService(pluginName); JSONObject jsonObject = makeJsonObjectForPlugin(pluginName, null, Type.JAVASCRIPT, pluginFile, true); assertNotNull(jsonObject); String myPluginString = DuktapeJavascriptEngineWrapper.performJavaHttpRequest("POST", "http://127.0.0.1:" + port + "/plugins/", jsonObject.toString()); JSONObject jPlugin = null; try { jPlugin = new JSONObject(myPluginString); long pluginId = jPlugin.getLong("id"); String name = "MyService"; String metadata = "A freshly created service"; JSONObject jservice = new JSONObject(); jservice.put("plugin", pluginId); jservice.put("name", name); jservice.put("metadata", metadata); jservice.put("bootAtStartup", false); // I should get an enable with no features as it is not configured res = DuktapeJavascriptEngineWrapper.performJavaHttpRequest("POST", "http://127.0.0.1:" + port + "/services/", jservice.toString()); JSONObject jexpectedService = new JSONObject(); jexpectedService.put("id", 1); jexpectedService.put("name", name); jexpectedService.put("metadata", metadata); jexpectedService.put("plugin", jPlugin); jexpectedService.put("bootAtStartup", false); assertEquals(jexpectedService.toString(), res.trim()); JSONObject data = new JSONObject(); JSONObject config = new JSONObject(); config.put("value", "Text to print"); data.put("configuration", config); res = DuktapeJavascriptEngineWrapper.performJavaHttpRequest("PUT", "http://127.0.0.1:" + port + "/services/" + name, data.toString()); jexpectedService.put("id", 1); jexpectedService.put("config", config.toString()); assertEquals(jexpectedService.toString(), res.trim()); res = DuktapeJavascriptEngineWrapper.performJavaHttpRequest("GET", "http://127.0.0.1:" + port + "/services/" + name + "/start", null); try { Thread.sleep(500); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); fail(e.getMessage()); } } catch (JSONException e) { // TODO Auto-generated catch block e.printStackTrace(); fail(e.getMessage()); } } }