2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
6 * Copyright © 2017-2018 Amdocs
7 * ================================================================================
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 * ============LICENSE_END=========================================================
22 package org.onap.aai.sparky.sync;
24 import static org.junit.Assert.assertEquals;
25 import static org.junit.Assert.assertNotNull;
26 import static org.junit.Assert.assertTrue;
28 import java.security.SecureRandom;
29 import java.util.ArrayList;
30 import java.util.HashMap;
31 import java.util.List;
33 import java.util.regex.Pattern;
35 import org.junit.Before;
36 import org.junit.Test;
37 import org.mockito.Mockito;
38 import org.onap.aai.cl.api.Logger;
39 import org.onap.aai.cl.eelf.LoggerFactory;
40 import org.onap.aai.restclient.client.OperationResult;
41 import org.onap.aai.sparky.config.oxm.SearchableEntityLookup;
42 import org.onap.aai.sparky.config.oxm.SearchableOxmEntityDescriptor;
43 import org.onap.aai.sparky.dal.ActiveInventoryAdapter;
44 import org.onap.aai.sparky.search.SearchServiceAdapter;
45 import org.onap.aai.sparky.dal.NetworkTransaction;
46 import org.onap.aai.sparky.dal.rest.HttpMethod;
47 import org.onap.aai.sparky.sync.config.NetworkStatisticsConfig;
51 public class AbstractEntitySynchronizerTest {
53 public class QuantumSynchronizer extends AbstractEntitySynchronizer {
55 private boolean amIDone;
56 private SearchableEntityLookup searchableEntityLookup;
58 protected QuantumSynchronizer(Logger logger, String syncName, int numSyncWorkers, int numActiveInventoryWorkers,
59 int numElasticsearchWorkers, String indexName, NetworkStatisticsConfig aaiStatConfig,
60 NetworkStatisticsConfig esStatConfig) throws Exception {
61 super(logger, syncName, numSyncWorkers, numActiveInventoryWorkers, numElasticsearchWorkers, indexName,
62 aaiStatConfig, esStatConfig);
68 public void setSearchableEntityLookup(SearchableEntityLookup searchableEntityLookup) {
69 this.searchableEntityLookup = searchableEntityLookup;
72 public void initCounters() {
73 if (this.searchableEntityLookup != null) {
75 .intializeEntityCounters(searchableEntityLookup.getSearchableEntityDescriptors().keySet());
77 .intializeEntityCounters(searchableEntityLookup.getSearchableEntityDescriptors().keySet());
82 public void setSyncDone(boolean done) {
87 protected boolean isSyncDone() {
93 private static Logger LOG = LoggerFactory.getInstance().getLogger(AbstractEntitySynchronizerTest.class);
94 private static SecureRandom secureRandom = new SecureRandom();
96 private QuantumSynchronizer quantumSync;
97 private NetworkStatisticsConfig aaiStatConfig;
98 private NetworkStatisticsConfig esStatConfig;
99 private SearchServiceAdapter searchServiceAdapter;
100 private ActiveInventoryAdapter aaiAdapter;
101 private SearchableEntityLookup searchableEntityLookup;
105 public void init() throws Exception {
107 aaiStatConfig = new NetworkStatisticsConfig();
109 aaiStatConfig.setNumSamplesPerThreadForRunningAverage(100);
111 aaiStatConfig.setBytesHistogramLabel("[Response Size In Bytes]");
112 aaiStatConfig.setBytesHistogramMaxYAxis(1000000L);
113 aaiStatConfig.setBytesHistogramNumBins(20);
114 aaiStatConfig.setBytesHistogramNumDecimalPoints(2);
116 aaiStatConfig.setQueueLengthHistogramLabel("[Queue Item Length]");
117 aaiStatConfig.setQueueLengthHistogramMaxYAxis(20000);
118 aaiStatConfig.setQueueLengthHistogramNumBins(20);
119 aaiStatConfig.setQueueLengthHistogramNumDecimalPoints(2);
121 aaiStatConfig.setTaskAgeHistogramLabel("[Task Age In Ms]");
122 aaiStatConfig.setTaskAgeHistogramMaxYAxis(600000L);
123 aaiStatConfig.setTaskAgeHistogramNumBins(20);
124 aaiStatConfig.setTaskAgeHistogramNumDecimalPoints(2);
126 aaiStatConfig.setResponseTimeHistogramLabel("[Response Time In Ms]");
127 aaiStatConfig.setResponseTimeHistogramMaxYAxis(1000L);
128 aaiStatConfig.setResponseTimeHistogramNumBins(20);
129 aaiStatConfig.setResponseTimeHistogramNumDecimalPoints(2);
131 aaiStatConfig.setTpsHistogramLabel("[Transactions Per Second]");
132 aaiStatConfig.setTpsHistogramMaxYAxis(100);
133 aaiStatConfig.setTpsHistogramNumBins(20);
134 aaiStatConfig.setTpsHistogramNumDecimalPoints(2);
136 esStatConfig = new NetworkStatisticsConfig();
138 esStatConfig.setNumSamplesPerThreadForRunningAverage(100);
140 esStatConfig.setBytesHistogramLabel("[Response Size In Bytes]");
141 esStatConfig.setBytesHistogramMaxYAxis(1000000L);
142 esStatConfig.setBytesHistogramNumBins(20);
143 esStatConfig.setBytesHistogramNumDecimalPoints(2);
145 esStatConfig.setQueueLengthHistogramLabel("[Queue Item Length]");
146 esStatConfig.setQueueLengthHistogramMaxYAxis(20000);
147 esStatConfig.setQueueLengthHistogramNumBins(20);
148 esStatConfig.setQueueLengthHistogramNumDecimalPoints(2);
150 esStatConfig.setTaskAgeHistogramLabel("[Task Age In Ms]");
151 esStatConfig.setTaskAgeHistogramMaxYAxis(600000L);
152 esStatConfig.setTaskAgeHistogramNumBins(20);
153 esStatConfig.setTaskAgeHistogramNumDecimalPoints(2);
155 esStatConfig.setResponseTimeHistogramLabel("[Response Time In Ms]");
156 esStatConfig.setResponseTimeHistogramMaxYAxis(10000L);
157 esStatConfig.setResponseTimeHistogramNumBins(20);
158 esStatConfig.setResponseTimeHistogramNumDecimalPoints(2);
160 esStatConfig.setTpsHistogramLabel("[Transactions Per Second]");
161 esStatConfig.setTpsHistogramMaxYAxis(100);
162 esStatConfig.setTpsHistogramNumBins(20);
163 esStatConfig.setTpsHistogramNumDecimalPoints(2);
165 searchServiceAdapter = Mockito.mock(SearchServiceAdapter.class);
166 aaiAdapter = Mockito.mock(ActiveInventoryAdapter.class);
171 public void validateNetworkStatConfig() {
173 // validate aaiStatConfig
175 assertEquals(100, aaiStatConfig.getNumSamplesPerThreadForRunningAverage());
177 assertEquals("[Response Size In Bytes]",aaiStatConfig.getBytesHistogramLabel());
178 assertEquals(1000000L,aaiStatConfig.getBytesHistogramMaxYAxis());
179 assertEquals(20,aaiStatConfig.getBytesHistogramNumBins());
180 assertEquals(2,aaiStatConfig.getBytesHistogramNumDecimalPoints());
182 assertEquals("[Queue Item Length]",aaiStatConfig.getQueueLengthHistogramLabel());
183 assertEquals(20000,aaiStatConfig.getQueueLengthHistogramMaxYAxis());
184 assertEquals(20,aaiStatConfig.getQueueLengthHistogramNumBins());
185 assertEquals(2,aaiStatConfig.getQueueLengthHistogramNumDecimalPoints());
187 assertEquals("[Task Age In Ms]",aaiStatConfig.getTaskAgeHistogramLabel());
188 assertEquals(600000L,aaiStatConfig.getTaskAgeHistogramMaxYAxis());
189 assertEquals(20,aaiStatConfig.getTaskAgeHistogramNumBins());
190 assertEquals(2,aaiStatConfig.getTaskAgeHistogramNumDecimalPoints());
192 assertEquals("[Response Time In Ms]",aaiStatConfig.getResponseTimeHistogramLabel());
193 assertEquals(1000L,aaiStatConfig.getResponseTimeHistogramMaxYAxis());
194 assertEquals(20,aaiStatConfig.getResponseTimeHistogramNumBins());
195 assertEquals(2, aaiStatConfig.getResponseTimeHistogramNumDecimalPoints());
197 assertEquals("[Transactions Per Second]",aaiStatConfig.getTpsHistogramLabel());
198 assertEquals(100,aaiStatConfig.getTpsHistogramMaxYAxis());
199 assertEquals(20,aaiStatConfig.getTpsHistogramNumBins());
200 assertEquals(2,aaiStatConfig.getTpsHistogramNumDecimalPoints());
202 // validate esStatConfig
204 assertEquals(100, esStatConfig.getNumSamplesPerThreadForRunningAverage());
206 assertEquals("[Response Size In Bytes]",esStatConfig.getBytesHistogramLabel());
207 assertEquals(1000000L,esStatConfig.getBytesHistogramMaxYAxis());
208 assertEquals(20,esStatConfig.getBytesHistogramNumBins());
209 assertEquals(2,esStatConfig.getBytesHistogramNumDecimalPoints());
211 assertEquals("[Queue Item Length]",esStatConfig.getQueueLengthHistogramLabel());
212 assertEquals(20000,esStatConfig.getQueueLengthHistogramMaxYAxis());
213 assertEquals(20,esStatConfig.getQueueLengthHistogramNumBins());
214 assertEquals(2,esStatConfig.getQueueLengthHistogramNumDecimalPoints());
216 assertEquals("[Task Age In Ms]",esStatConfig.getTaskAgeHistogramLabel());
217 assertEquals(600000L,esStatConfig.getTaskAgeHistogramMaxYAxis());
218 assertEquals(20,esStatConfig.getTaskAgeHistogramNumBins());
219 assertEquals(2,esStatConfig.getTaskAgeHistogramNumDecimalPoints());
221 assertEquals("[Response Time In Ms]",esStatConfig.getResponseTimeHistogramLabel());
222 assertEquals(10000L,esStatConfig.getResponseTimeHistogramMaxYAxis());
223 assertEquals(20,esStatConfig.getResponseTimeHistogramNumBins());
224 assertEquals(2, esStatConfig.getResponseTimeHistogramNumDecimalPoints());
226 assertEquals("[Transactions Per Second]",esStatConfig.getTpsHistogramLabel());
227 assertEquals(100,esStatConfig.getTpsHistogramMaxYAxis());
228 assertEquals(20,esStatConfig.getTpsHistogramNumBins());
229 assertEquals(2,esStatConfig.getTpsHistogramNumDecimalPoints());
234 public void validateBasicConstruction() throws Exception {
236 quantumSync = new QuantumSynchronizer(LOG, "quanumSynchronizer", 5, 5, 5, "quantum-search-index", aaiStatConfig,
239 quantumSync.setAaiAdapter(aaiAdapter);
240 quantumSync.setSearchServiceAdapter(searchServiceAdapter);
242 quantumSync.clearCache();
244 assertNotNull(quantumSync.getAaiAdapter());
245 assertNotNull(quantumSync.getSearchServiceAdapter());
246 assertEquals("quantum-search-index", quantumSync.getIndexName());
248 quantumSync.setIndexName("new-search-index-name");
249 assertEquals("new-search-index-name", quantumSync.getIndexName());
251 quantumSync.shutdownExecutors();
254 private static String REST_STAT_LINE_FORMAT = ".*%s.*1XX:.*%d.*2XX:.*%d.*3XX:.*%d.*4XX:.*%d.*5XX:.*%d.*6XX:.*%d.*";
255 private static String ENTITY_STATS_LINE_FORMAT = ".*%s.*TOTAL:.*%d.*FOUND:.*%d.*NO_PAYLOAD:.*%d.*NOT_FOUND:.*%d.*NUM_RETRIES:.*%d.*ERROR:.*%d.*";
257 private boolean reportContainsRestStatistics(String testString, HttpMethod httpMethod, long oneXX, long twoXX,
258 long threeXX, long fourXX, long fiveXX, long sixXX) {
260 Pattern pattern = Pattern.compile(String.format(REST_STAT_LINE_FORMAT, httpMethod.toString(), oneXX, twoXX,
261 threeXX, fourXX, fiveXX, sixXX));
263 String lines[] = testString.split("\\r?\\n");
266 * if we get a match on any of the lines in the report, then we
270 for (String line : lines) {
271 if (pattern.matcher(line).matches()) {
279 private boolean reportContainsEntityStatistics(String testString, String entityType, long total, long found,
280 long noPayload, long notFound, long numRetries, long numErrors) {
282 Pattern pattern = Pattern.compile(String.format(ENTITY_STATS_LINE_FORMAT, entityType, total, found,
283 noPayload, notFound, numRetries, numErrors));
285 String lines[] = testString.split("\\r?\\n");
288 * if we get a match on any of the lines in the report, then we
292 for (String line : lines) {
293 if (pattern.matcher(line).matches()) {
303 public void validateStatisticTrackingAndReporting() throws Exception {
305 quantumSync = new QuantumSynchronizer(LOG, "quanumSynchronizer", 5, 5, 5, "quantum-search-index", aaiStatConfig,
308 quantumSync.setAaiAdapter(aaiAdapter);
309 quantumSync.setSearchServiceAdapter(searchServiceAdapter);
311 searchableEntityLookup = new SearchableEntityLookup();
313 Map<String,SearchableOxmEntityDescriptor> searchableDescriptors = new HashMap<String,SearchableOxmEntityDescriptor>();
315 SearchableOxmEntityDescriptor complexDescriptor = new SearchableOxmEntityDescriptor();
316 complexDescriptor.setEntityName("complex");
317 List<String> pkeyNames = new ArrayList<String>();
318 pkeyNames.add("physical-location-id");
320 complexDescriptor.setPrimaryKeyAttributeNames(pkeyNames);
321 complexDescriptor.setSearchableAttributes(pkeyNames);
323 searchableDescriptors.put("complex", complexDescriptor);
325 searchableEntityLookup.setSearchableEntityDescriptors(searchableDescriptors);
327 quantumSync.setSearchableEntityLookup(searchableEntityLookup);
328 quantumSync.initCounters();
330 int randomMaxTimesToPegCounters = secureRandom.nextInt(1000);
332 NetworkTransaction txn = null;
333 OperationResult opResult = null;
337 * The result of this block is that for all HttpMethod types [ PUT, POST, GET, etc ] we'll peg a complex entity
338 * type counter a random number of times (set before the for loop, and for each status code category 1XX -> 6XX.
341 // GET, PUT, POST, DELETE, PATCH, HEAD
342 for (HttpMethod httpMethod : HttpMethod.values()) {
344 // for randomMaxTimesToPegCounters
345 for (int numTimesToPegCounter = 0; numTimesToPegCounter < randomMaxTimesToPegCounters; numTimesToPegCounter++) {
346 txn = new NetworkTransaction();
347 txn.setOperationType(httpMethod);
348 txn.setEntityType("complex");
351 * set the txn optime to a random value between 0 and 10000 ms.
352 * Over thousands of counter statistics the random sample
353 * averages should be approximately uniform, but is highly
354 * dependent on the pseudo-RNG.
356 txn.setOpTimeInMs(secureRandom.nextInt(10000));
358 // 1XX, 2XX, 3XX, 4XX, 5XX, 6XX
359 for ( int resultCode = 100; resultCode < 700; resultCode += 100) {
360 opResult = new OperationResult();
361 opResult.setResultCode(resultCode);
363 txn.setOperationResult(opResult);
365 // peg both AAI and ES statistics
367 quantumSync.updateActiveInventoryCounters(txn);
368 quantumSync.updateActiveInventoryCounters(httpMethod, "complex", opResult);
370 quantumSync.updateElasticSearchCounters(txn);
371 quantumSync.updateElasticSearchCounters(httpMethod, "complex", opResult);
377 for (int numTimesToPegCounter = 0; numTimesToPegCounter < randomMaxTimesToPegCounters; numTimesToPegCounter++) {
378 quantumSync.incActiveInventoryWorkOnHandCounter();
379 quantumSync.incElasticSearchWorkOnHandCounter();
382 assertEquals( randomMaxTimesToPegCounters, quantumSync.aaiWorkOnHand.get());
383 assertEquals( randomMaxTimesToPegCounters, quantumSync.esWorkOnHand.get());
386 * now we'll generate various reports and try to validate the output
389 String aaiStatsReport = quantumSync.getActiveInventoryStatisticsReport();
392 * We double the expected validation check number because we peg each
393 * counter in each category twice (with different APIs for the same
397 assertTrue(reportContainsRestStatistics(aaiStatsReport, HttpMethod.DELETE, randomMaxTimesToPegCounters * 2,
398 randomMaxTimesToPegCounters * 2, randomMaxTimesToPegCounters * 2, randomMaxTimesToPegCounters * 2,
399 randomMaxTimesToPegCounters * 2, randomMaxTimesToPegCounters * 2));
401 assertTrue(reportContainsRestStatistics(aaiStatsReport, HttpMethod.PUT, randomMaxTimesToPegCounters * 2,
402 randomMaxTimesToPegCounters * 2, randomMaxTimesToPegCounters * 2, randomMaxTimesToPegCounters * 2,
403 randomMaxTimesToPegCounters * 2, randomMaxTimesToPegCounters * 2));
405 assertTrue(reportContainsRestStatistics(aaiStatsReport, HttpMethod.POST, randomMaxTimesToPegCounters * 2,
406 randomMaxTimesToPegCounters * 2, randomMaxTimesToPegCounters * 2, randomMaxTimesToPegCounters * 2,
407 randomMaxTimesToPegCounters * 2, randomMaxTimesToPegCounters * 2));
409 assertTrue(reportContainsRestStatistics(aaiStatsReport, HttpMethod.GET, randomMaxTimesToPegCounters * 2,
410 randomMaxTimesToPegCounters * 2, randomMaxTimesToPegCounters * 2, randomMaxTimesToPegCounters * 2,
411 randomMaxTimesToPegCounters * 2, randomMaxTimesToPegCounters * 2));
413 long total = (randomMaxTimesToPegCounters*2)*6;
414 long found = randomMaxTimesToPegCounters*2;
415 long noPayload = (randomMaxTimesToPegCounters*2)*6;
418 long numErrors = (randomMaxTimesToPegCounters*2)*5;
420 assertTrue(reportContainsEntityStatistics(aaiStatsReport, "complex", total, found,
421 noPayload, notFound, numRetries, numErrors));
423 String esStatsReport = quantumSync.getElasticSearchStatisticsReport();
425 assertTrue(reportContainsRestStatistics(esStatsReport, HttpMethod.DELETE, randomMaxTimesToPegCounters * 2,
426 randomMaxTimesToPegCounters * 2, randomMaxTimesToPegCounters * 2, randomMaxTimesToPegCounters * 2,
427 randomMaxTimesToPegCounters * 2, randomMaxTimesToPegCounters * 2));
429 assertTrue(reportContainsRestStatistics(esStatsReport, HttpMethod.PUT, randomMaxTimesToPegCounters * 2,
430 randomMaxTimesToPegCounters * 2, randomMaxTimesToPegCounters * 2, randomMaxTimesToPegCounters * 2,
431 randomMaxTimesToPegCounters * 2, randomMaxTimesToPegCounters * 2));
433 assertTrue(reportContainsRestStatistics(esStatsReport, HttpMethod.POST, randomMaxTimesToPegCounters * 2,
434 randomMaxTimesToPegCounters * 2, randomMaxTimesToPegCounters * 2, randomMaxTimesToPegCounters * 2,
435 randomMaxTimesToPegCounters * 2, randomMaxTimesToPegCounters * 2));
437 assertTrue(reportContainsRestStatistics(esStatsReport, HttpMethod.GET, randomMaxTimesToPegCounters * 2,
438 randomMaxTimesToPegCounters * 2, randomMaxTimesToPegCounters * 2, randomMaxTimesToPegCounters * 2,
439 randomMaxTimesToPegCounters * 2, randomMaxTimesToPegCounters * 2));
442 assertNotNull(quantumSync.getStatReport(10000L, false));
443 assertNotNull(quantumSync.getStatReport(20000L, true));
445 for (int numTimesToPegCounter = 0; numTimesToPegCounter < randomMaxTimesToPegCounters; numTimesToPegCounter++) {
446 quantumSync.decActiveInventoryWorkOnHandCounter();
447 quantumSync.decElasticSearchWorkOnHandCounter();
450 assertEquals( 0, quantumSync.aaiWorkOnHand.get());
451 assertEquals( 0, quantumSync.esWorkOnHand.get());
454 * Validate stat reports display zero stats for complex
457 quantumSync.resetCounters();
459 aaiStatsReport = quantumSync.getActiveInventoryStatisticsReport();
462 * We double the expected validation check number because we peg each
463 * counter in each category twice (with different APIs for the same
467 assertTrue(reportContainsRestStatistics(aaiStatsReport, HttpMethod.DELETE, 0, 0, 0, 0, 0, 0));
468 assertTrue(reportContainsRestStatistics(aaiStatsReport, HttpMethod.PUT, 0, 0, 0, 0, 0, 0));
469 assertTrue(reportContainsRestStatistics(aaiStatsReport, HttpMethod.POST, 0, 0, 0, 0, 0, 0));
470 assertTrue(reportContainsRestStatistics(aaiStatsReport, HttpMethod.GET, 0, 0, 0, 0, 0, 0));
472 assertTrue(reportContainsEntityStatistics(aaiStatsReport, "complex", 0, 0, 0, 0, 0, 0));
474 esStatsReport = quantumSync.getElasticSearchStatisticsReport();
476 assertTrue(reportContainsRestStatistics(esStatsReport, HttpMethod.DELETE, 0, 0, 0, 0, 0, 0));
477 assertTrue(reportContainsRestStatistics(esStatsReport, HttpMethod.PUT, 0, 0, 0, 0, 0, 0));
478 assertTrue(reportContainsRestStatistics(esStatsReport, HttpMethod.POST, 0, 0, 0, 0, 0, 0));
479 assertTrue(reportContainsRestStatistics(esStatsReport, HttpMethod.GET, 0, 0, 0, 0, 0, 0));
481 quantumSync.shutdownExecutors();