b65e797b8fbc04d0c9aba4624fc4ba5068758b06
[vid.git] / vid-automation / src / test / java / org / onap / vid / more / LoggerFormatTest.java
1 package org.onap.vid.more;
2
3 import static java.util.Collections.reverse;
4 import static java.util.stream.Collectors.toList;
5 import static org.hamcrest.CoreMatchers.containsString;
6 import static org.hamcrest.CoreMatchers.is;
7 import static org.hamcrest.MatcherAssert.assertThat;
8 import static org.hamcrest.Matchers.allOf;
9 import static org.hamcrest.Matchers.contains;
10 import static org.hamcrest.Matchers.containsInAnyOrder;
11 import static org.hamcrest.Matchers.containsInRelativeOrder;
12 import static org.hamcrest.Matchers.either;
13 import static org.hamcrest.Matchers.emptyOrNullString;
14 import static org.hamcrest.Matchers.greaterThan;
15 import static org.hamcrest.Matchers.greaterThanOrEqualTo;
16 import static org.hamcrest.Matchers.hasSize;
17 import static org.hamcrest.Matchers.matchesPattern;
18 import static vid.automation.test.services.SimulatorApi.retrieveRecordedRequests;
19
20 import com.fasterxml.jackson.databind.JsonNode;
21
22 import java.lang.reflect.Method;
23 import java.net.URI;
24 import java.util.ArrayList;
25 import java.util.Arrays;
26 import java.util.HashMap;
27 import java.util.HashSet;
28 import java.util.LinkedList;
29 import java.util.List;
30 import java.util.Map;
31 import org.apache.commons.lang3.StringUtils;
32 import org.apache.logging.log4j.LogManager;
33 import org.apache.logging.log4j.Logger;
34 import org.jetbrains.annotations.NotNull;
35 import org.onap.simulator.presetGenerator.presets.aai.PresetAAIGetSubscribersGet;
36 import org.onap.vid.api.BaseApiTest;
37 import org.springframework.web.client.RestTemplate;
38 import org.testng.annotations.BeforeClass;
39 import org.testng.annotations.DataProvider;
40 import org.testng.annotations.Test;
41 import vid.automation.test.services.SimulatorApi;
42 import vid.automation.test.services.SimulatorApi.RecordedRequests;
43
44 public class LoggerFormatTest extends BaseApiTest {
45
46     private final static String logChecker = System.getProperty("EELF_LOG_CHECKER", "http://my-logchecker:8888/validate");
47     private final Logger logger = LogManager.getLogger(LoggerFormatTest.class);
48     private final int PRIORITY_LAST = 999;
49
50     public enum LogName {
51         audit2019, error, metrics2019, debug
52     }
53
54     @BeforeClass
55     public void login() {
56         super.login();
57     }
58
59     @BeforeClass
60     public void setAaiSubscribers() {
61         SimulatorApi.registerExpectationFromPreset(new PresetAAIGetSubscribersGet(), SimulatorApi.RegistrationStrategy.CLEAR_THEN_SET);
62     }
63
64     @DataProvider
65     public static Object[][] logsAndFormats(Method test) {
66         return new Object[][]{
67                 {LogName.debug, "debug", 0.65 },
68                 {LogName.metrics2019, "metric-ELS-2019.11", 0.95},
69                 {LogName.audit2019, "audit-ELS-2019.11", 0.95}
70         };
71     }
72
73
74     @Test(dataProvider = "logsAndFormats", priority = PRIORITY_LAST)
75     public void validateLogsAndFormat(LogName logName, String logCheckerFormat, Double expectedRank){
76         String logLines = validateLogsFormat(logName, logCheckerFormat, expectedRank);
77
78         if (logName == LogName.audit2019)
79         {
80             moreValidationsForAuditFormat(logLines);
81         }
82     }
83
84     //more validations for log format that logcheck doesn't verify
85     private void moreValidationsForAuditFormat (String logLines){
86         splitLogLines(logLines).forEach(line -> {
87             String[] records = line.split("\\|");
88             assertThat("server name shall be empty", records[5], emptyOrNullString());
89
90             //authenticated request shall logs with userId.
91             final String serviceName = records[6];
92             if (StringUtils.containsAny(serviceName, "aai", "mso")) {
93                 assertThat("Partner name shall be userId", records[7], matchesPattern("^[A-Za-z0-9]{4,15}$"));
94             }
95
96             assertThat("Severity shall be empty", records[13], emptyOrNullString());
97             assertThat("marker", records[21], either(is("ENTRY")).or(is("EXIT")));
98         });
99     }
100
101     private String validateLogsFormat (LogName logName, String logType){
102         return validateLogsFormat(logName, logType, 0.95);
103     }
104
105     private String validateLogsFormat (LogName logName, String logType,double score){
106
107         String logLines = getLogLines(logName);
108         logger.info("logLines are: " + logLines);
109         JsonNode response = getCheckerResults(logType, logLines);
110         logger.info("Response is:" + response.toString());
111
112         int total_records = response.path("summary").path("total_records").asInt();
113         int valid_records = response.path("summary").path("valid_records").asInt();
114
115         assertThat(total_records, greaterThan(30)); //make sure we have at least 30 total records
116         assertThat((double) valid_records / total_records, is(greaterThanOrEqualTo(score)));
117
118         return logLines;
119     }
120
121     private String getLogLines (LogName logname){
122         return getLogLines(logname, 5000, 30, restTemplate, uri);
123     }
124
125     public static String getLogLines (LogName logname,int maxRows, int minRows, RestTemplate restTemplate, URI uri){
126         String logLines = restTemplate.getForObject(uri + "/logger/" + logname.name() + "?limit={maxRows}", String.class, maxRows);
127         assertThat("expecting at least " + minRows + " rows in " + logname.name(),
128                 StringUtils.countMatches(logLines, '\n') + 1,
129                 is(greaterThanOrEqualTo(minRows)));
130         return logLines;
131     }
132
133     /**
134      * @return Chronological-ordered list of recent log-lines
135      */
136     public static List<String> getLogLinesAsList (LogName logname,int maxRows, int minRows, RestTemplate restTemplate, URI uri){
137         String logLines = LoggerFormatTest.getLogLines(logname, maxRows, minRows, restTemplate, uri);
138         List<String> lines = splitLogLines(logLines);
139
140         // Reverse
141         reverse(lines);
142
143         return lines;
144     }
145
146     @NotNull
147     private static List<String> splitLogLines (String logLines){
148         return new ArrayList<>(Arrays.asList(logLines.split("(\\r?\\n)")));
149     }
150
151
152     /**
153      * @return Chronological-ordered list of recent log-lines of a given requestId
154      */
155     public static List<String> getRequestLogLines (String requestId, LogName logname, RestTemplate restTemplate, URI uri){
156
157         List<String> lines = getLogLinesAsList(logname, 30, 1, restTemplate, uri);
158
159         //Filter
160         lines.removeIf(line -> !StringUtils.containsIgnoreCase(line, requestId));
161
162         return lines;
163     }
164
165     public static void verifyExistenceOfIncomingReqsInAuditLogs (RestTemplate restTemplate, URI uri, String requestId, String path){
166         List<String> logLines = getRequestLogLines(requestId, LogName.audit2019, restTemplate, uri);
167         String requestIdPrefix = "RequestID=";
168         assertThat("\nENTRY & EXIT logs are expected to include RequestId: " + requestId
169                         + " \nAnd request path: "
170                         + path +
171                         "\nin exactly two rows - inside the audit log matching lines:\n"
172                         + String.join("\n", logLines) + "\n",
173                 logLines,
174                 contains(
175                         allOf(
176                                 containsString(requestIdPrefix + requestId),
177                                 containsString("ENTRY"),
178                                 containsString(path)),
179                         allOf(
180                                 containsString(requestIdPrefix + requestId),
181                                 containsString("EXIT"),
182                                 containsString(path))
183                 ));
184     }
185
186     public static void assertHeadersAndMetricLogs (RestTemplate restTemplate, URI uri, String requestId, String path, int requestsSize){
187         List<String> logLines =
188                 getRequestLogLines(requestId, LogName.metrics2019, restTemplate, uri);
189
190         List<RecordedRequests> requests = retrieveRecordedRequests();
191         List<RecordedRequests> underTestRequests =
192                 requests.stream().filter(x -> x.path.contains(path)).collect(toList());
193
194         assertThat(underTestRequests, hasSize(requestsSize));
195
196         underTestRequests.forEach(request -> {
197             assertThat("X-ONAP-RequestID", request.headers.get("X-ONAP-RequestID"), contains(requestId));
198             assertThat("X-ECOMP-RequestID", request.headers.get("X-ECOMP-RequestID"), contains(requestId));
199             assertThat("X-ONAP-PartnerName", request.headers.get("X-ONAP-PartnerName"), contains("VID.VID"));
200         });
201
202         List<String> allInvocationIds = new LinkedList<>();
203
204         underTestRequests.forEach(request -> {
205
206             List<String> invocationIds = request.headers.get("X-InvocationID");
207             assertThat(invocationIds, hasSize(1));
208
209             String invocationId = invocationIds.get(0);
210             allInvocationIds.add(invocationId);
211
212             assertIdsInMetricsLog(logLines, requestId, invocationId);
213         });
214
215         //make sure no InvocationId is repeated twice
216         assertThat("expect all InvocationIds to be unique",
217                 allInvocationIds, containsInAnyOrder(new HashSet<>(allInvocationIds).toArray()));
218     }
219
220     public static void assertIdsInMetricsLog (List < String > logLines, String requestId, String invocationId){
221         assertThat("request id and invocation id must be found in exactly two rows in: \n" + String.join("\n", logLines),
222                 logLines,
223                 containsInRelativeOrder(
224                         allOf(
225                                 containsString("RequestID=" + requestId),
226                                 containsString("InvocationID=" + invocationId),
227                                 containsString("Invoke")),
228                         allOf(
229                                 containsString("RequestID=" + requestId),
230                                 containsString("InvocationID=" + invocationId),
231                                 containsString("InvokeReturn"))
232                 ));
233     }
234
235     private JsonNode getCheckerResults (String logtype, String logLines){
236         Map<String, String> params = new HashMap<>();
237         params.put("format", "raw");
238         params.put("type", logtype);
239         params.put("component", "vid");
240         params.put("data", logLines);
241
242         return restTemplate.postForObject(logChecker, params, JsonNode.class);
243     }
244 }