• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.adservices.common.logging;
18 
19 import static com.android.adservices.common.logging.annotations.ExpectErrorLogUtilWithExceptionCall.ANNOTATION_NAME;
20 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
21 
22 import static org.mockito.ArgumentMatchers.any;
23 import static org.mockito.ArgumentMatchers.anyInt;
24 
25 import android.util.Log;
26 
27 import com.android.adservices.common.logging.annotations.ExpectErrorLogUtilWithExceptionCall;
28 import com.android.adservices.common.logging.annotations.ExpectErrorLogUtilWithExceptionCalls;
29 import com.android.adservices.common.logging.annotations.SetErrorLogUtilDefaultParams;
30 import com.android.adservices.errorlogging.ErrorLogUtil;
31 import com.android.adservices.shared.testing.AbstractLogVerifier;
32 import com.android.adservices.shared.testing.TestHelper;
33 
34 import com.google.common.collect.ImmutableList;
35 import com.google.common.collect.ImmutableSet;
36 
37 import org.junit.runner.Description;
38 
39 import java.util.Arrays;
40 import java.util.List;
41 import java.util.Set;
42 import java.util.stream.Collectors;
43 
44 /** Log verifier for {@code ErrorLogUtil.e(Throwable, int, int)} invocations. */
45 public final class AdServicesErrorLogUtilWithExceptionVerifier
46         extends AbstractLogVerifier<ErrorLogUtilCall> {
47     @Override
mockLogCalls()48     protected void mockLogCalls() {
49         // Mock ErrorLogUtil.e(Throwable, int, int) calls and capture logging arguments.
50         doAnswer(
51                         invocation -> {
52                             recordActualCall(
53                                     new ErrorLogUtilCall(
54                                             ((Throwable) invocation.getArgument(0)).getClass(),
55                                             invocation.getArgument(1),
56                                             invocation.getArgument(2)));
57                             return null;
58                         })
59                 .when(() -> ErrorLogUtil.e(any(Throwable.class), anyInt(), anyInt()));
60     }
61 
62     @Override
getExpectedLogCalls(Description description)63     public Set<ErrorLogUtilCall> getExpectedLogCalls(Description description) {
64         List<ExpectErrorLogUtilWithExceptionCall> annotations = getAnnotations(description);
65         SetErrorLogUtilDefaultParams defaultParams =
66                 TestHelper.getAnnotation(description, SetErrorLogUtilDefaultParams.class);
67 
68         if (annotations.isEmpty()) {
69             Log.v(mTag, "No @" + ANNOTATION_NAME + " found over test method.");
70             return ImmutableSet.of();
71         }
72 
73         Set<ErrorLogUtilCall> expectedCalls =
74                 annotations.stream()
75                         .peek(a -> validateTimes(a.times(), ANNOTATION_NAME))
76                         .map(a -> ErrorLogUtilCall.createFrom(a, defaultParams))
77                         .collect(Collectors.toSet());
78 
79         if (expectedCalls.size() != annotations.size()) {
80             throw new IllegalStateException(
81                     "Detected @"
82                             + ANNOTATION_NAME
83                             + " annotations representing the same "
84                             + "invocation! De-dupe by using times arg");
85         }
86 
87         return expectedCalls;
88     }
89 
90     @Override
getResolutionMessage()91     public String getResolutionMessage() {
92         return "Please make sure to use @"
93                 + ANNOTATION_NAME
94                 + "(..) "
95                 + "over test method to denote "
96                 + "all expected ErrorLogUtil.e(Throwable, int, int) calls.";
97     }
98 
getAnnotations(Description description)99     private List<ExpectErrorLogUtilWithExceptionCall> getAnnotations(Description description) {
100         // Scan for multiple annotation container
101         ExpectErrorLogUtilWithExceptionCalls multiple =
102                 description.getAnnotation(ExpectErrorLogUtilWithExceptionCalls.class);
103         if (multiple != null) {
104             return Arrays.stream(multiple.value()).collect(Collectors.toList());
105         }
106 
107         // Scan for single annotation
108         ExpectErrorLogUtilWithExceptionCall single =
109                 description.getAnnotation(ExpectErrorLogUtilWithExceptionCall.class);
110         return single == null ? ImmutableList.of() : ImmutableList.of(single);
111     }
112 }
113