1 package org.onap.aai.sparky.sync;
3 import static org.junit.Assert.assertEquals;
4 import static org.junit.Assert.assertNotNull;
5 import static org.junit.Assert.assertTrue;
7 import java.security.SecureRandom;
8 import java.util.ArrayList;
9 import java.util.HashMap;
10 import java.util.List;
12 import java.util.regex.Pattern;
14 import org.junit.Before;
15 import org.junit.Test;
16 import org.mockito.Mockito;
17 import org.onap.aai.cl.api.Logger;
18 import org.onap.aai.cl.eelf.LoggerFactory;
19 import org.onap.aai.restclient.client.OperationResult;
20 import org.onap.aai.sparky.config.oxm.SearchableEntityLookup;
21 import org.onap.aai.sparky.config.oxm.SearchableOxmEntityDescriptor;
22 import org.onap.aai.sparky.dal.ActiveInventoryAdapter;
23 import org.onap.aai.sparky.dal.ElasticSearchAdapter;
24 import org.onap.aai.sparky.dal.NetworkTransaction;
25 import org.onap.aai.sparky.dal.rest.HttpMethod;
26 import org.onap.aai.sparky.sync.config.NetworkStatisticsConfig;
30 public class AbstractEntitySynchronizerTest {
32 public class QuantumSynchronizer extends AbstractEntitySynchronizer {
34 private boolean amIDone;
35 private SearchableEntityLookup searchableEntityLookup;
37 protected QuantumSynchronizer(Logger logger, String syncName, int numSyncWorkers, int numActiveInventoryWorkers,
38 int numElasticsearchWorkers, String indexName, NetworkStatisticsConfig aaiStatConfig,
39 NetworkStatisticsConfig esStatConfig) throws Exception {
40 super(logger, syncName, numSyncWorkers, numActiveInventoryWorkers, numElasticsearchWorkers, indexName,
41 aaiStatConfig, esStatConfig);
47 public void setSearchableEntityLookup(SearchableEntityLookup searchableEntityLookup) {
48 this.searchableEntityLookup = searchableEntityLookup;
51 public void initCounters() {
52 if (this.searchableEntityLookup != null) {
54 .intializeEntityCounters(searchableEntityLookup.getSearchableEntityDescriptors().keySet());
56 .intializeEntityCounters(searchableEntityLookup.getSearchableEntityDescriptors().keySet());
61 public void setSyncDone(boolean done) {
66 protected boolean isSyncDone() {
72 private static Logger LOG = LoggerFactory.getInstance().getLogger(AbstractEntitySynchronizerTest.class);
73 private static SecureRandom secureRandom = new SecureRandom();
75 private QuantumSynchronizer quantumSync;
76 private NetworkStatisticsConfig aaiStatConfig;
77 private NetworkStatisticsConfig esStatConfig;
78 private ElasticSearchAdapter esAdapter;
79 private ActiveInventoryAdapter aaiAdapter;
80 private SearchableEntityLookup searchableEntityLookup;
84 public void init() throws Exception {
86 aaiStatConfig = new NetworkStatisticsConfig();
88 aaiStatConfig.setNumSamplesPerThreadForRunningAverage(100);
90 aaiStatConfig.setBytesHistogramLabel("[Response Size In Bytes]");
91 aaiStatConfig.setBytesHistogramMaxYAxis(1000000L);
92 aaiStatConfig.setBytesHistogramNumBins(20);
93 aaiStatConfig.setBytesHistogramNumDecimalPoints(2);
95 aaiStatConfig.setQueueLengthHistogramLabel("[Queue Item Length]");
96 aaiStatConfig.setQueueLengthHistogramMaxYAxis(20000);
97 aaiStatConfig.setQueueLengthHistogramNumBins(20);
98 aaiStatConfig.setQueueLengthHistogramNumDecimalPoints(2);
100 aaiStatConfig.setTaskAgeHistogramLabel("[Task Age In Ms]");
101 aaiStatConfig.setTaskAgeHistogramMaxYAxis(600000L);
102 aaiStatConfig.setTaskAgeHistogramNumBins(20);
103 aaiStatConfig.setTaskAgeHistogramNumDecimalPoints(2);
105 aaiStatConfig.setResponseTimeHistogramLabel("[Response Time In Ms]");
106 aaiStatConfig.setResponseTimeHistogramMaxYAxis(1000L);
107 aaiStatConfig.setResponseTimeHistogramNumBins(20);
108 aaiStatConfig.setResponseTimeHistogramNumDecimalPoints(2);
110 aaiStatConfig.setTpsHistogramLabel("[Transactions Per Second]");
111 aaiStatConfig.setTpsHistogramMaxYAxis(100);
112 aaiStatConfig.setTpsHistogramNumBins(20);
113 aaiStatConfig.setTpsHistogramNumDecimalPoints(2);
115 esStatConfig = new NetworkStatisticsConfig();
117 esStatConfig.setNumSamplesPerThreadForRunningAverage(100);
119 esStatConfig.setBytesHistogramLabel("[Response Size In Bytes]");
120 esStatConfig.setBytesHistogramMaxYAxis(1000000L);
121 esStatConfig.setBytesHistogramNumBins(20);
122 esStatConfig.setBytesHistogramNumDecimalPoints(2);
124 esStatConfig.setQueueLengthHistogramLabel("[Queue Item Length]");
125 esStatConfig.setQueueLengthHistogramMaxYAxis(20000);
126 esStatConfig.setQueueLengthHistogramNumBins(20);
127 esStatConfig.setQueueLengthHistogramNumDecimalPoints(2);
129 esStatConfig.setTaskAgeHistogramLabel("[Task Age In Ms]");
130 esStatConfig.setTaskAgeHistogramMaxYAxis(600000L);
131 esStatConfig.setTaskAgeHistogramNumBins(20);
132 esStatConfig.setTaskAgeHistogramNumDecimalPoints(2);
134 esStatConfig.setResponseTimeHistogramLabel("[Response Time In Ms]");
135 esStatConfig.setResponseTimeHistogramMaxYAxis(10000L);
136 esStatConfig.setResponseTimeHistogramNumBins(20);
137 esStatConfig.setResponseTimeHistogramNumDecimalPoints(2);
139 esStatConfig.setTpsHistogramLabel("[Transactions Per Second]");
140 esStatConfig.setTpsHistogramMaxYAxis(100);
141 esStatConfig.setTpsHistogramNumBins(20);
142 esStatConfig.setTpsHistogramNumDecimalPoints(2);
144 esAdapter = Mockito.mock(ElasticSearchAdapter.class);
145 aaiAdapter = Mockito.mock(ActiveInventoryAdapter.class);
150 public void validateNetworkStatConfig() {
152 // validate aaiStatConfig
154 assertEquals(100, aaiStatConfig.getNumSamplesPerThreadForRunningAverage());
156 assertEquals("[Response Size In Bytes]",aaiStatConfig.getBytesHistogramLabel());
157 assertEquals(1000000L,aaiStatConfig.getBytesHistogramMaxYAxis());
158 assertEquals(20,aaiStatConfig.getBytesHistogramNumBins());
159 assertEquals(2,aaiStatConfig.getBytesHistogramNumDecimalPoints());
161 assertEquals("[Queue Item Length]",aaiStatConfig.getQueueLengthHistogramLabel());
162 assertEquals(20000,aaiStatConfig.getQueueLengthHistogramMaxYAxis());
163 assertEquals(20,aaiStatConfig.getQueueLengthHistogramNumBins());
164 assertEquals(2,aaiStatConfig.getQueueLengthHistogramNumDecimalPoints());
166 assertEquals("[Task Age In Ms]",aaiStatConfig.getTaskAgeHistogramLabel());
167 assertEquals(600000L,aaiStatConfig.getTaskAgeHistogramMaxYAxis());
168 assertEquals(20,aaiStatConfig.getTaskAgeHistogramNumBins());
169 assertEquals(2,aaiStatConfig.getTaskAgeHistogramNumDecimalPoints());
171 assertEquals("[Response Time In Ms]",aaiStatConfig.getResponseTimeHistogramLabel());
172 assertEquals(1000L,aaiStatConfig.getResponseTimeHistogramMaxYAxis());
173 assertEquals(20,aaiStatConfig.getResponseTimeHistogramNumBins());
174 assertEquals(2, aaiStatConfig.getResponseTimeHistogramNumDecimalPoints());
176 assertEquals("[Transactions Per Second]",aaiStatConfig.getTpsHistogramLabel());
177 assertEquals(100,aaiStatConfig.getTpsHistogramMaxYAxis());
178 assertEquals(20,aaiStatConfig.getTpsHistogramNumBins());
179 assertEquals(2,aaiStatConfig.getTpsHistogramNumDecimalPoints());
181 // validate esStatConfig
183 assertEquals(100, esStatConfig.getNumSamplesPerThreadForRunningAverage());
185 assertEquals("[Response Size In Bytes]",esStatConfig.getBytesHistogramLabel());
186 assertEquals(1000000L,esStatConfig.getBytesHistogramMaxYAxis());
187 assertEquals(20,esStatConfig.getBytesHistogramNumBins());
188 assertEquals(2,esStatConfig.getBytesHistogramNumDecimalPoints());
190 assertEquals("[Queue Item Length]",esStatConfig.getQueueLengthHistogramLabel());
191 assertEquals(20000,esStatConfig.getQueueLengthHistogramMaxYAxis());
192 assertEquals(20,esStatConfig.getQueueLengthHistogramNumBins());
193 assertEquals(2,esStatConfig.getQueueLengthHistogramNumDecimalPoints());
195 assertEquals("[Task Age In Ms]",esStatConfig.getTaskAgeHistogramLabel());
196 assertEquals(600000L,esStatConfig.getTaskAgeHistogramMaxYAxis());
197 assertEquals(20,esStatConfig.getTaskAgeHistogramNumBins());
198 assertEquals(2,esStatConfig.getTaskAgeHistogramNumDecimalPoints());
200 assertEquals("[Response Time In Ms]",esStatConfig.getResponseTimeHistogramLabel());
201 assertEquals(10000L,esStatConfig.getResponseTimeHistogramMaxYAxis());
202 assertEquals(20,esStatConfig.getResponseTimeHistogramNumBins());
203 assertEquals(2, esStatConfig.getResponseTimeHistogramNumDecimalPoints());
205 assertEquals("[Transactions Per Second]",esStatConfig.getTpsHistogramLabel());
206 assertEquals(100,esStatConfig.getTpsHistogramMaxYAxis());
207 assertEquals(20,esStatConfig.getTpsHistogramNumBins());
208 assertEquals(2,esStatConfig.getTpsHistogramNumDecimalPoints());
213 public void validateBasicConstruction() throws Exception {
215 quantumSync = new QuantumSynchronizer(LOG, "quanumSynchronizer", 5, 5, 5, "quantum-search-index", aaiStatConfig,
218 quantumSync.setAaiAdapter(aaiAdapter);
219 quantumSync.setElasticSearchAdapter(esAdapter);
221 quantumSync.clearCache();
223 assertNotNull(quantumSync.getAaiAdapter());
224 assertNotNull(quantumSync.getElasticSearchAdapter());
225 assertEquals("quantum-search-index", quantumSync.getIndexName());
227 quantumSync.setIndexName("new-search-index-name");
228 assertEquals("new-search-index-name", quantumSync.getIndexName());
230 quantumSync.shutdownExecutors();
233 private static String REST_STAT_LINE_FORMAT = ".*%s.*1XX:.*%d.*2XX:.*%d.*3XX:.*%d.*4XX:.*%d.*5XX:.*%d.*6XX:.*%d.*";
234 private static String ENTITY_STATS_LINE_FORMAT = ".*%s.*TOTAL:.*%d.*FOUND:.*%d.*NO_PAYLOAD:.*%d.*NOT_FOUND:.*%d.*NUM_RETRIES:.*%d.*ERROR:.*%d.*";
236 private boolean reportContainsRestStatistics(String testString, HttpMethod httpMethod, long oneXX, long twoXX,
237 long threeXX, long fourXX, long fiveXX, long sixXX) {
239 Pattern pattern = Pattern.compile(String.format(REST_STAT_LINE_FORMAT, httpMethod.toString(), oneXX, twoXX,
240 threeXX, fourXX, fiveXX, sixXX));
242 String lines[] = testString.split("\\r?\\n");
245 * if we get a match on any of the lines in the report, then we
249 for (String line : lines) {
250 if (pattern.matcher(line).matches()) {
258 private boolean reportContainsEntityStatistics(String testString, String entityType, long total, long found,
259 long noPayload, long notFound, long numRetries, long numErrors) {
261 Pattern pattern = Pattern.compile(String.format(ENTITY_STATS_LINE_FORMAT, entityType, total, found,
262 noPayload, notFound, numRetries, numErrors));
264 String lines[] = testString.split("\\r?\\n");
267 * if we get a match on any of the lines in the report, then we
271 for (String line : lines) {
272 if (pattern.matcher(line).matches()) {
282 public void validateStatisticTrackingAndReporting() throws Exception {
284 quantumSync = new QuantumSynchronizer(LOG, "quanumSynchronizer", 5, 5, 5, "quantum-search-index", aaiStatConfig,
287 quantumSync.setAaiAdapter(aaiAdapter);
288 quantumSync.setElasticSearchAdapter(esAdapter);
290 searchableEntityLookup = new SearchableEntityLookup();
292 Map<String,SearchableOxmEntityDescriptor> searchableDescriptors = new HashMap<String,SearchableOxmEntityDescriptor>();
294 SearchableOxmEntityDescriptor complexDescriptor = new SearchableOxmEntityDescriptor();
295 complexDescriptor.setEntityName("complex");
296 List<String> pkeyNames = new ArrayList<String>();
297 pkeyNames.add("physical-location-id");
299 complexDescriptor.setPrimaryKeyAttributeNames(pkeyNames);
300 complexDescriptor.setSearchableAttributes(pkeyNames);
302 searchableDescriptors.put("complex", complexDescriptor);
304 searchableEntityLookup.setSearchableEntityDescriptors(searchableDescriptors);
306 quantumSync.setSearchableEntityLookup(searchableEntityLookup);
307 quantumSync.initCounters();
309 int randomMaxTimesToPegCounters = secureRandom.nextInt(1000);
311 NetworkTransaction txn = null;
312 OperationResult opResult = null;
316 * The result of this block is that for all HttpMethod types [ PUT, POST, GET, etc ] we'll peg a complex entity
317 * type counter a random number of times (set before the for loop, and for each status code category 1XX -> 6XX.
320 // GET, PUT, POST, DELETE, PATCH, HEAD
321 for (HttpMethod httpMethod : HttpMethod.values()) {
323 // for randomMaxTimesToPegCounters
324 for (int numTimesToPegCounter = 0; numTimesToPegCounter < randomMaxTimesToPegCounters; numTimesToPegCounter++) {
325 txn = new NetworkTransaction();
326 txn.setOperationType(httpMethod);
327 txn.setEntityType("complex");
330 * set the txn optime to a random value between 0 and 10000 ms.
331 * Over thousands of counter statistics the random sample
332 * averages should be approximately uniform, but is highly
333 * dependent on the pseudo-RNG.
335 txn.setOpTimeInMs(secureRandom.nextInt(10000));
337 // 1XX, 2XX, 3XX, 4XX, 5XX, 6XX
338 for ( int resultCode = 100; resultCode < 700; resultCode += 100) {
339 opResult = new OperationResult();
340 opResult.setResultCode(resultCode);
342 txn.setOperationResult(opResult);
344 // peg both AAI and ES statistics
346 quantumSync.updateActiveInventoryCounters(txn);
347 quantumSync.updateActiveInventoryCounters(httpMethod, "complex", opResult);
349 quantumSync.updateElasticSearchCounters(txn);
350 quantumSync.updateElasticSearchCounters(httpMethod, "complex", opResult);
356 for (int numTimesToPegCounter = 0; numTimesToPegCounter < randomMaxTimesToPegCounters; numTimesToPegCounter++) {
357 quantumSync.incActiveInventoryWorkOnHandCounter();
358 quantumSync.incElasticSearchWorkOnHandCounter();
361 assertEquals( randomMaxTimesToPegCounters, quantumSync.aaiWorkOnHand.get());
362 assertEquals( randomMaxTimesToPegCounters, quantumSync.esWorkOnHand.get());
365 * now we'll generate various reports and try to validate the output
368 String aaiStatsReport = quantumSync.getActiveInventoryStatisticsReport();
371 * We double the expected validation check number because we peg each
372 * counter in each category twice (with different APIs for the same
376 assertTrue(reportContainsRestStatistics(aaiStatsReport, HttpMethod.DELETE, randomMaxTimesToPegCounters * 2,
377 randomMaxTimesToPegCounters * 2, randomMaxTimesToPegCounters * 2, randomMaxTimesToPegCounters * 2,
378 randomMaxTimesToPegCounters * 2, randomMaxTimesToPegCounters * 2));
380 assertTrue(reportContainsRestStatistics(aaiStatsReport, HttpMethod.PUT, randomMaxTimesToPegCounters * 2,
381 randomMaxTimesToPegCounters * 2, randomMaxTimesToPegCounters * 2, randomMaxTimesToPegCounters * 2,
382 randomMaxTimesToPegCounters * 2, randomMaxTimesToPegCounters * 2));
384 assertTrue(reportContainsRestStatistics(aaiStatsReport, HttpMethod.POST, randomMaxTimesToPegCounters * 2,
385 randomMaxTimesToPegCounters * 2, randomMaxTimesToPegCounters * 2, randomMaxTimesToPegCounters * 2,
386 randomMaxTimesToPegCounters * 2, randomMaxTimesToPegCounters * 2));
388 assertTrue(reportContainsRestStatistics(aaiStatsReport, HttpMethod.GET, randomMaxTimesToPegCounters * 2,
389 randomMaxTimesToPegCounters * 2, randomMaxTimesToPegCounters * 2, randomMaxTimesToPegCounters * 2,
390 randomMaxTimesToPegCounters * 2, randomMaxTimesToPegCounters * 2));
392 long total = (randomMaxTimesToPegCounters*2)*6;
393 long found = randomMaxTimesToPegCounters*2;
394 long noPayload = (randomMaxTimesToPegCounters*2)*6;
397 long numErrors = (randomMaxTimesToPegCounters*2)*5;
399 assertTrue(reportContainsEntityStatistics(aaiStatsReport, "complex", total, found,
400 noPayload, notFound, numRetries, numErrors));
402 String esStatsReport = quantumSync.getElasticSearchStatisticsReport();
404 assertTrue(reportContainsRestStatistics(esStatsReport, HttpMethod.DELETE, randomMaxTimesToPegCounters * 2,
405 randomMaxTimesToPegCounters * 2, randomMaxTimesToPegCounters * 2, randomMaxTimesToPegCounters * 2,
406 randomMaxTimesToPegCounters * 2, randomMaxTimesToPegCounters * 2));
408 assertTrue(reportContainsRestStatistics(esStatsReport, HttpMethod.PUT, randomMaxTimesToPegCounters * 2,
409 randomMaxTimesToPegCounters * 2, randomMaxTimesToPegCounters * 2, randomMaxTimesToPegCounters * 2,
410 randomMaxTimesToPegCounters * 2, randomMaxTimesToPegCounters * 2));
412 assertTrue(reportContainsRestStatistics(esStatsReport, HttpMethod.POST, randomMaxTimesToPegCounters * 2,
413 randomMaxTimesToPegCounters * 2, randomMaxTimesToPegCounters * 2, randomMaxTimesToPegCounters * 2,
414 randomMaxTimesToPegCounters * 2, randomMaxTimesToPegCounters * 2));
416 assertTrue(reportContainsRestStatistics(esStatsReport, HttpMethod.GET, randomMaxTimesToPegCounters * 2,
417 randomMaxTimesToPegCounters * 2, randomMaxTimesToPegCounters * 2, randomMaxTimesToPegCounters * 2,
418 randomMaxTimesToPegCounters * 2, randomMaxTimesToPegCounters * 2));
421 assertNotNull(quantumSync.getStatReport(10000L, false));
422 assertNotNull(quantumSync.getStatReport(20000L, true));
424 for (int numTimesToPegCounter = 0; numTimesToPegCounter < randomMaxTimesToPegCounters; numTimesToPegCounter++) {
425 quantumSync.decActiveInventoryWorkOnHandCounter();
426 quantumSync.decElasticSearchWorkOnHandCounter();
429 assertEquals( 0, quantumSync.aaiWorkOnHand.get());
430 assertEquals( 0, quantumSync.esWorkOnHand.get());
433 * Validate stat reports display zero stats for complex
436 quantumSync.resetCounters();
438 aaiStatsReport = quantumSync.getActiveInventoryStatisticsReport();
441 * We double the expected validation check number because we peg each
442 * counter in each category twice (with different APIs for the same
446 assertTrue(reportContainsRestStatistics(aaiStatsReport, HttpMethod.DELETE, 0, 0, 0, 0, 0, 0));
447 assertTrue(reportContainsRestStatistics(aaiStatsReport, HttpMethod.PUT, 0, 0, 0, 0, 0, 0));
448 assertTrue(reportContainsRestStatistics(aaiStatsReport, HttpMethod.POST, 0, 0, 0, 0, 0, 0));
449 assertTrue(reportContainsRestStatistics(aaiStatsReport, HttpMethod.GET, 0, 0, 0, 0, 0, 0));
451 assertTrue(reportContainsEntityStatistics(aaiStatsReport, "complex", 0, 0, 0, 0, 0, 0));
453 esStatsReport = quantumSync.getElasticSearchStatisticsReport();
455 assertTrue(reportContainsRestStatistics(esStatsReport, HttpMethod.DELETE, 0, 0, 0, 0, 0, 0));
456 assertTrue(reportContainsRestStatistics(esStatsReport, HttpMethod.PUT, 0, 0, 0, 0, 0, 0));
457 assertTrue(reportContainsRestStatistics(esStatsReport, HttpMethod.POST, 0, 0, 0, 0, 0, 0));
458 assertTrue(reportContainsRestStatistics(esStatsReport, HttpMethod.GET, 0, 0, 0, 0, 0, 0));
460 quantumSync.shutdownExecutors();