aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib/skyframe/TestSuiteExpansionFunction.java
blob: 0b563f74b9976d061d6d8fbaf6d2a603c636f19c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
// Copyright 2015 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.devtools.build.lib.skyframe;

import com.google.common.collect.ImmutableSet;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.cmdline.PackageIdentifier;
import com.google.devtools.build.lib.cmdline.ResolvedTargets;
import com.google.devtools.build.lib.packages.NoSuchTargetException;
import com.google.devtools.build.lib.packages.Package;
import com.google.devtools.build.lib.packages.Target;
import com.google.devtools.build.lib.packages.TargetUtils;
import com.google.devtools.build.lib.skyframe.TestSuiteExpansionValue.TestSuiteExpansionKey;
import com.google.devtools.build.skyframe.SkyFunction;
import com.google.devtools.build.skyframe.SkyKey;
import com.google.devtools.build.skyframe.SkyValue;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nullable;

/**
 * TestSuiteExpansionFunction takes a list of targets and expands all test suites in those targets.
 */
final class TestSuiteExpansionFunction implements SkyFunction {
  @Override
  public SkyValue compute(SkyKey key, Environment env) throws InterruptedException {
    TestSuiteExpansionKey expansion = (TestSuiteExpansionKey) key.argument();
    ResolvedTargets<Target> targets = labelsToTargets(env, expansion.getTargets(), false);
    List<SkyKey> testsInSuitesKeys = new ArrayList<>();
    for (Target target : targets.getTargets()) {
      if (TargetUtils.isTestSuiteRule(target)) {
        testsInSuitesKeys.add(TestsInSuiteValue.key(target, true));
      }
    }
    Map<SkyKey, SkyValue> testsInSuites = env.getValues(testsInSuitesKeys);
    if (env.valuesMissing()) {
      return null;
    }

    Set<Label> result = new LinkedHashSet<>();
    boolean hasError = targets.hasError();
    for (Target target : targets.getTargets()) {
      if (TargetUtils.isTestRule(target)) {
        result.add(target.getLabel());
      } else if (TargetUtils.isTestSuiteRule(target)) {
        TestsInSuiteValue value = (TestsInSuiteValue) testsInSuites.get(
            TestsInSuiteValue.key(target, true));
        if (value != null) {
          result.addAll(value.getLabels().getTargets());
          hasError |= value.getLabels().hasError();
        }
      } else {
        result.add(target.getLabel());
      }
    }
    if (env.valuesMissing()) {
      return null;
    }
    // We use ResolvedTargets in order to associate an error flag; the result should never contain
    // any filtered targets.
    return new TestSuiteExpansionValue(new ResolvedTargets<>(result, hasError));
  }

  static ResolvedTargets<Target> labelsToTargets(
      Environment env, ImmutableSet<Label> labels, boolean hasError) throws InterruptedException {
    Set<PackageIdentifier> pkgIdentifiers = new LinkedHashSet<>();
    for (Label label : labels) {
      pkgIdentifiers.add(label.getPackageIdentifier());
    }
    // Don't bother to check for exceptions - the incoming list should only contain valid targets.
    Map<SkyKey, SkyValue> packages = env.getValues(PackageValue.keys(pkgIdentifiers));
    if (env.valuesMissing()) {
      return null;
    }

    ResolvedTargets.Builder<Target> builder = ResolvedTargets.builder();
    builder.mergeError(hasError);
    Map<PackageIdentifier, Package> packageMap = new HashMap<>();
    for (Map.Entry<SkyKey, SkyValue> entry : packages.entrySet()) {
      packageMap.put(
          (PackageIdentifier) entry.getKey().argument(),
          ((PackageValue) entry.getValue()).getPackage());
    }

    for (Label label : labels) {
      Package pkg = packageMap.get(label.getPackageIdentifier());
      if (pkg == null) {
        continue;
      }
      try {
        builder.add(pkg.getTarget(label.getName()));
        if (pkg.containsErrors()) {
          builder.setError();
        }
      } catch (NoSuchTargetException e) {
        builder.setError();
      }
    }
    return builder.build();
  }

  @Nullable
  @Override
  public String extractTag(SkyKey skyKey) {
    return null;
  }
}