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