1 /*
2  * Copyright (C) 2012 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 android.filesystem.cts;
18 
19 import static androidx.test.InstrumentationRegistry.getContext;
20 import static androidx.test.InstrumentationRegistry.getInstrumentation;
21 
22 import android.util.Log;
23 
24 import androidx.test.runner.AndroidJUnit4;
25 
26 import com.android.compatibility.common.util.DeviceReportLog;
27 import com.android.compatibility.common.util.SystemUtil;
28 
29 import org.junit.After;
30 import org.junit.Before;
31 import org.junit.Test;
32 import org.junit.runner.RunWith;
33 
34 import java.util.concurrent.atomic.AtomicBoolean;
35 import java.util.concurrent.atomic.AtomicInteger;
36 
37 @RunWith(AndroidJUnit4.class)
38 public class AlmostFullTest {
39     private static final String DIR_INITIAL_FILL = "INITIAL_FILL";
40     private static final String DIR_SEQ_UPDATE = "SEQ_UPDATE";
41     private static final String DIR_RANDOM_WR = "RANDOM_WR";
42     private static final String DIR_RANDOM_RD = "RANDOM_RD";
43     private static final String TAG = "AlmostFullTest";
44     private static final String REPORT_LOG_NAME = "CtsFileSystemTestCases";
45 
46     private static final long FREE_SPACE_FINAL = 1000L * 1024 * 1024L;
47 
48     // test runner creates multiple instances at the begging.
49     // use that to fill disk only once.
50     // set as final to initialize it only once
51     private static final AtomicInteger mRefCounter = new AtomicInteger(0);
52     private static final AtomicBoolean mDiskFilled = new AtomicBoolean(false);
53 
AlmostFullTest()54     public AlmostFullTest() {
55         int currentCounter = mRefCounter.incrementAndGet();
56         Log.i(TAG, "++currentCounter: " + currentCounter);
57     }
58 
59     @Before
setUp()60     public void setUp() throws Exception {
61         CarTestUtil.getInstance().setUp();
62         if (mDiskFilled.compareAndSet(false, true)) {
63             Log.i(TAG, "Filling disk");
64             // initial fill done in two stage as disk can be filled by other
65             // components
66             long freeDisk = SystemUtil.getFreeDiskSize(getContext());
67             long diskToFill = freeDisk - FREE_SPACE_FINAL;
68             if (diskToFill >= 0) {
69                 Log.i(TAG, "free disk " + freeDisk + ", to fill " + diskToFill);
70             } else {
71                 Log.i(TAG, "free disk " + freeDisk + " too small, needs " + FREE_SPACE_FINAL);
72                 return;
73             }
74             // Ensure MAX_SIZE_TO_FILL is an integral multiple of FileUtil.BUFFER_SIZE to avoid
75             // rounding errors caused by FileUtil.createNewFilledFile. See b/63535343.
76             final long MAX_FILE_SIZE_TO_FILL = FileUtil.BUFFER_SIZE * 100L;
77             long filled = 0;
78             while (filled < diskToFill) {
79                 long toFill = diskToFill - filled;
80                 if (toFill > MAX_FILE_SIZE_TO_FILL) {
81                     toFill = MAX_FILE_SIZE_TO_FILL;
82                 }
83                 Log.i(TAG, "Generating file " + toFill);
84                 FileUtil.createNewFilledFile(getContext(),
85                         DIR_INITIAL_FILL, toFill);
86                 filled += toFill;
87             }
88         }
89         Log.i(TAG, "free disk " + SystemUtil.getFreeDiskSize(getContext()));
90     }
91 
92     @After
tearDown()93     public void tearDown() throws Exception {
94         CarTestUtil.getInstance().tearDown();
95         Log.i(TAG, "tearDown free disk " + SystemUtil.getFreeDiskSize(getContext()));
96         int currentCounter = mRefCounter.decrementAndGet();
97         Log.i(TAG, "--currentCounter: " + currentCounter);
98         if (currentCounter == 0) {
99             FileUtil.removeFileOrDir(getContext(), DIR_INITIAL_FILL);
100         }
101         FileUtil.removeFileOrDir(getContext(), DIR_SEQ_UPDATE);
102         FileUtil.removeFileOrDir(getContext(), DIR_RANDOM_WR);
103         FileUtil.removeFileOrDir(getContext(), DIR_RANDOM_RD);
104         Log.i(TAG, "tearDown free disk " + SystemUtil.getFreeDiskSize(getContext()));
105     }
106 
107     @Test
testSequentialUpdate()108     public void testSequentialUpdate() throws Exception {
109         // now about freeSpaceToLeave should be left
110         // and try updating exceeding the free space size
111         final long FILE_SIZE = 400L * 1024L * 1024L;
112         long freeDisk = SystemUtil.getFreeDiskSize(getContext());
113         Log.i(TAG, "Now free space is " + freeDisk);
114         if (freeDisk < FILE_SIZE) {
115             Log.w(TAG, "too little space: " + freeDisk);
116             return;
117         }
118         final int BUFFER_SIZE = 10 * 1024 * 1024;
119         final int NUMBER_REPETITION = 10;
120         String streamName = "test_sequential_update";
121         FileUtil.doSequentialUpdateTest(getContext(), DIR_SEQ_UPDATE, FILE_SIZE, BUFFER_SIZE,
122                 NUMBER_REPETITION, REPORT_LOG_NAME, streamName);
123     }
124 
125     // TODO: file size too small and caching will give wrong better result.
126     // needs to flush cache by reading big files per each read.
127     @Test
testRandomRead()128     public void testRandomRead() throws Exception {
129         final int BUFFER_SIZE = 4 * 1024;
130         final long fileSize = 400L * 1024L * 1024L;
131         long freeDisk = SystemUtil.getFreeDiskSize(getContext());
132         if (freeDisk < fileSize) {
133             Log.w(TAG, "too little space: " + freeDisk);
134             return;
135         }
136         String streamName = "test_random_read";
137         DeviceReportLog report = new DeviceReportLog(REPORT_LOG_NAME, streamName);
138         FileUtil.doRandomReadTest(getContext(), DIR_RANDOM_RD, report, fileSize, BUFFER_SIZE);
139         report.submit(getInstrumentation());
140     }
141 
142     @Test
testRandomUpdate()143     public void testRandomUpdate() throws Exception {
144         final int BUFFER_SIZE = 4 * 1024;
145         final long fileSize = 256L * 1024L * 1024L;
146         long freeDisk = SystemUtil.getFreeDiskSize(getContext());
147         if (freeDisk < fileSize) {
148             Log.w(TAG, "too little space: " + freeDisk);
149             return;
150         }
151         String streamName = "test_random_update";
152         DeviceReportLog report = new DeviceReportLog(REPORT_LOG_NAME, streamName);
153         FileUtil.doRandomWriteTest(getContext(), DIR_RANDOM_WR, report, fileSize, BUFFER_SIZE);
154         report.submit(getInstrumentation());
155     }
156 }
157