1 /*
2  * Copyright (C) 2021 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 package com.android.tradefed.config.filter;
17 
18 import com.android.tradefed.config.IConfiguration;
19 import com.android.tradefed.log.LogUtil.CLog;
20 import com.android.tradefed.service.TradefedFeatureClient;
21 import com.android.tradefed.testtype.suite.SuiteTestFilter;
22 
23 import com.google.common.base.Strings;
24 import com.proto.tradefed.feature.FeatureResponse;
25 
26 import java.util.ArrayList;
27 import java.util.HashMap;
28 import java.util.LinkedHashSet;
29 import java.util.List;
30 import java.util.Map;
31 import java.util.Set;
32 
33 /**
34  * Helper to get the previous passed test filters.
35  */
36 public class GetPreviousPassedHelper {
37 
GetPreviousPassedHelper()38     public GetPreviousPassedHelper() {}
39 
40     /**
41      * Fetch previous passed tests if applicable from previous attempt.
42      *
43      * @param config The configuration to apply filter to
44      * @return The list of tests that previously passed.
45      */
getPreviousPassedFilters(IConfiguration config)46     public Set<String> getPreviousPassedFilters(IConfiguration config) {
47         Set<String> filters = new LinkedHashSet<>();
48         List<SuiteTestFilter> previousPassedFilters = new ArrayList<>();
49         if (config == null) {
50             return filters;
51         }
52         if (!config.getCommandOptions().filterPreviousPassedTests()) {
53             return filters;
54         }
55         // Build the query of previous passed test
56         Map<String, String> args = new HashMap<>();
57         Map<String, String> invocationData = config
58                 .getCommandOptions()
59                 .getInvocationData()
60                 .getUniqueMap();
61         String invocationId = invocationData.get("invocation_id");
62         if (!Strings.isNullOrEmpty(invocationId)) {
63             args.put("invocation_id", invocationId);
64         }
65         if (args.isEmpty()) {
66             return filters;
67         }
68         String attempt = invocationData.get("attempt_index");
69         if ("0".equals(attempt)) {
70             return filters;
71         }
72         // Include the shard_index in query to filter server side.
73         if (config.getCommandOptions().getShardIndex() != null) {
74             args.put("shard_index", Integer.toString(config.getCommandOptions().getShardIndex()));
75         }
76         try (TradefedFeatureClient client = new TradefedFeatureClient()) {
77             FeatureResponse previousPassed = client.triggerFeature("getPreviousPassed", args);
78             convertResponseToFilter(previousPassed, previousPassedFilters);
79             boolean filterShards =
80                     previousPassedFilters.removeIf(
81                             f ->
82                                     f.getShardIndex() != null
83                                             && !f.getShardIndex()
84                                                     .equals(
85                                                             config
86                                                                     .getCommandOptions()
87                                                                     .getShardIndex()));
88             if (filterShards) {
89                 CLog.d("Remaining filter for the shard: %s", previousPassedFilters);
90             }
91             previousPassedFilters.stream().forEach(f->filters.add(f.toString()));
92         } catch (RuntimeException e) {
93             CLog.e(e);
94         }
95         return filters;
96     }
97 
convertResponseToFilter( FeatureResponse previousPassed, List<SuiteTestFilter> previousPassedFilters)98     private void convertResponseToFilter(
99             FeatureResponse previousPassed, List<SuiteTestFilter> previousPassedFilters) {
100         if (previousPassed.hasErrorInfo()) {
101             return;
102         }
103         if (Strings.isNullOrEmpty(previousPassed.getResponse())) {
104             return;
105         }
106         for (String line : previousPassed.getResponse().split("\n")) {
107             if (line.isEmpty()) {
108                 continue;
109             }
110             previousPassedFilters.add(SuiteTestFilter.createFrom(line));
111         }
112     }
113 }
114