Ray Milkey | 213e56a | 2014-06-23 10:45:45 -0700 | [diff] [blame] | 1 | package net.onrc.onos.api.rest; |
| 2 | |
| 3 | |
| 4 | import com.google.common.net.InetAddresses; |
| 5 | import net.onrc.onos.core.intent.IntentOperation; |
| 6 | import net.onrc.onos.core.intent.IntentOperationList; |
| 7 | import net.onrc.onos.core.intent.ShortestPathIntent; |
| 8 | import net.onrc.onos.core.intent.runtime.PathCalcRuntimeModule; |
| 9 | import org.json.JSONArray; |
| 10 | import org.json.JSONException; |
| 11 | import org.json.JSONObject; |
Ray Milkey | 213e56a | 2014-06-23 10:45:45 -0700 | [diff] [blame] | 12 | import org.junit.Assert; |
Ray Milkey | 213e56a | 2014-06-23 10:45:45 -0700 | [diff] [blame] | 13 | import org.junit.Test; |
| 14 | import org.junit.runner.RunWith; |
| 15 | import org.powermock.core.classloader.annotations.PrepareForTest; |
| 16 | import org.powermock.modules.junit4.PowerMockRunner; |
| 17 | import org.restlet.data.Status; |
| 18 | import org.restlet.resource.ClientResource; |
| 19 | import org.restlet.resource.ResourceException; |
| 20 | |
| 21 | import static net.onrc.onos.api.rest.ClientResourceStatusMatcher.hasStatusOf; |
| 22 | import static org.hamcrest.MatcherAssert.assertThat; |
| 23 | import static org.hamcrest.Matchers.containsString; |
| 24 | import static org.hamcrest.Matchers.equalTo; |
| 25 | import static org.hamcrest.Matchers.is; |
| 26 | import static org.hamcrest.Matchers.notNullValue; |
| 27 | |
| 28 | /** |
| 29 | * Unit tests to test the Intents GET REST APIs. |
| 30 | */ |
| 31 | @RunWith(PowerMockRunner.class) |
| 32 | @PrepareForTest(PathCalcRuntimeModule.class) |
| 33 | public class TestRestIntentLowGet extends TestRestIntent { |
| 34 | private static final Long LOCAL_PORT = 0xFFFEL; |
| 35 | private static final String BAD_SWITCH_INTENT_NAME = "No Such Switch Intent"; |
| 36 | private static final String IP_ADDRESS_1 = "127.0.0.1"; |
| 37 | private static final String IP_ADDRESS_2 = "127.0.0.2"; |
| 38 | private static final String IP_ADDRESS_3 = "127.0.0.3"; |
| 39 | |
| 40 | /** |
Ray Milkey | 213e56a | 2014-06-23 10:45:45 -0700 | [diff] [blame] | 41 | * Make a set of Intents that can be used as test data. |
| 42 | */ |
| 43 | private void makeDefaultIntents() { |
| 44 | final int ipAddress1AsInt = InetAddresses.coerceToInteger( |
| 45 | InetAddresses.forString(IP_ADDRESS_1)); |
| 46 | final int ipAddress2AsInt = InetAddresses.coerceToInteger( |
| 47 | InetAddresses.forString(IP_ADDRESS_2)); |
| 48 | final int ipAddress3AsInt = InetAddresses.coerceToInteger( |
| 49 | InetAddresses.forString(IP_ADDRESS_3)); |
| 50 | |
| 51 | // create shortest path intents |
| 52 | final IntentOperationList opList = new IntentOperationList(); |
| 53 | opList.add(IntentOperation.Operator.ADD, |
| 54 | new ShortestPathIntent(BAD_SWITCH_INTENT_NAME, 111L, 12L, |
| 55 | LOCAL_PORT, 2L, 21L, LOCAL_PORT)); |
| 56 | opList.add(IntentOperation.Operator.ADD, |
| 57 | new ShortestPathIntent("1:2", 1L, 14L, LOCAL_PORT, ipAddress1AsInt, |
| 58 | 4L, 41L, LOCAL_PORT, ipAddress2AsInt)); |
| 59 | opList.add(IntentOperation.Operator.ADD, |
| 60 | new ShortestPathIntent("1:3", 2L, 23L, LOCAL_PORT, ipAddress2AsInt, |
| 61 | 3L, 32L, LOCAL_PORT, ipAddress3AsInt)); |
| 62 | |
| 63 | // compile high-level intent operations into low-level intent |
| 64 | // operations (calculate paths) |
| 65 | |
| 66 | final IntentOperationList pathIntentOpList = |
| 67 | getRuntime().executeIntentOperations(opList); |
| 68 | assertThat(pathIntentOpList, notNullValue()); |
| 69 | |
| 70 | } |
| 71 | |
| 72 | /** |
| 73 | * Find the intent with the given ID in the intent array. |
| 74 | * |
| 75 | * @param intents array of intents |
| 76 | * @param id this is the id too look up |
| 77 | * @return JSONObject for the intent if found, null otherwise |
| 78 | * @throws JSONException if the intent object marshalling fails |
| 79 | */ |
| 80 | private JSONObject findIntent(final JSONArray intents, final String id) |
| 81 | throws JSONException { |
| 82 | |
| 83 | if (id == null) { |
| 84 | return null; |
| 85 | } |
| 86 | |
| 87 | JSONObject result = null; |
| 88 | for (int intentIndex = 0; intentIndex < intents.length(); intentIndex++) { |
| 89 | final JSONObject thisIntent = intents.getJSONObject(intentIndex); |
| 90 | if (id.equals(thisIntent.getString("id"))) { |
| 91 | result = thisIntent; |
| 92 | } |
| 93 | } |
| 94 | |
| 95 | return result; |
| 96 | } |
| 97 | |
| 98 | /** |
| 99 | * Test that the GET of all Intents REST call returns the proper result. |
| 100 | * The call to get all Intents should return 3 items, an HTTP status of OK, |
| 101 | * and the proper Intent data. |
| 102 | * |
| 103 | * @throws Exception to fail the test if any unhandled errors occur |
| 104 | */ |
| 105 | @Test |
| 106 | public void testFetchOfAllLowLevelIntents() throws Exception { |
| 107 | |
| 108 | makeDefaultIntents(); |
| 109 | |
| 110 | final ClientResource client = new ClientResource(getLowRestIntentUrl()); |
| 111 | final JSONArray intents = getJSONArray(client); |
| 112 | assertThat(intents, is(notNullValue())); |
| 113 | |
| 114 | // HTTP status should be OK |
| 115 | assertThat(client, hasStatusOf(Status.SUCCESS_OK)); |
| 116 | |
| 117 | // 2 low level intents should have been fetched - one of the |
| 118 | // high level intents is in error |
| 119 | assertThat(intents.length(), is(equalTo(2))); |
| 120 | |
| 121 | // Check that intent 0 is correct |
| 122 | final JSONObject intent0 = findIntent(intents, "1:2___0"); |
| 123 | assertThat(intent0, is(notNullValue())); |
| 124 | |
| 125 | // Check the values of the fields in low level intent 0 |
| 126 | assertThat(intent0.getString("id"), is(equalTo("1:2___0"))); |
| 127 | assertThat(intent0.getString("state"), is(equalTo("INST_REQ"))); |
| 128 | assertThat(intent0.getBoolean("pathFrozen"), is(equalTo(false))); |
| 129 | |
| 130 | // Check the path on intent 0 |
| 131 | final JSONArray path0 = intent0.getJSONArray("path"); |
| 132 | assertThat(path0, is(notNullValue())); |
| 133 | final JSONObject ports0 = path0.getJSONObject(0); |
| 134 | assertThat(ports0, is(notNullValue())); |
| 135 | final JSONObject dst0 = ports0.getJSONObject("dst"); |
| 136 | assertThat(dst0, is(notNullValue())); |
Pavlin Radoslavov | 5cf1fe0 | 2014-07-03 22:52:25 -0700 | [diff] [blame] | 137 | final String dstDpid0 = dst0.getString("dpid"); |
| 138 | assertThat(dstDpid0, is(equalTo("00:00:00:00:00:00:00:04"))); |
| 139 | int dstPortNumber0 = dst0.getInt("portNumber"); |
| 140 | assertThat(dstPortNumber0, is(equalTo(41))); |
Ray Milkey | 213e56a | 2014-06-23 10:45:45 -0700 | [diff] [blame] | 141 | final JSONObject src0 = ports0.getJSONObject("src"); |
| 142 | assertThat(src0, is(notNullValue())); |
Pavlin Radoslavov | 5cf1fe0 | 2014-07-03 22:52:25 -0700 | [diff] [blame] | 143 | final String srcDpid0 = src0.getString("dpid"); |
| 144 | assertThat(srcDpid0, is(equalTo("00:00:00:00:00:00:00:01"))); |
| 145 | int srcPortNumber0 = src0.getInt("portNumber"); |
| 146 | assertThat(srcPortNumber0, is(equalTo(14))); |
Ray Milkey | 213e56a | 2014-06-23 10:45:45 -0700 | [diff] [blame] | 147 | |
| 148 | // Check that intent 1 is correct |
| 149 | final JSONObject intent1 = findIntent(intents, "1:3___0"); |
| 150 | assertThat(intent1, is(notNullValue())); |
| 151 | |
| 152 | // Check the values of the fields in low level intent 1 |
| 153 | assertThat(intent1.getString("id"), is(equalTo("1:3___0"))); |
| 154 | assertThat(intent1.getString("state"), is(equalTo("INST_REQ"))); |
| 155 | assertThat(intent1.getBoolean("pathFrozen"), is(equalTo(false))); |
| 156 | |
| 157 | // Check the path on intent 1 |
| 158 | final JSONArray path1 = intent1.getJSONArray("path"); |
| 159 | assertThat(path1, is(notNullValue())); |
| 160 | final JSONObject ports1 = path1.getJSONObject(0); |
| 161 | assertThat(ports1, is(notNullValue())); |
| 162 | final JSONObject dst1 = ports1.getJSONObject("dst"); |
| 163 | assertThat(dst1, is(notNullValue())); |
Pavlin Radoslavov | 5cf1fe0 | 2014-07-03 22:52:25 -0700 | [diff] [blame] | 164 | final String dstDpid1 = dst1.getString("dpid"); |
| 165 | assertThat(dstDpid1, is(equalTo("00:00:00:00:00:00:00:03"))); |
| 166 | int dstPortNumber1 = dst1.getInt("portNumber"); |
| 167 | assertThat(dstPortNumber1, is(equalTo(32))); |
Ray Milkey | 213e56a | 2014-06-23 10:45:45 -0700 | [diff] [blame] | 168 | final JSONObject src1 = ports1.getJSONObject("src"); |
| 169 | assertThat(src1, is(notNullValue())); |
Pavlin Radoslavov | 5cf1fe0 | 2014-07-03 22:52:25 -0700 | [diff] [blame] | 170 | final String srcDpid1 = src1.getString("dpid"); |
| 171 | assertThat(srcDpid1, is(equalTo("00:00:00:00:00:00:00:02"))); |
| 172 | int srcPortNumber1 = src1.getInt("portNumber"); |
| 173 | assertThat(srcPortNumber1, is(equalTo(23))); |
Ray Milkey | 213e56a | 2014-06-23 10:45:45 -0700 | [diff] [blame] | 174 | } |
| 175 | |
| 176 | /** |
| 177 | * Test that the GET of a single Intent REST call returns the proper result |
| 178 | * when given a bad Intent id. The call to get the Intent should return a |
| 179 | * status of NOT_FOUND. |
| 180 | * |
| 181 | * @throws JSONException if a bad JSON object is returned for the error |
| 182 | */ |
| 183 | @Test |
| 184 | public void testFetchOfBadLowLevelIntent() throws JSONException { |
| 185 | |
| 186 | makeDefaultIntents(); |
| 187 | |
| 188 | final ClientResource client = new ClientResource(getLowRestIntentUrl() + "/2334"); |
| 189 | |
| 190 | try { |
| 191 | client.get(); |
| 192 | // The get operation should have thrown a ResourceException. |
| 193 | // Fail because the Exception was not seen. |
| 194 | Assert.fail("Invalid intent fetch did not cause an exception"); |
| 195 | } catch (ResourceException resourceError) { |
| 196 | // The HTTP status should be NOT FOUND |
| 197 | assertThat(client, hasStatusOf(Status.CLIENT_ERROR_NOT_FOUND)); |
| 198 | |
| 199 | // Check that the error entity is correct |
| 200 | final String responseErrorString = client.getResponse().getEntityAsText(); |
| 201 | final JSONObject responseError = new JSONObject(responseErrorString); |
| 202 | assertThat(responseError.getString("code"), |
| 203 | is(equalTo("INTENT_NOT_FOUND"))); |
| 204 | assertThat(responseError.getString("summary"), |
| 205 | is(equalTo("Intent not found"))); |
| 206 | assertThat(responseError.getString("formattedDescription"), |
| 207 | containsString("An intent with the identifier")); |
| 208 | } |
| 209 | } |
| 210 | |
| 211 | /** |
| 212 | * Test that the GET of a single Low Level Intent REST call returns the |
| 213 | * proper result for an existing Intent. The call to get the Low Level |
| 214 | * Intent should return a status of OK, and the data for the |
| 215 | * Low Level Intent should be correct. |
| 216 | * |
| 217 | * @throws JSONException if the JSON cannot be marshalled into an object. |
| 218 | */ |
| 219 | @Test |
| 220 | public void testFetchOfGoodLowLevelIntent() throws JSONException { |
| 221 | |
| 222 | makeDefaultIntents(); |
| 223 | |
| 224 | final ClientResource client = new ClientResource(getLowRestIntentUrl() + "/3___0"); |
| 225 | final JSONObject intent = getJSONObject(client); |
| 226 | |
| 227 | // HTTP status should be OK |
| 228 | assertThat(client, hasStatusOf(Status.SUCCESS_OK)); |
| 229 | |
| 230 | // Intent data should be correct |
| 231 | assertThat(intent, is(notNullValue())); |
| 232 | |
| 233 | assertThat(intent.getString("id"), is(equalTo("1:3___0"))); |
| 234 | assertThat(intent.getString("state"), is(equalTo("INST_REQ"))); |
| 235 | assertThat(intent.getBoolean("pathFrozen"), is(false)); |
| 236 | } |
| 237 | } |
| 238 | |