Home | History | Annotate | Download | only in sdklib
      1 /*
      2  * Copyright (C) 2011 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.sdklib;
     18 
     19 
     20 import com.android.prefs.AndroidLocation;
     21 import com.android.prefs.AndroidLocation.AndroidLocationException;
     22 import com.android.sdklib.ISdkLog;
     23 import com.android.sdklib.SdkConstants;
     24 import com.android.sdklib.SdkManager;
     25 import com.android.sdklib.internal.avd.AvdManager;
     26 import com.android.sdklib.io.FileOp;
     27 import com.android.sdklib.mock.MockLog;
     28 import com.android.sdklib.repository.PkgProps;
     29 
     30 import java.io.File;
     31 import java.io.FileWriter;
     32 import java.io.IOException;
     33 
     34 import junit.framework.TestCase;
     35 
     36 /**
     37  * Test case that allocates a temporary SDK, a temporary AVD base folder
     38  * with an SdkManager and an AvdManager that points to them.
     39  */
     40 public class SdkManagerTestCase extends TestCase {
     41 
     42     private File mFakeSdk;
     43     private MockLog mLog;
     44     private SdkManager mSdkManager;
     45     private TmpAvdManager mAvdManager;
     46 
     47     /** Returns the {@link MockLog} for this test case. */
     48     public MockLog getLog() {
     49         return mLog;
     50     }
     51 
     52     /** Returns the {@link SdkManager} for this test case. */
     53     public SdkManager getSdkManager() {
     54         return mSdkManager;
     55     }
     56 
     57     /** Returns the {@link AvdManager} for this test case. */
     58     public TmpAvdManager getAvdManager() {
     59         return mAvdManager;
     60     }
     61 
     62     /**
     63      * Sets up a {@link MockLog}, a fake SDK in a temporary directory
     64      * and an AVD Manager pointing to an initially-empty AVD directory.
     65      */
     66     @Override
     67     public void setUp() throws Exception {
     68         mLog = new MockLog();
     69         mFakeSdk = makeFakeSdk();
     70         mSdkManager = SdkManager.createManager(mFakeSdk.getAbsolutePath(), mLog);
     71         assertNotNull("SdkManager location was invalid", mSdkManager);
     72 
     73         mAvdManager = new TmpAvdManager(mSdkManager, mLog);
     74     }
     75 
     76     /**
     77      * Removes the temporary SDK and AVD directories.
     78      */
     79     @Override
     80     public void tearDown() throws Exception {
     81         deleteDir(mFakeSdk);
     82     }
     83 
     84     /**
     85      * A empty test method to placate the JUnit test runner, which doesn't
     86      * like TestCase classes with no test methods.
     87      */
     88     public void testPlaceholder() {
     89     }
     90 
     91     /**
     92      * An {@link AvdManager} that uses a temporary directory
     93      * located <em>inside</em> the SDK directory for testing.
     94      * The AVD list should be initially empty.
     95      */
     96     protected static class TmpAvdManager extends AvdManager {
     97 
     98         /*
     99          * Implementation detail:
    100          * - When the super.AvdManager constructor is invoked, it will invoke
    101          *   the buildAvdFilesList() to fill the initial AVD list, which will in
    102          *   turn call getBaseAvdFolder().
    103          * - That's why mTmpAvdRoot is initialized in getAvdRoot() rather than
    104          *   in the constructor, since we can't initialize fields before the super()
    105          *   call.
    106          */
    107 
    108         /**
    109          * AVD Root, initialized "lazily" when the AVD root is first requested.
    110          */
    111         private File mTmpAvdRoot;
    112 
    113         public TmpAvdManager(SdkManager sdkManager, ISdkLog log) throws AndroidLocationException {
    114             super(sdkManager, log);
    115         }
    116 
    117         @Override
    118         public String getBaseAvdFolder() throws AndroidLocationException {
    119             if (mTmpAvdRoot == null) {
    120                 mTmpAvdRoot = new File(getSdkManager().getLocation(), "tmp_avds");
    121                 mTmpAvdRoot.mkdirs();
    122             }
    123             return mTmpAvdRoot.getAbsolutePath();
    124         }
    125     }
    126 
    127     /**
    128      * Build enough of a skeleton SDK to make the tests pass.
    129      * <p/>
    130      * Ideally this wouldn't touch the file system but the current
    131      * structure of the SdkManager and AvdManager makes this difficult.
    132      *
    133      * @return Path to the temporary SDK root
    134      * @throws IOException
    135      */
    136     private File makeFakeSdk() throws IOException {
    137         // First we create a temp file to "reserve" the temp directory name we want to use.
    138         File sdkDir = File.createTempFile(
    139                 this.getClass().getSimpleName() + '_' + this.getName(), null);
    140         // Then erase the file and make the directory
    141         sdkDir.delete();
    142         sdkDir.mkdirs();
    143 
    144         AndroidLocation.resetFolder();
    145         System.setProperty("user.home", sdkDir.getAbsolutePath());
    146         File addonsDir = new File(sdkDir, SdkConstants.FD_ADDONS);
    147         addonsDir.mkdir();
    148         File toolsLibEmuDir = new File(sdkDir, SdkConstants.OS_SDK_TOOLS_LIB_FOLDER + "emulator");
    149         toolsLibEmuDir.mkdirs();
    150         new File(toolsLibEmuDir, "snapshots.img").createNewFile();
    151         File platformsDir = new File(sdkDir, SdkConstants.FD_PLATFORMS);
    152 
    153         // Creating a fake target here on down
    154         File targetDir = makeFakeTargetInternal(platformsDir);
    155 
    156         File imagesDir = new File(targetDir, "images");
    157         makeFakeSysImgInternal(imagesDir, SdkConstants.ABI_ARMEABI);
    158 
    159         makeFakeSkinInternal(targetDir);
    160         makeFakeSourceInternal(sdkDir);
    161         return sdkDir;
    162     }
    163 
    164     /**
    165      * Creates the system image folder and places a fake userdata.img in it.
    166      *
    167      * @param systemImage A system image with a valid location.
    168      * @throws IOException if the file fails to be created.
    169      */
    170     protected void makeSystemImageFolder(ISystemImage systemImage) throws IOException {
    171         File imagesDir = systemImage.getLocation();
    172         imagesDir.mkdirs();
    173 
    174         makeFakeSysImgInternal(imagesDir, systemImage.getAbiType());
    175     }
    176 
    177     //----
    178 
    179     /** Utility used by {@link #makeFakeSdk()} to create a fake target with API 0, rev 0. */
    180     private File makeFakeTargetInternal(File platformsDir) throws IOException {
    181         File targetDir = new File(platformsDir, "v0_0");
    182         targetDir.mkdirs();
    183         new File(targetDir, SdkConstants.FN_FRAMEWORK_LIBRARY).createNewFile();
    184         new File(targetDir, SdkConstants.FN_FRAMEWORK_AIDL).createNewFile();
    185 
    186         File sourceProp = new File(targetDir, SdkConstants.FN_SOURCE_PROP);
    187         sourceProp.createNewFile();
    188         FileWriter out = new FileWriter(sourceProp);
    189         out.write(PkgProps.LAYOUTLIB_API + "=5\n");
    190         out.write(PkgProps.LAYOUTLIB_REV + "=2\n");
    191         out.close();
    192 
    193         File buildProp = new File(targetDir, SdkConstants.FN_BUILD_PROP);
    194         out = new FileWriter(buildProp);
    195         out.write(SdkManager.PROP_VERSION_RELEASE + "=0.0\n");
    196         out.write(SdkManager.PROP_VERSION_SDK + "=0\n");
    197         out.write(SdkManager.PROP_VERSION_CODENAME + "=REL\n");
    198         out.close();
    199         return targetDir;
    200     }
    201 
    202     /** Utility to create a fake sys image in the given folder. */
    203     private void makeFakeSysImgInternal(File imagesDir, String abiType) throws IOException {
    204         imagesDir.mkdirs();
    205         new File(imagesDir, "userdata.img").createNewFile();
    206 
    207         File sourceProp = new File(imagesDir, SdkConstants.FN_SOURCE_PROP);
    208         sourceProp.createNewFile();
    209         FileWriter out = new FileWriter(sourceProp);
    210         out.write(PkgProps.VERSION_API_LEVEL + "=0\n");
    211         out.write(PkgProps.SYS_IMG_ABI + "=" + abiType + "\n");
    212         out.close();
    213     }
    214 
    215     /** Utility to make a fake skin for the given target */
    216     private void makeFakeSkinInternal(File targetDir) {
    217         FileOp.append(targetDir, "skins", "HVGA").mkdirs();
    218     }
    219 
    220     /** Utility to create a fake source with a few files in the given sdk folder. */
    221     private void makeFakeSourceInternal(File sdkDir) throws IOException {
    222         File sourcesDir = FileOp.append(sdkDir, SdkConstants.FD_PKG_SOURCES, "android-0");
    223         sourcesDir.mkdirs();
    224 
    225         File sourceProp = new File(sourcesDir, SdkConstants.FN_SOURCE_PROP);
    226         sourceProp.createNewFile();
    227         FileWriter out = new FileWriter(sourceProp);
    228         out.write(PkgProps.VERSION_API_LEVEL + "=0\n");
    229         out.close();
    230 
    231         File dir1 = FileOp.append(sourcesDir, "src", "com", "android");
    232         dir1.mkdirs();
    233         FileOp.append(dir1, "File1.java").createNewFile();
    234         FileOp.append(dir1, "File2.java").createNewFile();
    235 
    236         FileOp.append(sourcesDir, "res", "values").mkdirs();
    237         FileOp.append(sourcesDir, "res", "values", "styles.xml").createNewFile();
    238     }
    239 
    240     /**
    241      * Recursive delete directory. Mostly for fake SDKs.
    242      *
    243      * @param root directory to delete
    244      */
    245     private void deleteDir(File root) {
    246         if (root.exists()) {
    247             for (File file : root.listFiles()) {
    248                 if (file.isDirectory()) {
    249                     deleteDir(file);
    250                 } else {
    251                     file.delete();
    252                 }
    253             }
    254             root.delete();
    255         }
    256     }
    257 
    258 }
    259