Ray Milkey | 26921af | 2014-06-30 16:27:40 -0700 | [diff] [blame] | 1 | package net.onrc.onos.api.rest; |
| 2 | |
| 3 | import com.codahale.metrics.Histogram; |
| 4 | import net.onrc.onos.core.intent.runtime.PathCalcRuntimeModule; |
| 5 | import net.onrc.onos.core.metrics.OnosMetrics; |
| 6 | import org.json.JSONArray; |
| 7 | import org.json.JSONException; |
| 8 | import org.json.JSONObject; |
| 9 | import org.junit.After; |
| 10 | import org.junit.Before; |
| 11 | import org.junit.Test; |
| 12 | import org.junit.runner.RunWith; |
| 13 | import org.powermock.core.classloader.annotations.PrepareForTest; |
| 14 | import org.powermock.modules.junit4.PowerMockRunner; |
| 15 | import org.restlet.resource.ClientResource; |
| 16 | |
| 17 | import java.util.Arrays; |
| 18 | |
| 19 | import static org.hamcrest.MatcherAssert.assertThat; |
| 20 | import static org.hamcrest.Matchers.both; |
| 21 | import static org.hamcrest.Matchers.equalTo; |
| 22 | import static org.hamcrest.Matchers.greaterThanOrEqualTo; |
| 23 | import static org.hamcrest.Matchers.is; |
| 24 | import static org.hamcrest.Matchers.lessThanOrEqualTo; |
| 25 | import static org.hamcrest.Matchers.notNullValue; |
| 26 | |
| 27 | /** |
| 28 | * Unit tests for REST APIs for Histogram Metrics. |
| 29 | */ |
| 30 | |
| 31 | @RunWith(PowerMockRunner.class) |
| 32 | @PrepareForTest(PathCalcRuntimeModule.class) |
| 33 | public class TestRestMetricsHistograms extends TestRestMetrics { |
| 34 | |
| 35 | /** |
| 36 | * Create the web server and mocks required for |
| 37 | * all of the tests. |
| 38 | */ |
| 39 | @Before |
| 40 | @SuppressWarnings("ununsed") |
| 41 | public void beforeTest() { |
| 42 | setRestPort(generateRandomPort()); |
| 43 | setUp(); |
| 44 | } |
| 45 | |
| 46 | /** |
| 47 | * Remove anything that will interfere with the next test running correctly. |
| 48 | * Shuts down the test REST web server and removes the mocks. |
| 49 | */ |
| 50 | @After |
| 51 | @SuppressWarnings("unused") |
| 52 | public void afterTest() { |
| 53 | tearDown(); |
| 54 | } |
| 55 | |
| 56 | // Test data for Histograms |
| 57 | |
Ray Milkey | 71cd2c8 | 2014-07-16 15:02:33 -0700 | [diff] [blame^] | 58 | private static final OnosMetrics.MetricsComponent COMPONENT = |
| 59 | OnosMetrics.registerComponent("MetricsUnitTests"); |
| 60 | private static final OnosMetrics.MetricsFeature FEATURE = |
| 61 | COMPONENT.registerFeature("Histograms"); |
| 62 | |
Ray Milkey | 26921af | 2014-06-30 16:27:40 -0700 | [diff] [blame] | 63 | private static final String HISTOGRAM1_NAME = "HISTOGRAM1"; |
Ray Milkey | 49d67be | 2014-07-10 13:47:01 -0700 | [diff] [blame] | 64 | private static final String HISTOGRAM1_FULL_NAME = |
Ray Milkey | 71cd2c8 | 2014-07-16 15:02:33 -0700 | [diff] [blame^] | 65 | OnosMetrics.generateName(COMPONENT, FEATURE, HISTOGRAM1_NAME); |
| 66 | |
Ray Milkey | 26921af | 2014-06-30 16:27:40 -0700 | [diff] [blame] | 67 | private static final int[] HISTOGRAM1_VALUES = |
| 68 | {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; |
| 69 | |
| 70 | private static final String HISTOGRAM2_NAME = "HISTOGRAM2"; |
Ray Milkey | 49d67be | 2014-07-10 13:47:01 -0700 | [diff] [blame] | 71 | private static final String HISTOGRAM2_FULL_NAME = |
Ray Milkey | 71cd2c8 | 2014-07-16 15:02:33 -0700 | [diff] [blame^] | 72 | OnosMetrics.generateName(COMPONENT, FEATURE, HISTOGRAM2_NAME); |
Ray Milkey | 26921af | 2014-06-30 16:27:40 -0700 | [diff] [blame] | 73 | private static final int[] HISTOGRAM2_VALUES = |
| 74 | {100, 100, 100, 100, 100, 100, 100}; |
| 75 | |
| 76 | private static final String HISTOGRAM3_NAME = "HISTOGRAM3"; |
Ray Milkey | 49d67be | 2014-07-10 13:47:01 -0700 | [diff] [blame] | 77 | private static final String HISTOGRAM3_FULL_NAME = |
Ray Milkey | 71cd2c8 | 2014-07-16 15:02:33 -0700 | [diff] [blame^] | 78 | OnosMetrics.generateName(COMPONENT, FEATURE, HISTOGRAM3_NAME); |
Ray Milkey | 26921af | 2014-06-30 16:27:40 -0700 | [diff] [blame] | 79 | private static final int[] HISTOGRAM3_VALUES = |
| 80 | {555}; |
| 81 | |
| 82 | private final Histogram histogram1 = |
Ray Milkey | 49d67be | 2014-07-10 13:47:01 -0700 | [diff] [blame] | 83 | OnosMetrics.createHistogram( |
Ray Milkey | 71cd2c8 | 2014-07-16 15:02:33 -0700 | [diff] [blame^] | 84 | COMPONENT, |
| 85 | FEATURE, |
Ray Milkey | 49d67be | 2014-07-10 13:47:01 -0700 | [diff] [blame] | 86 | HISTOGRAM1_NAME); |
| 87 | |
Ray Milkey | 26921af | 2014-06-30 16:27:40 -0700 | [diff] [blame] | 88 | private final Histogram histogram2 = |
Ray Milkey | 49d67be | 2014-07-10 13:47:01 -0700 | [diff] [blame] | 89 | OnosMetrics.createHistogram( |
Ray Milkey | 71cd2c8 | 2014-07-16 15:02:33 -0700 | [diff] [blame^] | 90 | COMPONENT, |
| 91 | FEATURE, |
Ray Milkey | 49d67be | 2014-07-10 13:47:01 -0700 | [diff] [blame] | 92 | HISTOGRAM2_NAME); |
| 93 | |
Ray Milkey | 26921af | 2014-06-30 16:27:40 -0700 | [diff] [blame] | 94 | private final Histogram histogram3 = |
Ray Milkey | 49d67be | 2014-07-10 13:47:01 -0700 | [diff] [blame] | 95 | OnosMetrics.createHistogram( |
Ray Milkey | 71cd2c8 | 2014-07-16 15:02:33 -0700 | [diff] [blame^] | 96 | COMPONENT, |
| 97 | FEATURE, |
Ray Milkey | 49d67be | 2014-07-10 13:47:01 -0700 | [diff] [blame] | 98 | HISTOGRAM3_NAME); |
Ray Milkey | 26921af | 2014-06-30 16:27:40 -0700 | [diff] [blame] | 99 | |
| 100 | /** |
| 101 | * Add each int in an array to a Histogram. |
| 102 | * |
| 103 | * @param histogram Histogram object to update |
| 104 | * @param values list of values to add to the Histogram |
| 105 | */ |
| 106 | private void updateHistogramFromArray(final Histogram histogram, |
| 107 | final int[] values) { |
| 108 | for (final int value : values) { |
| 109 | histogram.update(value); |
| 110 | } |
| 111 | } |
| 112 | |
| 113 | /** |
| 114 | * Initialize all the Histograms. |
| 115 | */ |
| 116 | private void fillHistograms() { |
| 117 | updateHistogramFromArray(histogram1, HISTOGRAM1_VALUES); |
| 118 | updateHistogramFromArray(histogram2, HISTOGRAM2_VALUES); |
| 119 | updateHistogramFromArray(histogram3, HISTOGRAM3_VALUES); |
| 120 | } |
| 121 | |
| 122 | /** |
| 123 | * Check that a JSON object representing a histogram contains the correct |
| 124 | * data. |
| 125 | * |
| 126 | * @param histogramContainer JSON object for the Histogram |
| 127 | * @param name the name of the Histogram |
| 128 | * @param values the array of expected values in the histogram |
| 129 | * @throws JSONException if any of the JSON processing generates an error |
| 130 | */ |
| 131 | private void checkHistogram(final JSONObject histogramContainer, |
| 132 | final String name, |
| 133 | final int[] values) throws JSONException { |
| 134 | |
| 135 | // Check that the name is correct |
| 136 | final String histogramName = histogramContainer.getString("name"); |
| 137 | assertThat(histogramName, is(notNullValue())); |
| 138 | assertThat(histogramName, is(equalTo(name))); |
| 139 | |
| 140 | // Make sure a histogram is present |
| 141 | final JSONObject histogramObject = histogramContainer.getJSONObject("histogram"); |
| 142 | assertThat(histogramObject, is(notNullValue())); |
| 143 | |
| 144 | // The histogram count should equal the length of the array used to |
| 145 | // initialize it. |
| 146 | final int histogramCount = histogramObject.getInt("count"); |
| 147 | assertThat(histogramCount, is(equalTo(values.length))); |
| 148 | |
| 149 | final int[] sortedValues = Arrays.copyOf(values, values.length); |
| 150 | Arrays.sort(sortedValues); |
| 151 | |
| 152 | // max should be the largest value from the array |
| 153 | final int max = histogramObject.getInt("max"); |
| 154 | assertThat(max, is(equalTo(sortedValues[sortedValues.length - 1]))); |
| 155 | |
| 156 | // min should be the smallest value from the array |
| 157 | final int min = histogramObject.getInt("min"); |
| 158 | assertThat(min, is(equalTo(sortedValues[0]))); |
| 159 | |
| 160 | // Each of the probability values should be between the min and the max |
| 161 | // value |
| 162 | final double p999 = histogramObject.getDouble("p999"); |
| 163 | assertThat((int) p999, |
| 164 | is(both(greaterThanOrEqualTo(min)).and(lessThanOrEqualTo(max)))); |
| 165 | |
| 166 | final double p99 = histogramObject.getDouble("p99"); |
| 167 | assertThat((int) p99, |
| 168 | is(both(greaterThanOrEqualTo(min)).and(lessThanOrEqualTo(max)))); |
| 169 | |
| 170 | final double p98 = histogramObject.getDouble("p98"); |
| 171 | assertThat((int) p98, |
| 172 | is(both(greaterThanOrEqualTo(min)).and(lessThanOrEqualTo(max)))); |
| 173 | |
| 174 | final double p95 = histogramObject.getDouble("p95"); |
| 175 | assertThat((int) p95, |
| 176 | is(both(greaterThanOrEqualTo(min)).and(lessThanOrEqualTo(max)))); |
| 177 | |
| 178 | final double p75 = histogramObject.getDouble("p75"); |
| 179 | assertThat((int) p75, |
| 180 | is(both(greaterThanOrEqualTo(min)).and(lessThanOrEqualTo(max)))); |
| 181 | |
| 182 | final double p50 = histogramObject.getDouble("p50"); |
| 183 | assertThat((int) p50, |
| 184 | is(both(greaterThanOrEqualTo(min)).and(lessThanOrEqualTo(max)))); |
| 185 | |
| 186 | } |
| 187 | |
| 188 | /** |
| 189 | * Unit test for REST APIs for Histogram Metrics. |
| 190 | * |
| 191 | * @throws JSONException if any JSON processing causes an error |
| 192 | */ |
| 193 | @Test |
| 194 | public void testHistograms() throws JSONException { |
| 195 | |
| 196 | fillHistograms(); |
| 197 | |
| 198 | // Read the metrics from the REST API for the test data |
| 199 | final ClientResource client = new ClientResource(getBaseRestMetricsUrl()); |
| 200 | |
| 201 | final JSONObject metrics = getJSONObject(client); |
| 202 | assertThat(metrics.length(), is(equalTo(5))); |
| 203 | |
| 204 | // There should be 3 histograms |
| 205 | final JSONArray histograms = metrics.getJSONArray("histograms"); |
| 206 | assertThat(histograms, is(notNullValue())); |
| 207 | assertThat(histograms.length(), is(3)); |
| 208 | |
| 209 | // There should be no timers, gauges, meters or counters |
| 210 | checkEmptyLists(metrics, "timers", "gauges", "meters", "counters"); |
| 211 | |
| 212 | // Check the values for histogram 1 |
| 213 | final JSONObject histogram1Container = histograms.getJSONObject(0); |
Ray Milkey | 49d67be | 2014-07-10 13:47:01 -0700 | [diff] [blame] | 214 | checkHistogram(histogram1Container, HISTOGRAM1_FULL_NAME, HISTOGRAM1_VALUES); |
Ray Milkey | 26921af | 2014-06-30 16:27:40 -0700 | [diff] [blame] | 215 | |
| 216 | // Check the values for histogram 2 |
| 217 | final JSONObject histogram2Container = histograms.getJSONObject(1); |
Ray Milkey | 49d67be | 2014-07-10 13:47:01 -0700 | [diff] [blame] | 218 | checkHistogram(histogram2Container, HISTOGRAM2_FULL_NAME, HISTOGRAM2_VALUES); |
Ray Milkey | 26921af | 2014-06-30 16:27:40 -0700 | [diff] [blame] | 219 | |
| 220 | // Check the values for histogram 3 |
| 221 | final JSONObject histogram3Container = histograms.getJSONObject(2); |
Ray Milkey | 49d67be | 2014-07-10 13:47:01 -0700 | [diff] [blame] | 222 | checkHistogram(histogram3Container, HISTOGRAM3_FULL_NAME, HISTOGRAM3_VALUES); |
Ray Milkey | 26921af | 2014-06-30 16:27:40 -0700 | [diff] [blame] | 223 | |
| 224 | } |
| 225 | |
| 226 | } |
| 227 | |