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