package com.sixsq.slipstream.run; /* * +=================================================================+ * SlipStream Server (WAR) * ===== * Copyright (C) 2013 SixSq Sarl (sixsq.com) * ===== * 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. * -=================================================================- */ import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.lessThanOrEqualTo; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import java.io.FileNotFoundException; import java.io.IOException; import java.util.Map; import java.util.Properties; import java.util.logging.Logger; import javax.persistence.EntityManager; import javax.persistence.EntityTransaction; import org.junit.After; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; import org.restlet.Request; import org.restlet.Response; import org.restlet.data.Form; import org.restlet.data.Status; import org.restlet.representation.Representation; import org.restlet.representation.StringRepresentation; import com.sixsq.slipstream.exceptions.AbortException; import com.sixsq.slipstream.exceptions.ConfigurationException; import com.sixsq.slipstream.exceptions.NotFoundException; import com.sixsq.slipstream.exceptions.SlipStreamException; import com.sixsq.slipstream.exceptions.ValidationException; import com.sixsq.slipstream.persistence.PersistenceUtil; import com.sixsq.slipstream.persistence.Run; import com.sixsq.slipstream.persistence.RuntimeParameter; public class RuntimeParameterResourceTest extends RuntimeParameterResourceTestBase { @BeforeClass public static void classSetup() throws ValidationException { RuntimeParameterResourceTestBase.classSetup(); } @AfterClass public static void classTearDown() throws ValidationException { RuntimeParameterResourceTestBase.classTearDown(); } @After public void tearDown() { super.tearDown(); } @Test public void runtimeParameterResourceGetUnknownUuid() throws ConfigurationException, ValidationException { Request request = createGetRequest("unknownUuid", "aKey"); Response response = executeRequest(request); assertEquals(Status.CLIENT_ERROR_NOT_FOUND, response.getStatus()); } @Test public void runtimeParameterResourceGetUnknownKey() throws IOException, SlipStreamException { Run run = createAndStoreRunImage("RuntimeParameterResourceGetUnknownKey"); Request request = createGetRequest(run.getUuid(), "unknownKey"); Response response = executeRequest(request); assertEquals(Status.CLIENT_ERROR_NOT_FOUND, response.getStatus()); run = Run.loadFromUuid(run.getUuid()); assertAbortSet(run); run.remove(); } @Test public void runtimeParameterResourceGetNotYetSetValue() throws IOException, SlipStreamException { Run run = createAndStoreRunImage("runtimeParameterResourceGetNotYetSetValue"); Request request = createGetRequest(run.getUuid(), "ss:abort"); Response response = executeRequest(request); assertEquals(Status.CLIENT_ERROR_PRECONDITION_FAILED, response.getStatus()); assertAbortNotSet(run); run.remove(); } @Test public void runtimeParameterResourceGet() throws IOException, SlipStreamException { Run run = createAndStoreRunImage("RuntimeParameterResourceGet"); String key = "node.1:key"; String value = "value of key"; storeRuntimeParameter(key, value, run); executeGetRequestAndAssertValue(run, key, value); run.remove(); } private void storeRuntimeParameter(String key, String value, Run run) throws ValidationException, NotFoundException { run.assignRuntimeParameter(key, value, ""); run.store(); } @Test public void runtimeParameterResourcePutExisting() throws IOException, SlipStreamException { Run run = createAndStoreRunImage("runtimeParameterResourcePutExisting"); String key = "node.1:key"; String value = "value of key"; run.assignRuntimeParameter(key, value, ""); run.store(); Request request = createPutRequest(run.getUuid(), key, new StringRepresentation(value)); executeRequest(request); RuntimeParameter runtimeParameter = RuntimeParameter.loadFromUuidAndKey(run.getUuid(), key); run.remove(); assertNotNull(runtimeParameter); assertEquals("value of key", runtimeParameter.getValue()); assertAbortNotSet(run); } private void assertAbortNotSet(Run run) { assertThat(run.getRuntimeParameters().get("ss:abort").isSet(), is(false)); } private void assertAbortSet(Run run) { EntityManager em = PersistenceUtil.createEntityManager(); EntityTransaction transaction = em.getTransaction(); transaction.begin(); run = em.merge(run); assertThat(run.getRuntimeParameters().get("ss:abort").isSet(), is(true)); transaction.commit(); em.close(); } @Test public void runtimeParameterResourcePutNotExisting() throws IOException, SlipStreamException { Run run = createAndStoreRunImage("runtimeParameterResourcePutNotExisting"); String key = "node.1:key"; Form form = new Form(); String value = "value of key"; form.add("value", value); Representation entity = form.getWebRepresentation(); Request request = createPutRequest(run.getUuid(), key, entity); Response response = executeRequest(request); run.remove(); assertThat(response.getStatus(), is(Status.CLIENT_ERROR_NOT_FOUND)); } @Test public void runtimeParameterResourcePutTooLong() throws IOException, SlipStreamException { Run run = createAndStoreRunImage("runtimeParameterResourcePutTooLong"); String key = "node.1:key"; String value = new String(new char[RuntimeParameter.VALUE_MAX_LENGTH+1]).replace('\0', 'x'); run.assignRuntimeParameter(key, "", ""); run.store(); Request request = createPutRequest(run.getUuid(), key, new StringRepresentation(value)); Response response = executeRequest(request); run.remove(); assertThat(response.getStatus().getCode(), is(Status.CLIENT_ERROR_BAD_REQUEST.getCode())); } @Test public void runtimeParameterResourcePutAbortTooLong() throws IOException, SlipStreamException { Run run = createAndStoreRunImage("runtimeParameterResourcePutAbortTooLong"); String key = "node.1:abort"; String value = new String(new char[RuntimeParameter.VALUE_MAX_LENGTH+1]).replace('\0', 'x'); run.assignRuntimeParameter(key, "", ""); run.store(); Request request = createPutRequest(run.getUuid(), key, new StringRepresentation(value)); Response response = executeRequest(request); RuntimeParameter runtimeParameter = RuntimeParameter.loadFromUuidAndKey(run.getUuid(), key); run.remove(); assertNotNull(runtimeParameter); assertThat(runtimeParameter.getValue().length(), lessThanOrEqualTo(RuntimeParameter.VALUE_MAX_LENGTH)); assertThat(response.getStatus(), is(Status.SUCCESS_OK)); } @Test public void runtimeParameterRetrieveFromContainerRun() throws IOException, SlipStreamException { Run run = createAndStoreRunImage("RuntimeParameterRetrieveFromContainerRun"); String key = "node.1:key"; String value = "value of key"; storeRuntimeParameter(key, value, run); EntityManager em = PersistenceUtil.createEntityManager(); run = Run.loadFromUuid(run.getUuid(), em); assertNotNull(run); assertEquals("value of key", run.getRuntimeParameterValue(key)); em.close(); run.remove(); } @Test public void runtimeParameterReset() throws SlipStreamException, IOException { String key = "node.1:key"; String value = "value of key"; Run run = createAndStoreRunWithRuntimeParameter("runtimeParameterReset", key, value); assertNotNull(run); assertEquals(value, run.getRuntimeParameterValue(key)); Request request = createDeleteRequest(run.getUuid(), key); Response response = executeRequest(request); assertEquals(Status.SUCCESS_NO_CONTENT, response.getStatus()); assertRuntimeParameterWasReset(run, key); run.remove(); } private void assertRuntimeParameterWasReset(Run run, String key) throws AbortException { RuntimeParameter rtp = RuntimeParameter.loadFromUuidAndKey(run.getUuid(), key); assertNotNull(rtp); assertThat(rtp.isSet(), is(false)); } @Test public void wrongNodeTriggersAbort() throws SlipStreamException, IOException { String key = "wrong.1:key"; Run run = createAndStoreRunImage("wrongNodeTriggersAbort"); Request request = createGetRequest(run.getUuid(), key); Response response = executeRequest(request); assertEquals(Status.CLIENT_ERROR_NOT_FOUND, response.getStatus()); run = Run.loadFromUuid(run.getUuid()); assertAbortSet(run); run.remove(); } @Test public void wrongKeyTriggersAbort() throws SlipStreamException, IOException { String key = "ss:wrong"; Run run = createAndStoreRunImage("wrongKeyTriggersAbort"); Request request = createGetRequest(run.getUuid(), key); Response response = executeRequest(request); assertEquals(Status.CLIENT_ERROR_NOT_FOUND, response.getStatus()); run = Run.loadFromUuid(run.getUuid()); assertAbortSet(run); run.remove(); } @Test public void cantSetAbortTwice() throws SlipStreamException, IOException { String key = "ss:abort"; Run run = createAndStoreRunImage("cantSetAbortTwice"); Request request = createPutRequest(run.getUuid(), key, new StringRepresentation("first abort")); Response response = executeRequest(request); assertEquals(Status.SUCCESS_OK, response.getStatus()); RuntimeParameter abort = RuntimeParameter.loadFromUuidAndKey(run.getUuid(), "ss:abort"); assertThat(abort.getValue(), is("first abort")); request = createPutRequest(run.getUuid(), key, new StringRepresentation("second abort")); response = executeRequest(request); assertEquals(Status.CLIENT_ERROR_CONFLICT, response.getStatus()); abort = RuntimeParameter.loadFromUuidAndKey(run.getUuid(), "ss:abort"); assertThat(abort.getValue(), is("first abort")); run.remove(); } @Test public void errorSetsNodeAndGlobalAbort() throws IOException, SlipStreamException { String machineAbortKey = Run.MACHINE_NAME_PREFIX.toLowerCase() + RuntimeParameter.ABORT_KEY; String globalAbortKey = RuntimeParameter.GLOBAL_ABORT_KEY; String abortMessage = "machine abort"; Run run = createAndStoreRunImage("errorSetsNodeAndGlobalAbort"); Request request = createPutRequest(run.getUuid(), machineAbortKey, new StringRepresentation(abortMessage)); Response response = executeRequest(request); assertEquals(Status.SUCCESS_OK, response.getStatus()); RuntimeParameter nodeAbort = RuntimeParameter.loadFromUuidAndKey(run.getUuid(), machineAbortKey); assertThat(nodeAbort.getValue(), is(abortMessage)); RuntimeParameter globalAbort = RuntimeParameter.loadFromUuidAndKey(run.getUuid(), globalAbortKey); assertThat(globalAbort.getValue(), is(abortMessage)); } @Test public void cancelAbort() throws IOException, SlipStreamException { String machineAbortKey = Run.MACHINE_NAME_PREFIX.toLowerCase() + RuntimeParameter.ABORT_KEY; String globalAbortKey = RuntimeParameter.GLOBAL_ABORT_KEY; String abortMessage = "machine abort"; Run run = createAndStoreRunImage("errorSetsNodeAndGlobalAbort"); Request request = createPutRequest(run.getUuid(), machineAbortKey, new StringRepresentation(abortMessage)); Response response = executeRequest(request); assertEquals(Status.SUCCESS_OK, response.getStatus()); RuntimeParameter nodeAbort = RuntimeParameter.loadFromUuidAndKey(run.getUuid(), machineAbortKey); assertThat(nodeAbort.getValue(), is(abortMessage)); assertThat(nodeAbort.isSet(), is(true)); RuntimeParameter globalAbort = RuntimeParameter.loadFromUuidAndKey(run.getUuid(), globalAbortKey); assertThat(globalAbort.getValue(), is(abortMessage)); assertThat(globalAbort.isSet(), is(true)); Map<String, Object> attributes = createRequestAttributes(run.getUuid(), ""); attributes.put(RunListResource.IGNORE_ABORT_QUERY, "true"); attributes.put("key", machineAbortKey); request = createDeleteRequest(attributes); response = executeRequest(request); assertEquals(Status.SUCCESS_NO_CONTENT, response.getStatus()); attributes.put("key", globalAbortKey); request = createDeleteRequest(attributes); response = executeRequest(request); assertEquals(Status.SUCCESS_NO_CONTENT, response.getStatus()); nodeAbort = RuntimeParameter.loadFromUuidAndKey(run.getUuid(), machineAbortKey); assertThat(nodeAbort.getValue(), is("")); assertThat(nodeAbort.isSet(), is(false)); globalAbort = RuntimeParameter.loadFromUuidAndKey(run.getUuid(), globalAbortKey); assertThat(globalAbort.getValue(), is("")); assertThat(globalAbort.isSet(), is(false)); } @Test public void runtimeParameterResourceGetStress() throws IOException, SlipStreamException { Run run = createAndStoreRunImage("runtimeParameterResourceGetStress"); String key = "node.1:key"; String value = "value of key"; storeRuntimeParameter(key, value, run); Long before = System.currentTimeMillis(); for (int i = 0; i < 1000; i++) { executeGetRequestAndAssertValue(run, key, value); } logTimeDiff("parseRequest", before); run.remove(); } @Test public void isAbort() throws IOException, SlipStreamException { Run run = createAndStoreRunImage("isAbort"); boolean isAbort = RuntimeParameter.isAbort(run.getUuid()); assertThat(isAbort, is(false)); RuntimeParameter abort = RuntimeParameter.loadFromUuidAndKey(run.getUuid(), "ss:abort"); abort.setValue("abort!"); abort.store(); isAbort = RuntimeParameter.isAbort(run.getUuid()); assertThat(isAbort, is(true)); run.remove(); } @Test public void getValueAndSet() throws IOException, SlipStreamException { Run run = createAndStoreRunImage("getValueAndSet"); String key = "node.1:key"; storeRuntimeParameter(key, "", run); RuntimeParameter rp = RuntimeParameter.loadFromUuidAndKey(run.getUuid(), key); Properties p = RuntimeParameter.getValueAndSet(run.getUuid(), key); String value = (String) p.get("value"); boolean isSet = (Boolean) p.get("isSet"); assertThat(value, is("")); assertFalse(isSet); rp = RuntimeParameter.loadFromUuidAndKey(run.getUuid(), key); value = "value of key"; rp.setValue(value); rp.store(); p = RuntimeParameter.getValueAndSet(run.getUuid(), key); value = (String) p.get("value"); isSet = (Boolean) p.get("isSet"); assertThat(value, is("value of key")); assertTrue(isSet); run.remove(); } @Test public void runtimeParameterResourceGetSsGroups() throws IOException, SlipStreamException { Run run = createAndStoreRunImage("runtimeParameterResourceGetSsGroups"); String key = "ss:groups"; String value = "local:machine"; executeGetRequestAndAssertValue(run, key, value); run.remove(); } private void logTimeDiff(String msg, long before, long after) { Logger.getLogger("Timing").severe("took to execute " + msg + ": " + (after - before)); } protected void logTimeDiff(String msg, long before) { logTimeDiff(msg, before, System.currentTimeMillis()); } }