首页 > 代码库 > Cts框架解析(8)-IBuildProvider

Cts框架解析(8)-IBuildProvider

IBuildProvider接口中定义了三个方法


/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * 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.android.tradefed.build;

/**
 * Responsible for providing info regarding the build under test.
 */
public interface IBuildProvider {

    /**
     * Retrieve the data for build under test.
     *
     * @return the {@link IBuildInfo} for build under test or <code>null</code> if no build is
     * available for testing
     * @throws BuildRetrievalError if build info failed to be retrieved due to an unexpected error
     */
    public IBuildInfo getBuild() throws BuildRetrievalError;

    /**
     * Mark the given build as untested.
     * <p/>
     * Called in cases where TradeFederation has failed to complete testing on the build due to an
     * environment problem.
     *
     * @param info the {@link IBuildInfo} to reset
     */
    public void buildNotTested(IBuildInfo info);

    /**
     * Clean up any temporary build files.
     */
    public void cleanUp(IBuildInfo info);
}

该类主要是为了提供IBuildInfo信息的。所以目光转到IBuildInfo接口中:


/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * 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.android.tradefed.build;

import com.android.tradefed.device.ITestDevice;

import java.io.File;
import java.util.Collection;
import java.util.Map;

/**
 * Holds information about the build under test.
 */
public interface IBuildInfo {

    /**
     * Default value when build ID is unknown.
     */
    public final static String UNKNOWN_BUILD_ID = "-1";

    /**
     * Returns the unique identifier of build under test. Should never be null. Defaults to
     * {@link #UNKNOWN_BUILD_ID}.
     */
    public String getBuildId();

    /**
     * Return a unique name for the tests being run.
     */
    public String getTestTag();

    /**
     * Return complete name for the build being tested.
     * <p/>
     * A common implementation is to construct the build target name from a combination of
     * the build flavor and branch name. [ie (branch name)-(build flavor)]
     */
    public String getBuildTargetName();

    /**
     * Optional method to return the type of build being tested.
     * <p/>
     * A common implementation for Android platform builds is to return
     * (build product)-(build os)-(build variant).
     * ie generic-linux-userdebug
     *
     * @return the build flavor or <code>null</code> if unset/not applicable
     */
    public String getBuildFlavor();

    /**
     * @return the {@link ITestDevice} serial that this build was executed on. Returns <code>null
     * </code> if no device is associated with this build.
     */
    public String getDeviceSerial();

    /**
     * Set the build flavor.
     *
     * @param buildFlavor
     */
    public void setBuildFlavor(String buildFlavor);

    /**
     * Optional method to return the source control branch that the build being tested was
     * produced from.
     *
     * @return the build branch or <code>null</code> if unset/not applicable
     */
    public String getBuildBranch();

    /**
     * Set the build branch
     *
     * @param branch the branch name
     */
    public void setBuildBranch(String branch);

    /**
     * Set the {@link ITestDevice} serial associated with this build.
     *
     * @param serial the serial number of the {@link ITestDevice} that this build was executed with.
     */
    public void setDeviceSerial(String serial);

    /**
     * Get a set of name-value pairs of additional attributes describing the build.
     *
     * @return a {@link Map} of build attributes. Will not be <code>null</code>, but may be empty.
     */
    public Map<String, String> getBuildAttributes();

    /**
     * Add a build attribute
     *
     * @param attributeName the unique attribute name
     * @param attributeValue the attribute value
     */
    public void addBuildAttribute(String attributeName, String attributeValue);


    /**
     * Helper method to retrieve a file with given name.
     * @param name
     * @return the image file or <code>null</code> if not found
     */
    public File getFile(String name);

    /**
     * Returns all {@link VersionedFile}s stored in this {@link BuildInfo}.
     */
    public Collection<VersionedFile> getFiles();

    /**
     * Helper method to retrieve a file version with given name.
     * @param name
     * @return the image version or <code>null</code> if not found
     */
    public String getVersion(String name);

    /**
     * Stores an file with given name in this build info.
     *
     * @param name the unique name of the file
     * @param file the local {@link File}
     * @param version the file version
     */
    public void setFile(String name, File file, String version);

    /**
     * Clean up any temporary build files
     */
    public void cleanUp();

    /**
     * Clones the {@link IBuildInfo} object.
     */
    public IBuildInfo clone();
}

该接口中定义了一些方法都是跟属性相关的,其实现在BuildInfo中。


/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * 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.android.tradefed.build;

import com.android.tradefed.log.LogUtil.CLog;
import com.android.tradefed.util.FileUtil;
import com.android.tradefed.util.MultiMap;
import com.android.tradefed.util.UniqueMultiMap;
import com.google.common.base.Objects;

import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.Hashtable;
import java.util.Map;

/**
 * Generic implementation of a {@link IBuildInfo}.
 */
public class BuildInfo implements IBuildInfo {
    private String mBuildId = "0";
    private String mTestTag = "stub";
    private String mBuildTargetName = "stub";
    private final UniqueMultiMap<String, String> mBuildAttributes =
            new UniqueMultiMap<String, String>();
    private Map<String, VersionedFile> mVersionedFileMap;
    private String mBuildFlavor = null;
    private String mBuildBranch = null;
    private String mDeviceSerial = null;

    /**
     * Creates a {@link BuildInfo} using default attribute values.
     */
    public BuildInfo() {
        mVersionedFileMap = new Hashtable<String, VersionedFile>();
    }

    /**
     * Creates a {@link BuildInfo}
     *
     * @param buildId the build id
     * @param testTag the test tag name
     * @param buildTargetName the build target name
     */
    public BuildInfo(String buildId, String testTag, String buildTargetName) {
        mBuildId = buildId;
        mTestTag = testTag;
        mBuildTargetName = buildTargetName;
        mVersionedFileMap = new Hashtable<String, VersionedFile>();
    }

    /**
     * Creates a {@link BuildInfo}, populated with attributes given in another build.
     *
     * @param buildToCopy
     */
    BuildInfo(BuildInfo buildToCopy) {
        this(buildToCopy.getBuildId(), buildToCopy.getTestTag(), buildToCopy.getBuildTargetName());
        addAllBuildAttributes(buildToCopy);
        try {
            addAllFiles(buildToCopy);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String getBuildId() {
        return mBuildId;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String getTestTag() {
        return mTestTag;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String getDeviceSerial() {
        return mDeviceSerial;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Map<String, String> getBuildAttributes() {
        return mBuildAttributes.getUniqueMap();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String getBuildTargetName() {
        return mBuildTargetName;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void addBuildAttribute(String attributeName, String attributeValue) {
        mBuildAttributes.put(attributeName, attributeValue);
    }

    /**
     * Helper method to copy build attributes, branch, and flavor from other build.
     */
    protected void addAllBuildAttributes(BuildInfo build) {
        mBuildAttributes.putAll(build.getAttributesMultiMap());
        setBuildFlavor(build.getBuildFlavor());
        setBuildBranch(build.getBuildBranch());
    }

    protected MultiMap<String, String> getAttributesMultiMap() {
        return mBuildAttributes;
    }

    /**
     * Helper method to copy all files from the other build.
     * <p>
     * Creates new hardlinks to the files so that each build will have a unique file path to the
     * file.
     * </p>
     *
     * @throws IOException if an exception is thrown when creating the hardlinks.
     */
    protected void addAllFiles(BuildInfo build) throws IOException {
        for (Map.Entry<String, VersionedFile> fileEntry : build.getVersionedFileMap().entrySet()) {
            File origFile = fileEntry.getValue().getFile();
            File copyFile;
            if (origFile.isDirectory()) {
                copyFile = FileUtil.createTempDir(fileEntry.getKey());
                FileUtil.recursiveHardlink(origFile, copyFile);
            } else {
                // Only using createTempFile to create a unique dest filename
                copyFile = FileUtil.createTempFile(fileEntry.getKey(),
                        FileUtil.getExtension(origFile.getName()));
                copyFile.delete();
                FileUtil.hardlinkFile(origFile, copyFile);
            }
            setFile(fileEntry.getKey(), copyFile, fileEntry.getValue().getVersion());
        }
    }

    protected Map<String, VersionedFile> getVersionedFileMap() {
        return mVersionedFileMap;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public File getFile(String name) {
        VersionedFile fileRecord = mVersionedFileMap.get(name);
        if (fileRecord != null) {
            return fileRecord.getFile();
        }
        return null;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Collection<VersionedFile> getFiles() {
        return mVersionedFileMap.values();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String getVersion(String name) {
        VersionedFile fileRecord = mVersionedFileMap.get(name);
        if (fileRecord != null) {
            return fileRecord.getVersion();
        }
        return null;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void setFile(String name, File file, String version) {
        if (mVersionedFileMap.containsKey(name)) {
            CLog.e("Device build already contains a file for %s in thread %s", name,
                    Thread.currentThread().getName());
            return;
        }
        mVersionedFileMap.put(name, new VersionedFile(file, version));
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void cleanUp() {
        for (VersionedFile fileRecord : mVersionedFileMap.values()) {
            FileUtil.recursiveDelete(fileRecord.getFile());
        }
        mVersionedFileMap.clear();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public IBuildInfo clone() {
        BuildInfo copy = new BuildInfo(mBuildId, mTestTag, mBuildTargetName);
        copy.addAllBuildAttributes(this);
        try {
            copy.addAllFiles(this);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        copy.setBuildBranch(mBuildBranch);
        copy.setBuildFlavor(mBuildFlavor);

        return copy;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String getBuildFlavor() {
        return mBuildFlavor;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void setBuildFlavor(String buildFlavor) {
        mBuildFlavor = buildFlavor;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String getBuildBranch() {
        return mBuildBranch;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void setBuildBranch(String branch) {
        mBuildBranch = branch;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void setDeviceSerial(String serial) {
        mDeviceSerial = serial;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public int hashCode() {
        return Objects.hashCode(mBuildAttributes, mBuildBranch, mBuildFlavor, mBuildId,
                mBuildTargetName, mTestTag, mDeviceSerial);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        BuildInfo other = (BuildInfo) obj;
        return Objects.equal(mBuildAttributes, other.mBuildAttributes) &&
                Objects.equal(mBuildBranch, other.mBuildBranch) &&
                Objects.equal(mBuildFlavor, other.mBuildFlavor) &&
                Objects.equal(mBuildId, other.mBuildId) &&
                Objects.equal(mBuildTargetName, other.mBuildTargetName) &&
                Objects.equal(mTestTag, other.mTestTag) &&
                Objects.equal(mDeviceSerial, other.mDeviceSerial);
    }
}

提供的属性有build的id号,build的目标名称,测试标签,根目录,build的分支,测试类型。关机要理解build是什么意思,我还不是太了解build这个意义,暂时先用build来代替吧,等我了解了,再做解释。在原生的cts中,使用的是CtsBuildProvider,很简单的就是把cts的根目录属性设置上,然后是buildId,测试目标,build命令设置好就返回了。但是你如果要添加你自己的实现类,肯定不是简单的这么一点代码。比如你要做的测试时测试你的系统,那么这里面提供的东西就多了。首先你的系统存放的地址,分支号,要build的版本号等等都要在这里面获取并存到buildinfo对象中返回给TestInvocation中。


/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * 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.android.cts.tradefed.build;

import com.android.tradefed.build.FolderBuildInfo;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.build.IBuildProvider;
import com.android.tradefed.build.IFolderBuildInfo;
import com.android.tradefed.config.Option;

import java.io.File;

/**
 * A simple {@link IBuildProvider} that uses a pre-existing CTS install.
 */
public class CtsBuildProvider implements IBuildProvider {

    @Option(name="cts-install-path", description="the path to the cts installation to use")
    private String mCtsRootDirPath = System.getProperty("CTS_ROOT");

    public static final String CTS_BUILD_VERSION = "4.4_r1.95";

    /**
     * {@inheritDoc}
     */
    @Override
    public IBuildInfo getBuild() {
        if (mCtsRootDirPath == null) {
            throw new IllegalArgumentException("Missing --cts-install-path");
        }
        IFolderBuildInfo ctsBuild = new FolderBuildInfo(CTS_BUILD_VERSION, "cts", "cts");
        ctsBuild.setRootDir(new File(mCtsRootDirPath));
        return ctsBuild;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void buildNotTested(IBuildInfo info) {
        // ignore
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void cleanUp(IBuildInfo info) {
        // ignore
    }
}




Cts框架解析(8)-IBuildProvider