Home | History | Annotate | Download | only in build
      1 /*
      2  * Copyright (C) 2015 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.compatibility.common.tradefed.build;
     17 
     18 import com.android.annotations.VisibleForTesting;
     19 import com.android.compatibility.SuiteInfo;
     20 import com.android.tradefed.build.BuildInfo;
     21 import com.android.tradefed.build.BuildRetrievalError;
     22 import com.android.tradefed.build.DeviceBuildInfo;
     23 import com.android.tradefed.build.IBuildInfo;
     24 import com.android.tradefed.build.IBuildProvider;
     25 import com.android.tradefed.build.IDeviceBuildInfo;
     26 import com.android.tradefed.build.IDeviceBuildProvider;
     27 import com.android.tradefed.config.Option;
     28 import com.android.tradefed.config.Option.Importance;
     29 import com.android.tradefed.config.OptionClass;
     30 import com.android.tradefed.device.DeviceNotAvailableException;
     31 import com.android.tradefed.device.ITestDevice;
     32 
     33 import java.io.File;
     34 import java.text.SimpleDateFormat;
     35 import java.util.Date;
     36 import java.util.HashMap;
     37 import java.util.Map;
     38 import java.util.regex.Pattern;
     39 /**
     40  * A simple {@link IBuildProvider} that uses a pre-existing Compatibility install.
     41  */
     42 @OptionClass(alias="compatibility-build-provider")
     43 public class CompatibilityBuildProvider implements IDeviceBuildProvider {
     44 
     45     private static final Pattern RELEASE_BUILD = Pattern.compile("^[A-Z]{3}\\d{2}[A-Z]{0,1}$");
     46     private static final String ROOT_DIR = "ROOT_DIR";
     47     private static final String SUITE_BUILD = "SUITE_BUILD";
     48     private static final String SUITE_NAME = "SUITE_NAME";
     49     private static final String SUITE_FULL_NAME = "SUITE_FULL_NAME";
     50     private static final String SUITE_VERSION = "SUITE_VERSION";
     51     private static final String SUITE_PLAN = "SUITE_PLAN";
     52     private static final String RESULT_DIR = "RESULT_DIR";
     53     private static final String START_TIME_MS = "START_TIME_MS";
     54     private static final String DYNAMIC_CONFIG_OVERRIDE_URL = "DYNAMIC_CONFIG_OVERRIDE_URL";
     55 
     56     /* API Key for compatibility test project, used for dynamic configuration */
     57     private static final String API_KEY = "AIzaSyAbwX5JRlmsLeygY2WWihpIJPXFLueOQ3U";
     58 
     59     @Option(name="branch", description="build branch name to supply.")
     60     private String mBranch = null;
     61 
     62     @Option(name = "build-id",
     63             description =
     64                     "build version number to supply. Override the default cts version number.")
     65     private String mBuildId = null;
     66 
     67     @Option(name="build-flavor", description="build flavor name to supply.")
     68     private String mBuildFlavor = null;
     69 
     70     @Option(name="build-attribute", description="build attributes to supply.")
     71     private Map<String, String> mBuildAttributes = new HashMap<String,String>();
     72 
     73     @Option(name="use-device-build-info", description="Bootstrap build info from device")
     74     private boolean mUseDeviceBuildInfo = false;
     75 
     76     @Option(name="test-tag", description="test tag name to supply.")
     77     private String mTestTag = "cts";
     78 
     79     @Option(name = "dynamic-config-url",
     80             description = "Specify the url for override config")
     81     private String mURL = "https://androidpartner.googleapis.com/v1/dynamicconfig/"
     82             + "suites/{suite-name}/modules/{module}/version/{version}?key=" + API_KEY;
     83 
     84     @Option(name = "plan",
     85             description = "the test suite plan to run, such as \"everything\" or \"cts\"",
     86             importance = Importance.ALWAYS)
     87     private String mSuitePlan;
     88 
     89     /**
     90      * Util method to inject build attributes into supplied {@link IBuildInfo}
     91      * @param buildInfo
     92      */
     93     private void injectBuildAttributes(IBuildInfo buildInfo) {
     94         for (Map.Entry<String, String> entry : mBuildAttributes.entrySet()) {
     95             buildInfo.addBuildAttribute(entry.getKey(), entry.getValue());
     96         }
     97     }
     98 
     99     /**
    100      * {@inheritDoc}
    101      */
    102     @Override
    103     public IBuildInfo getBuild() {
    104         // Create a blank BuildInfo which will get populated later.
    105         String version = null;
    106         if (mBuildId != null) {
    107             version = mBuildId;
    108         } else {
    109             version = getSuiteInfoBuildNumber();
    110             if (version == null) {
    111                 version = IBuildInfo.UNKNOWN_BUILD_ID;
    112             }
    113         }
    114         IBuildInfo ctsBuild = new BuildInfo(version, mTestTag);
    115         if (mBranch  != null) {
    116             ctsBuild.setBuildBranch(mBranch);
    117         }
    118         if (mBuildFlavor != null) {
    119             ctsBuild.setBuildFlavor(mBuildFlavor);
    120         }
    121         injectBuildAttributes(ctsBuild);
    122         addCompatibilitySuiteInfo(ctsBuild);
    123         return ctsBuild;
    124     }
    125 
    126     /**
    127      * {@inheritDoc}
    128      */
    129     @Override
    130     public IBuildInfo getBuild(ITestDevice device)
    131             throws BuildRetrievalError, DeviceNotAvailableException {
    132         if (!mUseDeviceBuildInfo) {
    133             // return a regular build info without extracting device attributes into standard
    134             // build info fields
    135             return getBuild();
    136         } else {
    137             String buildId = device.getBuildId();
    138             String buildFlavor = device.getBuildFlavor();
    139             IBuildInfo info = new DeviceBuildInfo(buildId, mTestTag);
    140             if (mBranch == null) {
    141                 // if branch is not specified via param, make a pseudo branch name based on platform
    142                 // version and product info from device
    143                 mBranch = String.format("%s-%s-%s-%s",
    144                         device.getProperty("ro.product.brand"),
    145                         device.getProperty("ro.product.name"),
    146                         device.getProductVariant(),
    147                         device.getProperty("ro.build.version.release"));
    148             }
    149             info.setBuildBranch(mBranch);
    150             info.setBuildFlavor(buildFlavor);
    151             String buildAlias = device.getBuildAlias();
    152             if (RELEASE_BUILD.matcher(buildAlias).matches()) {
    153                 info.addBuildAttribute("build_alias", buildAlias);
    154             }
    155             injectBuildAttributes(info);
    156             addCompatibilitySuiteInfo(info);
    157             return info;
    158         }
    159     }
    160 
    161     /**
    162      * {@inheritDoc}
    163      */
    164     @Override
    165     public void buildNotTested(IBuildInfo info) {
    166         // ignore
    167     }
    168 
    169     /**
    170      * {@inheritDoc}
    171      */
    172     @Override
    173     public void cleanUp(IBuildInfo info) {
    174         // ignore
    175     }
    176 
    177     private void addCompatibilitySuiteInfo(IBuildInfo info) {
    178         long startTimeMs = System.currentTimeMillis();
    179         info.addBuildAttribute(SUITE_BUILD, getSuiteInfoBuildNumber());
    180         info.addBuildAttribute(SUITE_NAME, getSuiteInfoName());
    181         info.addBuildAttribute(SUITE_FULL_NAME, getSuiteInfoFullname());
    182         info.addBuildAttribute(SUITE_VERSION, getSuiteInfoVersion());
    183         info.addBuildAttribute(SUITE_PLAN, mSuitePlan);
    184         info.addBuildAttribute(START_TIME_MS, Long.toString(startTimeMs));
    185         info.addBuildAttribute(RESULT_DIR, getDirSuffix(startTimeMs));
    186         String rootDirPath = getRootDirPath();
    187         if (rootDirPath == null || rootDirPath.trim().equals("")) {
    188             throw new IllegalArgumentException(
    189                     String.format("Missing install path property %s_ROOT", getSuiteInfoName()));
    190         }
    191         File rootDir = new File(rootDirPath);
    192         if (!rootDir.exists()) {
    193             throw new IllegalArgumentException(
    194                     String.format("Root directory doesn't exist %s", rootDir.getAbsolutePath()));
    195         }
    196         info.addBuildAttribute(ROOT_DIR, rootDir.getAbsolutePath());
    197         // For DeviceBuildInfo we populate the testsDir folder of the build info.
    198         if (info instanceof IDeviceBuildInfo) {
    199             File testDir =  new File(rootDir, String.format("android-%s/testcases/",
    200                     getSuiteInfoName().toLowerCase()));
    201             ((IDeviceBuildInfo) info).setTestsDir(testDir, "0");
    202         }
    203         if (mURL != null && !mURL.isEmpty()) {
    204             info.addBuildAttribute(DYNAMIC_CONFIG_OVERRIDE_URL,
    205                     mURL.replace("{suite-name}", getSuiteInfoName()));
    206         }
    207     }
    208 
    209     /**
    210      * Returns the CTS_ROOT variable that the harness was started with.
    211      */
    212     @VisibleForTesting
    213     String getRootDirPath() {
    214         return System.getProperty(String.format("%s_ROOT", getSuiteInfoName()));
    215     }
    216 
    217     /**
    218      * Return the SuiteInfo name generated at build time. Exposed for testing.
    219      */
    220     protected String getSuiteInfoName() {
    221         return SuiteInfo.NAME;
    222     }
    223 
    224     /**
    225      * Return the SuiteInfo build number generated at build time. Exposed for testing.
    226      */
    227     protected String getSuiteInfoBuildNumber() {
    228         return SuiteInfo.BUILD_NUMBER;
    229     }
    230 
    231     /**
    232      * Return the SuiteInfo fullname generated at build time. Exposed for testing.
    233      */
    234     protected String getSuiteInfoFullname() {
    235         return SuiteInfo.FULLNAME;
    236     }
    237 
    238     /**
    239      * Return the SuiteInfo version generated at build time. Exposed for testing.
    240      */
    241     protected String getSuiteInfoVersion() {
    242         return SuiteInfo.VERSION;
    243     }
    244 
    245     /**
    246      * @return a {@link String} to use for directory suffixes created from the given time.
    247      */
    248     private String getDirSuffix(long millis) {
    249         return new SimpleDateFormat("yyyy.MM.dd_HH.mm.ss").format(new Date(millis));
    250     }
    251 }
    252