/*******************************************************************************
* Copyright (c) 2010, 2014 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.orion.server.tests.prefs;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URLEncoder;
import java.util.Arrays;
import java.util.List;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.orion.internal.server.core.metastore.SimpleMetaStore;
import org.eclipse.orion.server.core.IOUtilities;
import org.eclipse.orion.server.tests.servlets.files.FileSystemTest;
import org.json.JSONException;
import org.json.JSONObject;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import com.meterware.httpunit.GetMethodWebRequest;
import com.meterware.httpunit.PutMethodWebRequest;
import com.meterware.httpunit.WebConversation;
import com.meterware.httpunit.WebRequest;
import com.meterware.httpunit.WebResponse;
/**
* Tests for the preference servlet.
*/
public class PreferenceTest extends FileSystemTest {
@Before
public void setUp() throws Exception {
webConversation = new WebConversation();
webConversation.setExceptionsThrownOnErrorStatus(false);
setUpAuthorization();
createWorkspace(SimpleMetaStore.DEFAULT_WORKSPACE_NAME);
createTestProject(testName.getMethodName());
}
/**
* Tests corruption of preference keys containing URLS.
*/
@Test
public void testBug409792() throws JSONException, IOException {
String location = toAbsoluteURI("prefs/user/" + getTestUserId() + "/testBug409792");
//put a value containing a URL in the key
JSONObject prefs = new JSONObject();
final String key = "http://127.0.0.2:8080/plugins/samplePlugin.html";
prefs.put(key, true);
WebRequest request = new PutMethodWebRequest(location, IOUtilities.toInputStream(prefs.toString()), "application/json");
setAuthentication(request);
WebResponse response = webConversation.getResource(request);
assertEquals("1.1", HttpURLConnection.HTTP_NO_CONTENT, response.getResponseCode());
//attempt to retrieve the preference
request = new GetMethodWebRequest(location);
setAuthentication(request);
response = webConversation.getResource(request);
assertEquals("1.2", HttpURLConnection.HTTP_OK, response.getResponseCode());
JSONObject result = new JSONObject(response.getText());
assertTrue("1.3", result.optBoolean(key));
}
@Test
public void testGetSingle() throws IOException, JSONException {
List<String> locations = getTestPreferenceNodes();
for (String location : locations) {
//unknown key should return 404
WebRequest request = new GetMethodWebRequest(location + "?key=Name");
setAuthentication(request);
WebResponse response = webConversation.getResource(request);
assertEquals("1." + location, HttpURLConnection.HTTP_NOT_FOUND, response.getResponseCode());
//put a value
request = createSetPreferenceRequest(location, "Name", "Frodo");
setAuthentication(request);
response = webConversation.getResource(request);
assertEquals("2." + location, HttpURLConnection.HTTP_NO_CONTENT, response.getResponseCode());
//now doing a get should succeed
request = new GetMethodWebRequest(location + "?key=Name");
setAuthentication(request);
response = webConversation.getResource(request);
assertEquals("3." + location, HttpURLConnection.HTTP_OK, response.getResponseCode());
JSONObject result = new JSONObject(response.getText());
assertEquals("4." + location, "Frodo", result.optString("Name"));
//getting another key on the same resource should still 404
request = new GetMethodWebRequest(location + "?key=Address");
setAuthentication(request);
response = webConversation.getResource(request);
assertEquals("5." + location, HttpURLConnection.HTTP_NOT_FOUND, response.getResponseCode());
}
}
@Test
public void testPutSingle() throws IOException, JSONException {
List<String> locations = getTestPreferenceNodes();
for (String location : locations) {
//put a value that isn't currently defined
WebRequest request = createSetPreferenceRequest(location, "Name", "Frodo");
setAuthentication(request);
WebResponse response = webConversation.getResource(request);
assertEquals("1." + location, HttpURLConnection.HTTP_NO_CONTENT, response.getResponseCode());
//doing a get should succeed
request = new GetMethodWebRequest(location + "?key=Name");
setAuthentication(request);
response = webConversation.getResource(request);
assertEquals("2." + location, HttpURLConnection.HTTP_OK, response.getResponseCode());
JSONObject result = new JSONObject(response.getText());
assertEquals("3." + location, "Frodo", result.optString("Name"));
//setting a value to the empty string
request = createSetPreferenceRequest(location, "Name", "");
setAuthentication(request);
response = webConversation.getResource(request);
assertEquals("4." + location, HttpURLConnection.HTTP_NO_CONTENT, response.getResponseCode());
request = new GetMethodWebRequest(location + "?key=Name");
setAuthentication(request);
response = webConversation.getResource(request);
assertEquals("5." + location, HttpURLConnection.HTTP_OK, response.getResponseCode());
result = new JSONObject(response.getText());
assertEquals("6." + location, "", result.optString("Name"));
//putting with forbidden URL characters in key and value
request = createSetPreferenceRequest(location, "Na=me", "Fr&do");
setAuthentication(request);
response = webConversation.getResource(request);
assertEquals("1." + location, HttpURLConnection.HTTP_NO_CONTENT, response.getResponseCode());
//doing a get should succeed
request = new GetMethodWebRequest(location + "?key=Na%3Dme");
setAuthentication(request);
response = webConversation.getResource(request);
result = new JSONObject(response.getText());
assertEquals("3." + location, "Fr&do", result.optString("Na=me"));
}
}
/**
* Tests setting JSON objects as preference values
*
* @throws IOException
* @throws JSONException
*/
@Test
public void testPutJSON() throws IOException, JSONException {
List<String> locations = getTestPreferenceNodes();
for (String location : locations) {
//PUT http://myserver:8080/prefs/user/cm/configurations/jslint.config
//{"properties":{"options":"foo:true, bar:false"}}
JSONObject value = new JSONObject();
String options = "foo:true, bar:false";
value.put("options", options);
JSONObject prefs = new JSONObject();
prefs.put("properties", value);
String inString = prefs.toString();
WebRequest request = new PutMethodWebRequest(location, IOUtilities.toInputStream(inString), "application/json");
setAuthentication(request);
WebResponse response = webConversation.getResource(request);
assertEquals("1." + location, HttpURLConnection.HTTP_NO_CONTENT, response.getResponseCode());
//GET http://myserver:8080/prefs/user/cm/configurations/jslint.config
//should return: same value we put in
request = new GetMethodWebRequest(location);
setAuthentication(request);
response = webConversation.getResource(request);
assertEquals("2." + location, HttpURLConnection.HTTP_OK, response.getResponseCode());
JSONObject resultObject = new JSONObject(response.getText());
assertTrue("3." + location, resultObject.has("properties"));
JSONObject resultValue = resultObject.getJSONObject("properties");
Object resultOptions = resultValue.get("options");
assertEquals("4." + location, options, resultOptions);
}
//
//but...
//
//GET http://myserver:8080/prefs/user/cm/configurations/jslint.config
//{
// "properties" : "{\"options\":\"foo:true, bar:false\"}"
//}
}
@Test
public void testPutNode() throws IOException, JSONException {
List<String> locations = getTestPreferenceNodes();
for (String location : locations) {
//put a node that isn't currently defined
JSONObject prefs = new JSONObject();
prefs.put("Name", "Frodo");
prefs.put("Address", "Bag End");
WebRequest request = new PutMethodWebRequest(location, IOUtilities.toInputStream(prefs.toString()), "application/json");
setAuthentication(request);
WebResponse response = webConversation.getResource(request);
assertEquals("1." + location, HttpURLConnection.HTTP_NO_CONTENT, response.getResponseCode());
//doing a get should succeed
request = new GetMethodWebRequest(location + "?key=Address");
setAuthentication(request);
response = webConversation.getResource(request);
assertEquals("2." + location, HttpURLConnection.HTTP_OK, response.getResponseCode());
JSONObject result = new JSONObject(response.getText());
assertEquals("3." + location, "Bag End", result.optString("Address"));
//setting a node with disjoint values should clear values not in common
prefs = new JSONObject();
prefs.put("Name", "Barliman");
prefs.put("Occupation", "Barkeep");
request = new PutMethodWebRequest(location, IOUtilities.toInputStream(prefs.toString()), "application/json");
setAuthentication(request);
response = webConversation.getResource(request);
assertEquals("4." + location, HttpURLConnection.HTTP_NO_CONTENT, response.getResponseCode());
request = new GetMethodWebRequest(location);
setAuthentication(request);
response = webConversation.getResource(request);
assertEquals("5." + location, HttpURLConnection.HTTP_OK, response.getResponseCode());
result = new JSONObject(response.getText());
assertEquals("6." + location, "Barliman", result.optString("Name"));
assertFalse("7." + location, result.has("Address"));//this value was previously defined but the put node should clean it
assertEquals("8." + location, "Barkeep", result.optString("Occupation"));
}
}
@Ignore
public void testDeleteSingle() {
//TODO not implemented
}
@Ignore
public void testDeleteNode() {
//TODO not implemented
}
@Test
public void testValueWithSpaces() throws IOException, JSONException {
//put a value
String location = getTestPreferenceNodes().get(0);
WebRequest request = createSetPreferenceRequest(location, "Name", "Frodo Baggins");
setAuthentication(request);
WebResponse response = webConversation.getResource(request);
assertEquals(HttpURLConnection.HTTP_NO_CONTENT, response.getResponseCode());
//now doing a get should succeed
request = new GetMethodWebRequest(location + "?key=Name");
setAuthentication(request);
response = webConversation.getResource(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
JSONObject result = new JSONObject(response.getText());
assertEquals("Frodo Baggins", result.optString("Name"));
}
/**
* Tests whether a client can access workspace metadata via the preferences servlet.
* @throws IOException
*/
@Test
public void testAccessingMetadata() throws IOException {
List<String> locations = getIllegalPreferenceNodes();
for (String location : locations) {
//get should return 405
WebRequest request = new GetMethodWebRequest(location);
setAuthentication(request);
WebResponse response = webConversation.getResource(request);
assertEquals(HttpURLConnection.HTTP_BAD_METHOD, response.getResponseCode());
//put a value should be 403
request = createSetPreferenceRequest(location, "Name", "Frodo");
setAuthentication(request);
response = webConversation.getResource(request);
assertEquals(HttpURLConnection.HTTP_BAD_METHOD, response.getResponseCode());
}
}
@Test
public void testGetNode() throws IOException, JSONException {
List<String> locations = getTestPreferenceNodes();
for (String location : locations) {
//unknown node should empty JSON
WebRequest request = new GetMethodWebRequest(location);
setAuthentication(request);
WebResponse response = webConversation.getResource(request);
assertEquals("1." + location, HttpURLConnection.HTTP_OK, response.getResponseCode());
assertEquals("1." + location, "{}", response.getText());
//put a value
request = createSetPreferenceRequest(location, "Name", "Frodo");
setAuthentication(request);
response = webConversation.getResource(request);
assertEquals("2." + location, HttpURLConnection.HTTP_NO_CONTENT, response.getResponseCode());
//now doing a get should succeed
request = new GetMethodWebRequest(location);
setAuthentication(request);
response = webConversation.getResource(request);
assertEquals("3." + location, HttpURLConnection.HTTP_OK, response.getResponseCode());
JSONObject result = new JSONObject(response.getText());
assertEquals("4." + location, "Frodo", result.optString("Name"));
}
}
private WebRequest createSetPreferenceRequest(String location, String key, String value) throws UnsupportedEncodingException {
String body = "key=" + URLEncoder.encode(key, "UTF-8") + "&value=" + URLEncoder.encode(value, "UTF-8");
return new PutMethodWebRequest(location, new ByteArrayInputStream(body.getBytes()), "application/x-www-form-urlencoded");
}
/**
* Create locations of preference HTTP resources corresponding to our test user, workspace, and project.
*/
private List<String> getTestPreferenceNodes() {
IPath projectPath = new Path(testProjectBaseLocation);
String userId = getTestUserId();
String workspaceId = projectPath.segment(0);
String projectName = projectPath.segment(1);
String userPref = toAbsoluteURI("prefs/user/" + userId + "/testprefs");
String workspacePref = toAbsoluteURI("prefs/workspace/" + workspaceId + "/testprefs");
String projectPref = toAbsoluteURI("prefs/project/" + workspaceId + '/' + projectName + "/testprefs");
return Arrays.asList(userPref, workspacePref, projectPref);
}
/**
* Returns preference nodes the client should not have access to.
*/
private List<String> getIllegalPreferenceNodes() {
return Arrays.asList(toAbsoluteURI("prefs/Users"), toAbsoluteURI("prefs/user"), toAbsoluteURI("prefs/Workspaces"), toAbsoluteURI("prefs/workspace"), toAbsoluteURI("prefs/Projects"), toAbsoluteURI("prefs/project"));
}
}