1 /*
2  * Copyright (C) 2019 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.tradefed.contentprovider;
17 
18 import static org.junit.Assert.assertEquals;
19 import static org.junit.Assert.assertFalse;
20 import static org.junit.Assert.assertTrue;
21 
22 import com.android.tradefed.device.contentprovider.ContentProviderHandler;
23 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
24 import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
25 import com.android.tradefed.util.FileUtil;
26 
27 import org.junit.After;
28 import org.junit.Before;
29 import org.junit.Test;
30 import org.junit.runner.RunWith;
31 
32 import java.io.File;
33 import java.util.ArrayList;
34 import java.util.List;
35 
36 /** Host tests for the Tradefed Content Provider. */
37 @RunWith(DeviceJUnit4ClassRunner.class)
38 public class ContentProviderTest extends BaseHostJUnit4Test {
39     private static final String EXTERNAL_STORAGE_PATH = "/storage/emulated/%d/";
40 
41     private ContentProviderHandler mHandler;
42     private String mCurrentUserStoragePath;
43     private List<String> mToBeDeleted = new ArrayList<>();
44 
45     @Before
setUp()46     public void setUp() throws Exception {
47         mHandler = new ContentProviderHandler(getDevice());
48         mCurrentUserStoragePath =
49                 String.format(EXTERNAL_STORAGE_PATH, getDevice().getCurrentUser());
50         assertTrue(mHandler.setUp());
51     }
52 
53     @After
tearDown()54     public void tearDown() throws Exception {
55         for (String delete : mToBeDeleted) {
56             getDevice().deleteFile(delete);
57         }
58         mToBeDeleted.clear();
59         if (mHandler != null) {
60             mHandler.tearDown();
61         }
62     }
63 
64     /** Test pushing a file with special characters in the name. */
65     @Test
testPushFile_encode()66     public void testPushFile_encode() throws Exception {
67         // Name with space and parenthesis
68         File tmpFile = FileUtil.createTempFile("tmpFileToPush (test)", ".txt");
69         try {
70             boolean res = mHandler.pushFile(tmpFile, "/sdcard/" + tmpFile.getName());
71             assertTrue(res);
72             assertTrue(getDevice().doesFileExist(mCurrentUserStoragePath + tmpFile.getName()));
73         } finally {
74             FileUtil.deleteFile(tmpFile);
75         }
76     }
77 
78     /**
79      * '+' character is special in URLs as it can be decoded incorrectly as a space. Ensure it works
80      * and our encoding/decoding handles it well.
81      */
82     @Test
testPushFile_encode_plus()83     public void testPushFile_encode_plus() throws Exception {
84         // Name with '+'
85         File tmpFile = FileUtil.createTempFile("tmpFileToPush+(test)", ".txt");
86         try {
87             boolean res = mHandler.pushFile(tmpFile, "/sdcard/" + tmpFile.getName());
88             assertTrue(res);
89             assertTrue(getDevice().doesFileExist(mCurrentUserStoragePath + tmpFile.getName()));
90         } finally {
91             FileUtil.deleteFile(tmpFile);
92         }
93     }
94 
95     @Test
testPushFile()96     public void testPushFile() throws Exception {
97         File tmpFile = FileUtil.createTempFile("tmpFileToPush", ".txt");
98         try {
99             String devicePath = "/sdcard/" + tmpFile.getName();
100             mToBeDeleted.add(devicePath);
101             boolean res = mHandler.pushFile(tmpFile, devicePath);
102             assertTrue(res);
103             assertTrue(getDevice().doesFileExist(mCurrentUserStoragePath + tmpFile.getName()));
104         } finally {
105             FileUtil.deleteFile(tmpFile);
106         }
107     }
108 
109     /** Test that we can delete a file via Content Provider. */
110     @Test
testDeleteFile()111     public void testDeleteFile() throws Exception {
112         File tmpFile = FileUtil.createTempFile("tmpFileToPush", ".txt");
113         try {
114             String devicePath = "/sdcard/" + tmpFile.getName();
115             // Push the file first
116             boolean res = mHandler.pushFile(tmpFile, devicePath);
117             assertTrue(res);
118             assertTrue(getDevice().doesFileExist(mCurrentUserStoragePath + tmpFile.getName()));
119             // Attempt to delete it.
120             assertTrue(mHandler.deleteFile(devicePath));
121         } finally {
122             FileUtil.deleteFile(tmpFile);
123         }
124     }
125 
126     @Test
testPullFile()127     public void testPullFile() throws Exception {
128         String fileContent = "some test content";
129 
130         // First, push the file onto a device.
131         File tmpFile = FileUtil.createTempFile("tmpFileToPush", ".txt");
132         FileUtil.writeToFile(fileContent, tmpFile);
133         mHandler.pushFile(tmpFile, "/sdcard/" + tmpFile.getName());
134         mToBeDeleted.add("/sdcard/" + tmpFile.getName());
135 
136         File tmpPullFile = FileUtil.createTempFile("fileToPullTo", ".txt");
137         // Delete the placeholder, it should be recreated when pulling.
138         FileUtil.deleteFile(tmpPullFile);
139         // Local file does not exist before we pull the content from the device.
140         assertFalse(tmpPullFile.exists());
141 
142         try {
143             boolean res = mHandler.pullFile("/sdcard/" + tmpFile.getName(), tmpPullFile);
144             assertTrue(res);
145             assertTrue(tmpPullFile.exists()); // Verify existence.
146             assertEquals(FileUtil.readStringFromFile(tmpPullFile), fileContent); // Verify content.
147         } finally {
148             FileUtil.deleteFile(tmpFile);
149             FileUtil.deleteFile(tmpPullFile);
150         }
151     }
152 
153     @Test
testPullDir()154     public void testPullDir() throws Exception {
155         String fileContent = "some test content";
156         String dirName = "test_dir_path";
157         String subDirName = "test_subdir_path";
158         String subDirPath = dirName + "/" + subDirName;
159 
160         // First, push the file onto a device to create nested structure= dirName->subDirName->file
161         File tmpFile = FileUtil.createTempFile("tmpFileToPush", ".txt");
162         FileUtil.writeToFile(fileContent, tmpFile);
163         mHandler.pushFile(tmpFile, "/sdcard/" + subDirPath + "/" + tmpFile.getName());
164         mToBeDeleted.add("/sdcard/" + dirName);
165 
166         File tmpPullDir = FileUtil.createTempDir("dirToPullTo");
167 
168         try {
169             boolean res = mHandler.pullDir("/sdcard/" + dirName, tmpPullDir);
170             assertTrue(res);
171             assertEquals(tmpPullDir.listFiles()[0].getName(), subDirName); // Verify subDir
172             assertEquals(tmpPullDir.listFiles()[0].listFiles().length, 1); // Verify subDir content.
173             assertEquals(
174                     FileUtil.readStringFromFile(tmpPullDir.listFiles()[0].listFiles()[0]),
175                     fileContent); // Verify content.
176         } finally {
177             FileUtil.recursiveDelete(tmpPullDir);
178             FileUtil.deleteFile(tmpFile);
179         }
180     }
181 }
182