36cf26bb74f9eb8cdd0a976161049196525fc559
[appc.git] / appc-dispatcher / appc-dispatcher-common / transaction-recorder / src / test / java / org / onap / appc / transactionrecorder / impl / TransactionRecorderImplTest.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP : APPC
4  * ================================================================================
5  * Copyright (C) 2017-2019 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Copyright (C) 2017 Amdocs
8  * ================================================================================
9  * Modifications Copyright (C) 2019 Ericsson
10  * =============================================================================
11  * Licensed under the Apache License, Version 2.0 (the "License");
12  * you may not use this file except in compliance with the License.
13  * You may obtain a copy of the License at
14  *
15  *      http://www.apache.org/licenses/LICENSE-2.0
16  *
17  * Unless required by applicable law or agreed to in writing, software
18  * distributed under the License is distributed on an "AS IS" BASIS,
19  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20  * See the License for the specific language governing permissions and
21  * limitations under the License.
22  *
23  * ============LICENSE_END=========================================================
24  */
25
26 package org.onap.appc.transactionrecorder.impl;
27
28 import static org.mockito.Matchers.anyObject;
29 import static org.mockito.Matchers.anyString;
30 import static org.hamcrest.CoreMatchers.isA;
31 import java.sql.Connection;
32 import java.sql.PreparedStatement;
33 import java.sql.ResultSet;
34 import java.sql.SQLException;
35 import java.sql.Statement;
36 import java.text.ParseException;
37 import java.time.Instant;
38 import java.time.ZoneOffset;
39 import java.time.format.DateTimeFormatter;
40 import java.time.temporal.ChronoUnit;
41 import java.util.ArrayList;
42 import java.util.HashMap;
43 import java.util.List;
44 import java.util.Map;
45 import java.util.UUID;
46 import javax.sql.rowset.CachedRowSet;
47 import org.junit.After;
48 import org.junit.Assert;
49 import org.junit.Before;
50 import org.junit.Rule;
51 import org.junit.Test;
52 import org.junit.rules.ExpectedException;
53 import org.mockito.Mockito;
54 import org.onap.appc.dao.util.dbcp.DBConnectionPool;
55 import org.onap.appc.dao.util.helper.DBHelper;
56 import org.onap.appc.domainmodel.lcm.Flags;
57 import org.onap.appc.domainmodel.lcm.RequestStatus;
58 import org.onap.appc.domainmodel.lcm.TransactionRecord;
59 import org.onap.appc.domainmodel.lcm.VNFOperation;
60 import org.onap.appc.exceptions.APPCException;
61 import org.onap.appc.transactionrecorder.objects.TransactionConstants;
62 import org.onap.appc.transactionrecorder.objects.TransactionConstants.TRANSACTION_ATTRIBUTES;
63 import org.onap.ccsdk.sli.core.dblib.DbLibService;
64 import com.sun.rowset.CachedRowSetImpl;
65
66 /**
67  * Test class for TransactionRecorder
68  */
69 public class TransactionRecorderImplTest {
70
71     private String dbUrl = "jdbc:h2:mem:test;MODE=MYSQL;DB_CLOSE_DELAY=-1";
72     private String username = "sa";
73     private String password = "sa";
74     private String driver = "org.h2.Driver";
75
76     private TransactionRecorderImpl transactionRecorderImpl;
77     private DbLibService dbLibService;
78
79     private DBConnectionPool dbConnectionPool;
80
81
82     /**
83      * Ideally JUnit should grab the SQL to create the transaction table from the same source used in deployments;
84      * however, at the time of writing this that was not possible.  Should it become possible in the future please
85      * update this JUnit test to use the deployment source.
86      * <p>
87      * Please ensure this table create script is identical to the source script used in a deployment.
88      */
89     private String TRANSACTION_CREATE_TABLE = "CREATE TABLE TRANSACTIONS (" +
90             "  TRANSACTION_ID VARCHAR(75) NOT NULL PRIMARY KEY," +
91             "  ORIGIN_TIMESTAMP DATETIME(3) NOT NULL," +
92             "  REQUEST_ID VARCHAR(256) NOT NULL," +
93             "  SUBREQUEST_ID VARCHAR(256) DEFAULT NULL," +
94             "  ORIGINATOR_ID VARCHAR(256) DEFAULT NULL," +
95             "  START_TIME DATETIME(3) NOT NULL," +
96             "  END_TIME DATETIME(3) DEFAULT NULL," +
97             "  TARGET_ID VARCHAR(256) NOT NULL," +
98             "  TARGET_TYPE VARCHAR(256) DEFAULT NULL," +
99             "  OPERATION VARCHAR(256) NOT NULL," +
100             "  RESULT_CODE INT(11) DEFAULT NULL," +
101             "  DESCRIPTION TEXT," +
102             "  STATE VARCHAR(50) NOT NULL," +
103             "  SERVICE_INSTANCE_ID VARCHAR(256) DEFAULT NULL," +
104             "  VNFC_NAME VARCHAR(256) DEFAULT NULL," +
105             "  VSERVER_ID VARCHAR(256) DEFAULT NULL," +
106             "  VF_MODULE_ID VARCHAR(256) DEFAULT NULL," +
107             "  MODE VARCHAR(50) NOT NULL," +
108             ")";
109     private String TRANSACTION_DROP_TABLE = "DROP TABLE IF EXISTS TRANSACTIONS";
110
111     @Rule
112     public ExpectedException expectedEx = ExpectedException.none();
113
114     @Before
115     public void setUp() throws Exception {
116         transactionRecorderImpl = new TransactionRecorderImpl();
117         transactionRecorderImpl.setAppcInstanceId("123");
118         dbLibService = Mockito.mock(DbLibService.class);
119         transactionRecorderImpl.setDbLibService(dbLibService);
120         dbConnectionPool = new DBConnectionPool(dbUrl, username, password, driver);
121         executeUpdate(TRANSACTION_CREATE_TABLE);
122     }
123
124
125     @After
126     public void shutdown() {
127         if (dbConnectionPool != null) {
128             executeUpdate(TRANSACTION_DROP_TABLE);
129             dbConnectionPool.shutdown();
130         }
131     }
132
133     private void executeUpdate(String updateSQL) {
134         Connection connection = null;
135         Statement stmt = null;
136         try {
137             connection = dbConnectionPool.getConnection();
138             stmt = connection.createStatement();
139             stmt.executeUpdate(updateSQL);
140         } catch (SQLException e) {
141             throw new RuntimeException(e);
142         } finally {
143             DBHelper.close(null, stmt, connection);
144         }
145     }
146
147     /**
148      * Verify the transactionRecorderImpl.store() store the TransactionRecord correctly in the database.
149      */
150     @Test
151     public void testStore() throws Exception {
152
153         TransactionRecord input = prepareTransactionsInput();
154         Mockito.when(dbLibService.writeData(anyString(), anyObject(), anyString())).thenAnswer(invocation ->
155                 testStoreInMemory(invocation.getArguments()));
156         transactionRecorderImpl.store(input);
157
158     }
159
160     @Test
161     public void testStoreExceptionFlow() throws SQLException, APPCException {
162
163         TransactionRecord input = prepareTransactionsInput();
164         Mockito.when(dbLibService.writeData(anyString(), anyObject(), anyString())).thenThrow(new SQLException());
165         expectedEx.expect(APPCException.class);
166         expectedEx.expectMessage(TransactionConstants.ERROR_ACCESSING_DATABASE);
167         expectedEx.expectCause(isA(SQLException.class));
168         transactionRecorderImpl.store(input);
169
170     }
171
172     @Test
173     public void testGetInProgressRequests() throws SQLException, APPCException {
174         TransactionRecord record1 = prepareTransactionsInput();
175         insertRecord(record1);
176         TransactionRecord input = prepareTransactionsInput();
177         input.setStartTime(Instant.now());
178         Mockito.when(dbLibService.getData(anyString(), anyObject(), anyString())).thenAnswer(invocation ->
179                 inMemoryExecutionWithResultSet(invocation.getArguments()));
180         Assert.assertEquals(1, transactionRecorderImpl.getInProgressRequests(input, 0).size());
181
182     }
183
184     @Test
185     public void testGetInProgressRequestsSqlException() throws SQLException, APPCException {
186         TransactionRecord record1 = prepareTransactionsInput();
187         insertRecord(record1);
188         TransactionRecord input = prepareTransactionsInput();
189         input.setStartTime(Instant.now());
190         Mockito.when(dbLibService.getData(anyString(), anyObject(), anyString())).thenThrow(new SQLException());
191         expectedEx.expect(APPCException.class);
192         expectedEx.expectMessage(TransactionConstants.ERROR_ACCESSING_DATABASE);
193         expectedEx.expectCause(isA(SQLException.class));
194         transactionRecorderImpl.getInProgressRequests(input, 0);
195     }
196
197     @Test
198     public void testGetInProgressRequestsWithinTimeInterval() throws SQLException, APPCException {
199         TransactionRecord record1 = prepareTransactionsInput();
200         record1.setStartTime(Instant.now().minus(4,ChronoUnit.HOURS));
201         insertRecord(record1);
202         TransactionRecord input = prepareTransactionsInput();
203         input.setStartTime(Instant.now());
204         Mockito.when(dbLibService.getData(anyString(), anyObject(), anyString())).thenAnswer(invocation ->
205                 inMemoryExecutionWithResultSet(invocation.getArguments()));
206         List<TransactionRecord> aList= transactionRecorderImpl.getInProgressRequests(input,12);
207         Assert.assertEquals(1, transactionRecorderImpl.getInProgressRequests(input,12).size());
208
209     }
210
211     @Test
212     public void testIsTransactionDuplicate() throws SQLException, APPCException {
213         TransactionRecord input = prepareTransactionsInput();
214         Mockito.when(dbLibService.getData(anyString(), anyObject(), anyString())).thenAnswer(invocation ->
215                 inMemoryExecutionWithResultSet(invocation.getArguments()));
216         Assert.assertFalse(transactionRecorderImpl.isTransactionDuplicate(input));
217
218     }
219
220     @Test
221     public void testIsTransactionDuplicateExceptionFlow() throws SQLException, APPCException {
222         TransactionRecord input = prepareTransactionsInput();
223         Mockito.when(dbLibService.getData(anyString(), anyObject(), anyString())).thenThrow(new SQLException());
224         expectedEx.expect(APPCException.class);
225         expectedEx.expectMessage(TransactionConstants.ERROR_ACCESSING_DATABASE);
226         expectedEx.expectCause(isA(SQLException.class));
227         transactionRecorderImpl.isTransactionDuplicate(input);
228     }
229
230     @Test
231     public void testIsTransactionDuplicateAlternativeFlow() throws SQLException, APPCException {
232         TransactionRecord input = prepareTransactionsInput();
233         input.setSubRequestId(null);
234         input.setOriginatorId(null);
235         CachedRowSetImpl rowset = Mockito.mock(CachedRowSetImpl.class);
236         Mockito.when(rowset.first()).thenReturn(true);
237         Mockito.when(rowset.getString(TransactionConstants.TRANSACTION_ATTRIBUTES.TRANSACTION_ID.getColumnName()))
238             .thenReturn(null);
239         Mockito.when(dbLibService.getData(anyString(), anyObject(), anyString())).thenReturn(rowset);
240         Assert.assertTrue(transactionRecorderImpl.isTransactionDuplicate(input));
241     }
242
243     @Test
244     public void testGetInProgressRequestsCount() throws SQLException, APPCException {
245         TransactionRecord input = prepareTransactionsInput();
246         Mockito.when(dbLibService.getData(anyString(), anyObject(), anyString())).thenAnswer(invocation ->
247                 inMemoryExecutionWithResultSet(invocation.getArguments()));
248         Assert.assertEquals(0, transactionRecorderImpl.getInProgressRequestsCount().intValue());
249     }
250
251     @Test
252     public void testGetInProgressRequestsCountSqlException() throws SQLException, APPCException {
253         TransactionRecord input = prepareTransactionsInput();
254         Mockito.when(dbLibService.getData(anyString(), anyObject(), anyString())).thenThrow(new SQLException());
255         expectedEx.expect(APPCException.class);
256         expectedEx.expectMessage(TransactionConstants.ERROR_ACCESSING_DATABASE);
257         expectedEx.expectCause(isA(SQLException.class));
258         transactionRecorderImpl.getInProgressRequestsCount();
259     }
260
261     @Test
262     public void testGetInProgressRequestsCountNoRecords() throws SQLException, APPCException {
263         CachedRowSetImpl rowset = Mockito.mock(CachedRowSetImpl.class);
264         Mockito.when(rowset.first()).thenReturn(false);
265         Mockito.when(dbLibService.getData(anyString(), anyObject(), anyString())).thenReturn(rowset);
266         expectedEx.expect(APPCException.class);
267         expectedEx.expectMessage(TransactionConstants.ERROR_ACCESSING_DATABASE);
268         transactionRecorderImpl.getInProgressRequestsCount();
269     }
270
271     @Test
272     public void testUpdate() throws APPCException, SQLException {
273         TransactionRecord input = prepareTransactionsInput();
274         insertRecord(input);
275         Map<TransactionConstants.TRANSACTION_ATTRIBUTES, String> updateColumns = new HashMap<>();
276         updateColumns.put(TransactionConstants.TRANSACTION_ATTRIBUTES.TARGET_TYPE, "Firewall");
277         Mockito.when(dbLibService.getData(anyString(), anyObject(), anyString())).thenAnswer(invocation ->
278                 returnResult(invocation.getArguments()));
279         Mockito.when(dbLibService.writeData(anyString(), anyObject(), anyString())).thenAnswer(invocation ->
280                 testUpdateInMemory(invocation.getArguments()));
281         transactionRecorderImpl.update(input.getTransactionId(), input.getRequestId(), updateColumns);
282         Mockito.verify(dbLibService).getData(anyString(), anyObject(), anyString());
283         Mockito.verify(dbLibService).writeData(anyString(), anyObject(), anyString());
284     }
285
286     @Test
287     public void testUpdateExceptionFlow() throws APPCException, SQLException {
288         TransactionRecord input = prepareTransactionsInput();
289         insertRecord(input);
290         Map<TransactionConstants.TRANSACTION_ATTRIBUTES, String> updateColumns = new HashMap<>();
291         updateColumns.put(TransactionConstants.TRANSACTION_ATTRIBUTES.TARGET_TYPE, "Firewall");
292         Mockito.when(dbLibService.writeData(anyString(), anyObject(), anyString())).thenThrow(new SQLException());
293         expectedEx.expect(APPCException.class);
294         expectedEx.expectMessage(TransactionConstants.ERROR_ACCESSING_DATABASE);
295         expectedEx.expectCause(isA(SQLException.class));
296         transactionRecorderImpl.update(input.getTransactionId(), input.getRequestId(), updateColumns);
297     }
298
299     @Test
300     public void testUpdatewithNullInstance() throws APPCException, SQLException {
301         TransactionRecord input = prepareTransactionsInput();
302         Map<TransactionConstants.TRANSACTION_ATTRIBUTES, String> updateColumns = new HashMap<>();
303         updateColumns.put(TransactionConstants.TRANSACTION_ATTRIBUTES.TARGET_TYPE, "Firewall");
304         Mockito.when(dbLibService.getData(anyString(), anyObject(), anyString())).thenAnswer(invocation ->
305                 returnPositiveResult(invocation.getArguments()));
306         Mockito.when(dbLibService.writeData(anyString(), anyObject(), anyString())).thenAnswer(invocation ->
307                 testUpdateInMemory(invocation.getArguments()));
308
309         transactionRecorderImpl.update(input.getTransactionId(), input.getRequestId(), updateColumns);
310         Mockito.verify(dbLibService).getData(anyString(), anyObject(), anyString());
311         Mockito.verify(dbLibService).writeData(anyString(), anyObject(), anyString());
312     }
313
314     private Object returnPositiveResult(Object[] obj) throws Exception {
315         String query = (String) obj[0];
316         ArrayList<String> args = (ArrayList<String>) obj[1];
317         System.out.println("returnPositiveResult: Query: " + query + "\nArgs: " + args);
318
319         insertNullInstanceData(args.get(0));
320
321         try (
322              Connection con = dbConnectionPool.getConnection();
323              PreparedStatement ps_second = con.prepareStatement(query)
324              ) {
325             for (int i = 1; i <= args.size(); i++) {
326                 ps_second.setString(i, args.get(i - 1));
327             }
328             CachedRowSet rowSet = new CachedRowSetImpl();
329             rowSet.populate(ps_second.executeQuery());
330             return rowSet;
331         }
332     }
333
334     private void insertNullInstanceData(String transactionId) throws Exception {
335         final String nullInstanceQuery = (TransactionConstants.INSERT_INTO + TransactionConstants.TRANSACTIONS +
336                                           " values (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)");
337         try (
338              Connection con = dbConnectionPool.getConnection();
339              PreparedStatement ps = con.prepareStatement(nullInstanceQuery)
340              ) {
341             ArrayList<String> input = new ArrayList<String>();
342             input.add(transactionId);
343             input.add(dateToStringConverterMillis(Instant.parse("2017-09-12T00:00:01.00Z")));
344             input.add("REQUEST_ID");
345             input.add("SUB_REQUEST_ID");
346             input.add("ORIGINATOR_ID");
347             input.add(dateToStringConverterMillis(Instant.parse("2018-09-12T00:00:02.00Z")));
348             input.add(dateToStringConverterMillis(Instant.parse("2018-09-12T20:00:02.00Z")));
349             input.add("TARGET_ID");
350             input.add("TARGET_TYPE");
351             input.add("Audit");
352             input.add(String.valueOf(200));
353             input.add("SERVICE_INSTANCE_ID");
354             input.add("ACCEPTED");
355             input.add("DESCRIPTION");
356             input.add("test");
357             input.add("test");
358             input.add("test");
359             input.add("EXCLUSIVE");
360
361             for (int i = 1; i <= input.size(); i++) {
362                 ps.setString(i, input.get(i-1));
363             }
364             ps.execute();
365
366             if (checkIfRowIsPresent(input.get(0))) {
367                 System.out.println("RECORD INSERTED " + input.get(0));
368             }
369         }
370     }
371
372     private ResultSet returnResult(Object[] obj) throws Exception {
373         String query = (String) obj[0];
374         ArrayList<String> args = (ArrayList<String>) obj[1];
375         System.out.println("Query: " + query + "\nArgs: " + args);
376         try (
377              Connection con = dbConnectionPool.getConnection();
378              PreparedStatement ps = con.prepareStatement(query)
379              ) {
380             for (int i = 1; i <= args.size(); i++) {
381                 ps.setString(i, args.get(i - 1));
382             }
383             CachedRowSet rowSet = new CachedRowSetImpl();
384             rowSet.populate(ps.executeQuery());
385             return rowSet;
386         }
387     }
388
389     @Test
390     public void testMarkTransactionsAborted() throws SQLException {
391         TransactionRecord input = prepareTransactionsInput();
392         insertRecord(input);
393         Mockito.when(dbLibService.writeData(anyString(), anyObject(), anyString())).thenAnswer(invocation ->
394                 testMarkAbortedInMemory(invocation.getArguments()));
395         transactionRecorderImpl.markTransactionsAborted("123~");
396     }
397
398     @Test
399     public void testMarkTransactionsAbortedExceptionFlow() throws SQLException {
400         TransactionRecord input = prepareTransactionsInput();
401         insertRecord(input);
402         Mockito.when(dbLibService.writeData(anyString(), anyObject(), anyString())).thenThrow(new SQLException());
403         expectedEx.expect(RuntimeException.class);
404         expectedEx.expectMessage("In progress transactions couldn't be marked aborted on server start up");
405         expectedEx.expectCause(isA(SQLException.class));
406         transactionRecorderImpl.markTransactionsAborted("123~");
407     }
408
409     @Test
410     public void testGetRecords() throws SQLException, APPCException {
411         CachedRowSetImpl rowset = Mockito.mock(CachedRowSetImpl.class);
412         Mockito.when(rowset.next()).thenReturn(true).thenReturn(false);
413         Mockito.when(rowset.getString(TRANSACTION_ATTRIBUTES.STATE.getColumnName())).thenReturn("NAME");
414         Mockito.when(dbLibService.getData(anyString(), anyObject(), anyString())).thenReturn(rowset);
415         Assert.assertEquals(RequestStatus.UNKNOWN,
416                 transactionRecorderImpl.getRecords(null, "SUBREQUEST_ID", "ORIGINATOR_ID", null).get(0));
417     }
418
419     @Test
420     public void testGetRecordsSqlException() throws SQLException, APPCException {
421         Mockito.when(dbLibService.getData(anyString(), anyObject(), anyString())).thenThrow(new SQLException());
422         expectedEx.expect(APPCException.class);
423         expectedEx.expectMessage("Error retrieving record for requestID null and vnfId null");
424         expectedEx.expectCause(isA(SQLException.class));
425         transactionRecorderImpl.getRecords(null, null, null, null);
426     }
427
428     private ResultSet inMemoryExecutionWithResultSet(Object[] obj) throws Exception {
429         String query = (String) obj[0];
430         ArrayList<String> args = (ArrayList<String>) obj[1];
431         // System.out.println("Query: " + query + "\nArgs: " + args);
432         try (
433              Connection con = dbConnectionPool.getConnection();
434              PreparedStatement ps = con.prepareStatement(query)
435              ) {
436             for (int i = 1; i <= args.size(); i++) {
437                 ps.setString(i, args.get(i - 1));
438             }
439             CachedRowSet rowSet = new CachedRowSetImpl();
440             rowSet.populate(ps.executeQuery());
441             return rowSet;
442         }
443     }
444
445     private boolean testMarkAbortedInMemory(Object[] obj) throws Exception {
446         String query = (String) obj[0];
447         ArrayList<String> args = (ArrayList<String>) obj[1];
448         try (
449              Connection con = dbConnectionPool.getConnection();
450              PreparedStatement ps = con.prepareStatement(query)
451              ) {
452             for (int i = 1; i <= args.size(); i++) {
453                 ps.setString(i, args.get(i - 1));
454             }
455             ps.execute();
456             return isTransactionAborted();
457         }
458     }
459
460     private boolean isTransactionAborted() throws Exception {
461         String query = "SELECT COUNT(*) FROM  TRANSACTIONS WHERE STATE = ?";
462         try (
463              Connection con = dbConnectionPool.getConnection();
464              PreparedStatement ps = con.prepareStatement(query)
465              ) {
466             ps.setString(1, RequestStatus.ABORTED.toString());
467             try (
468                  ResultSet rs = ps.executeQuery()
469                  ) {
470                 while (rs.next()) {
471                     int value = rs.getInt(1);
472                     if (value == 1) {
473                         System.out.println("Non terminal Transactions are aborted");
474                         return true;
475                     }
476                 }
477                 throw new Exception("Transactions are not aborted");
478             }
479         }
480     }
481
482     private boolean testUpdateInMemory(Object[] obj) throws Exception {
483         String query = (String) obj[0];
484         ArrayList<String> args = (ArrayList<String>) obj[1];
485         try (
486              Connection con = dbConnectionPool.getConnection();
487              PreparedStatement ps = con.prepareStatement(query)
488              ) {
489             for (int i = 1; i <= args.size(); i++) {
490                 System.out.println("Value at " + i + ": " + args.get(i - 1));
491                 ps.setString(i, args.get(i - 1));
492             }
493             ps.execute();
494             String updatedValue = checkIfValueIsUpdated(args.get(1));
495             System.out.println("updated Value is " + updatedValue);
496             if (updatedValue.equals("Firewall")) {
497                 return true;
498             }
499             throw new Exception("Not Updated");
500         }
501     }
502
503     private boolean testStoreInMemory(Object[] obj) throws Exception {
504         String query = (String) obj[0];
505         ArrayList<String> args = (ArrayList<String>) obj[1];
506         try (
507              Connection con = dbConnectionPool.getConnection();
508              PreparedStatement ps = con.prepareStatement(query)
509              ) {
510             for (int i = 1; i <= args.size(); i++) {
511                 ps.setString(i, args.get(i - 1));
512             }
513             ps.execute();
514             if (checkIfRowIsPresent(args.get(0))) {
515                 return true;
516             }
517             throw new Exception("Failed to update");
518         }
519     }
520
521     private TransactionRecord prepareTransactionsInput() {
522         TransactionRecord input = new TransactionRecord();
523         input.setTransactionId(UUID.randomUUID().toString());
524         input.setOriginTimestamp(Instant.parse("2017-09-11T00:00:01.00Z"));
525         input.setRequestId("REQUEST_ID");
526         input.setSubRequestId("SUB_REQUEST_ID");
527         input.setOriginatorId("ORIGINATOR_ID");
528         input.setStartTime(Instant.parse("2017-09-11T00:00:02.00Z"));
529         input.setTargetId("TARGET_ID");
530         input.setTargetType("TARGET_TYPE");
531         input.setServiceInstanceId("SERVICE_INSTANCE_ID");
532         input.setOperation(VNFOperation.ActionStatus);
533         input.setResultCode(200);
534         input.setRequestState(RequestStatus.ACCEPTED);
535         input.setDescription("DESCRIPTION");
536         input.setMode(Flags.Mode.EXCLUSIVE);
537         return input;
538     }
539
540     private void insertRecord(TransactionRecord input) throws SQLException {
541         final String STORE_DATE_QUERY = TransactionConstants.INSERT_INTO + TransactionConstants.TRANSACTIONS +
542                 " values (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
543         try (
544              Connection con = dbConnectionPool.getConnection();
545              PreparedStatement ps = con.prepareStatement(STORE_DATE_QUERY)
546              ) {
547             ArrayList<String> args = prepareArguments(input);
548             args.remove(0);
549             args.add(0, "123~" + input.getTransactionId());
550             for (int i = 1; i <= 18; i++) {
551                 ps.setString(i, args.get(i - 1));
552             }
553             ps.execute();
554             if (checkIfRowIsPresent(args.get(0))) {
555                 System.out.println("RECORD INSERTED " + args.get(0));
556             }
557         }
558     }
559
560     private ArrayList<String> prepareArguments(TransactionRecord input) {
561         ArrayList<String> arguments = new ArrayList<>();
562         arguments.add(input.getTransactionId());
563         arguments.add(dateToStringConverterMillis(input.getOriginTimestamp()));
564         arguments.add(input.getRequestId());
565         arguments.add(input.getSubRequestId());
566         arguments.add(input.getOriginatorId());
567         arguments.add(dateToStringConverterMillis(input.getStartTime()));
568         arguments.add(dateToStringConverterMillis(input.getEndTime()));
569         arguments.add(input.getTargetId());
570         arguments.add(input.getTargetType());
571         arguments.add(input.getOperation().name());
572         arguments.add(String.valueOf(input.getResultCode()));
573         arguments.add(input.getDescription());
574         arguments.add(input.getRequestState());
575         arguments.add(input.getServiceInstanceId());
576         arguments.add(input.getVnfcName());
577         arguments.add(input.getVserverId());
578         arguments.add(input.getVfModuleId());
579         arguments.add(input.getMode());
580
581         return arguments;
582     }
583
584     private static String dateToStringConverterMillis(Instant date) {
585         if (date == null) {
586             return null;
587         }
588         DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS").withZone(ZoneOffset.UTC);
589         return formatter.format(date);
590     }
591
592     private boolean checkIfRowIsPresent(String key) {
593         Connection con = null;
594         ResultSet rs = null;
595         PreparedStatement ps = null;
596         try {
597             con = dbConnectionPool.getConnection();
598             ps = con.prepareStatement("SELECT COUNT(*) FROM  TRANSACTIONS WHERE TRANSACTION_ID = ?");
599             ps.setString(1, key);
600             rs = ps.executeQuery();
601             while (rs.next()) {
602                 int value = rs.getInt(1);
603                 System.out.println("KEY checked is " + key + " COUNT RETURNED IS " + value);
604                 if (value == 1) {
605                     return true;
606                 }
607             }
608         } catch (SQLException e) {
609             e.printStackTrace();
610         } finally {
611             DBHelper.close(rs, ps, con);
612         }
613         return false;
614     }
615
616     private String checkIfValueIsUpdated(String key) throws Exception {
617         try (
618              Connection con = dbConnectionPool.getConnection();
619              PreparedStatement ps = con.prepareStatement("SELECT TARGET_TYPE,TRANSACTION_ID FROM TRANSACTIONS" +
620                                                          " WHERE TRANSACTION_ID = ?")
621              ) {
622             ps.setString(1, key);
623             try (
624                  ResultSet rs = ps.executeQuery()
625                  ) {
626                while (rs.next()) {
627                    String value = rs.getString("TARGET_TYPE");
628                    String transactionId = rs.getString("TRANSACTION_ID");
629                    System.out.println("Updated data: TRANSACTION_ID: " + transactionId + " TARGET_TYPE: " + value);
630                    return value;
631                }
632                throw new Exception("Value not found");
633             }
634         }
635     }
636
637
638     /**
639      * Verify the transactionRecorderImpl. getRecords () can be fetch with each of the parameter combinations
640      * @throws Exception
641      *//*
642     @Test
643     public void test_api_getRecords() throws Exception {
644
645
646         final int requestId = 0;
647         final int subrequestId = 1;
648         final int originatorId = 2;
649         final int vnfId = 3;
650         final int requestStatus = 4;
651
652
653         String[][] trCreateMatrix = {
654             {"request1", "subrequestId1", "originatorId1", "vnfId1", RequestStatus.UNKNOWN.name()},
655             {"request1", "subrequestId2", "originatorId1", "vnfId1", RequestStatus.RECEIVED.name()},
656             {"request2", "subrequestId1", "originatorId1", "vnfId1", RequestStatus.ACCEPTED.name()},
657             {"request2", "subrequestId2", "originatorId1", "vnfId1", RequestStatus.REJECTED.name()},
658             {"request1", "subrequestId1", "originatorId1", "vnfId2", RequestStatus.SUCCESSFUL.name()},
659             {"request1", "subrequestId2", "originatorId1", "vnfId2", RequestStatus.FAILED.name()},
660             {"request2", "subrequestId1", "originatorId1", "vnfId2", RequestStatus.TIMEOUT.name()},
661             {"request2", "subrequestId2", "originatorId1", "vnfId2", RequestStatus.ABORTED.name()},
662             {"request1", "subrequestId1", "originatorId2", "vnfId1", RequestStatus.UNKNOWN.name()},
663             {"request1", "subrequestId2", "originatorId2", "vnfId1", RequestStatus.RECEIVED.name()},
664             {"request2", "subrequestId1", "originatorId2", "vnfId1", RequestStatus.ACCEPTED.name()},
665             {"request2", "subrequestId2", "originatorId2", "vnfId1", RequestStatus.REJECTED.name()},
666             {"request1", "subrequestId1", "originatorId2", "vnfId2", RequestStatus.SUCCESSFUL.name()},
667             {"request1", "subrequestId2", "originatorId2", "vnfId2", RequestStatus.FAILED.name()},
668             {"request2", "subrequestId1", "originatorId2", "vnfId2", RequestStatus.TIMEOUT.name()},
669             {"request2", "subrequestId2", "originatorId2", "vnfId2", RequestStatus.ABORTED.name()},
670         };
671
672
673         TransactionRecord tr = new TransactionRecord();
674         tr.setTimeStamp(Instant.parse("2017-09-11T00:00:01.00Z"));
675         tr.setStartTime(Instant.parse("2017-09-11T00:00:02.00Z"));
676         tr.setEndTime(Instant.parse("2017-09-11T00:00:03.00Z"));
677         tr.setTargetType("TARGET_TYPE");
678         tr.setSubComponent("SUB_COMPONENT");
679         tr.setOperation(VNFOperation.ActionStatus);
680         tr.setResultCode("RESULT_CODE");
681         tr.setDescription("DESCRIPTION");
682
683         for (int row = 0; row < trCreateMatrix.length; row++) {
684             tr.setRequestID(trCreateMatrix[row][requestId]);
685             tr.setSubRequestID(trCreateMatrix[row][subrequestId]);
686             tr.setOriginatorId(trCreateMatrix[row][originatorId]);
687             tr.setTargetID(trCreateMatrix[row][vnfId]);
688             tr.setRequestStatus(RequestStatus.valueOf(trCreateMatrix[row][requestStatus]));
689             transactionRecorderImpl.store(tr);
690         }
691
692
693         String[][] trSearchMatrix = {
694             {"request1", null, null, "vnfId1"},
695             {"request2", "subrequestId1", null, "vnfId1"},
696             {"request1", null, "originatorId1", "vnfId1"},
697             {"request2", "subrequestId2", "originatorId1", "vnfId1"},
698         };
699
700
701         for (int i = 0; i < trSearchMatrix.length; i++) {
702             final int row = i;
703             List<RequestStatus> actualList = transactionRecorderImpl
704                 .getRecords(trSearchMatrix[row][requestId], trSearchMatrix[row][subrequestId],
705                     trSearchMatrix[row][originatorId], trSearchMatrix[row][vnfId])
706                 .stream()
707                 .sorted()
708                 .collect(Collectors.toList());
709
710             List<RequestStatus> expectedList = Arrays.stream(trCreateMatrix)
711                 .filter(entry -> entry[requestId].equals(trSearchMatrix[row][requestId]))
712                 .filter(entry -> trSearchMatrix[row][subrequestId] == null || entry[subrequestId].equals
713                     (trSearchMatrix[row][subrequestId]))
714                 .filter(entry -> trSearchMatrix[row][originatorId] == null || entry[originatorId].equals
715                     (trSearchMatrix[row][originatorId]))
716                 .filter(entry -> entry[vnfId].equals(trSearchMatrix[row][vnfId]))
717                 .map(entry -> RequestStatus.valueOf(entry[requestStatus]))
718                 .sorted()
719                 .collect(Collectors.toList());
720             System.out.println(expectedList);
721             System.out.println(actualList);
722             Assert.assertEquals("Unexpected results: ", expectedList, actualList);
723
724         }
725
726
727     }*/
728 }