Merge "Handle checking sim provider if dual sim"
diff --git a/src/com/android/tradefed/suite/checker/DeviceStorageStatusChecker.java b/src/com/android/tradefed/suite/checker/DeviceStorageStatusChecker.java
new file mode 100644
index 0000000..3d037ca
--- /dev/null
+++ b/src/com/android/tradefed/suite/checker/DeviceStorageStatusChecker.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2020 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.suite.checker;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import com.android.tradefed.config.Option;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.log.LogUtil.CLog;
+import com.android.tradefed.suite.checker.StatusCheckerResult.CheckStatus;
+
+/**
+ * Check if device has enough disk space for the given partitions.
+ */
+public class DeviceStorageStatusChecker implements ISystemStatusChecker {
+    @Option(
+        name = "minimal-storage-bytes",
+        description = "Number of bytes that should be left free on the device."
+    )
+    private long mMinimalStorage = 50L * 1024 * 1024; // 50MB
+
+    @Option(
+        name = "partition",
+        description = "Partition needed to be checked on the device."
+    )
+    private Set<String> mPartitions = new HashSet<>();
+
+    /** {@inheritDoc} */
+    @Override
+    public StatusCheckerResult preExecutionCheck(ITestDevice device)
+            throws DeviceNotAvailableException {
+        List<String> noEnoughStorage = new ArrayList<>();
+        for (String partition : mPartitions) {
+            long freeSpace = device.getPartitionFreeSpace(partition) * 1024;
+            String message = String.format(
+                    "%s bytes left on the partition %s", freeSpace, partition);
+            CLog.i(message);
+            if (freeSpace < mMinimalStorage) {
+                noEnoughStorage.add(message);
+            }
+        }
+        if (noEnoughStorage.isEmpty()) {
+            return new StatusCheckerResult(CheckStatus.SUCCESS);
+        } else {
+            StatusCheckerResult result = new StatusCheckerResult(CheckStatus.FAILED);
+            String errorMessage =
+                    String.format(
+                            "No enough storage left on the device in pre-execution: %s\n",
+                            String.join(",", noEnoughStorage));
+            CLog.e(errorMessage);
+            result.setErrorMessage(errorMessage);
+            return result;
+        }
+    }
+}
diff --git a/tests/src/com/android/tradefed/UnitTests.java b/tests/src/com/android/tradefed/UnitTests.java
index 304afa8..a709517 100644
--- a/tests/src/com/android/tradefed/UnitTests.java
+++ b/tests/src/com/android/tradefed/UnitTests.java
@@ -202,6 +202,7 @@
 import com.android.tradefed.sandbox.TradefedSandboxTest;
 import com.android.tradefed.suite.checker.ActivityStatusCheckerTest;
 import com.android.tradefed.suite.checker.DeviceSettingCheckerTest;
+import com.android.tradefed.suite.checker.DeviceStorageStatusCheckerTest;
 import com.android.tradefed.suite.checker.EnforcedSeLinuxCheckerTest;
 import com.android.tradefed.suite.checker.KeyguardStatusCheckerTest;
 import com.android.tradefed.suite.checker.LeakedThreadStatusCheckerTest;
@@ -702,6 +703,7 @@
     // suite/checker
     ActivityStatusCheckerTest.class,
     DeviceSettingCheckerTest.class,
+    DeviceStorageStatusCheckerTest.class,
     EnforcedSeLinuxCheckerTest.class,
     KeyguardStatusCheckerTest.class,
     LeakedThreadStatusCheckerTest.class,
diff --git a/tests/src/com/android/tradefed/suite/checker/DeviceStorageStatusCheckerTest.java b/tests/src/com/android/tradefed/suite/checker/DeviceStorageStatusCheckerTest.java
new file mode 100644
index 0000000..e094071
--- /dev/null
+++ b/tests/src/com/android/tradefed/suite/checker/DeviceStorageStatusCheckerTest.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2020 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.suite.checker;
+
+import static org.junit.Assert.*;
+
+import com.android.tradefed.config.OptionSetter;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.suite.checker.StatusCheckerResult.CheckStatus;
+
+import org.easymock.EasyMock;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Unit tests for {@link DeviceStorageStatusChecker} */
+@RunWith(JUnit4.class)
+public class DeviceStorageStatusCheckerTest {
+
+    private DeviceStorageStatusChecker mChecker;
+    private ITestDevice mMockDevice;
+    private OptionSetter mOptionSetter;
+
+    @Before
+    public void setup() throws Exception {
+        mMockDevice = EasyMock.createMock(ITestDevice.class);
+        mChecker = new DeviceStorageStatusChecker();
+        mOptionSetter = new OptionSetter(mChecker);
+        mOptionSetter.setOptionValue("partition", "/data");
+        mOptionSetter.setOptionValue("partition", "/data2");
+    }
+
+    /** Test that device checker passes if device has enough storage. */
+    @Test
+    public void testEnoughDeviceStorage() throws Exception {
+        EasyMock.expect(mMockDevice.getPartitionFreeSpace(EasyMock.eq("/data")))
+                .andReturn(54L * 1024); // 54MB
+        EasyMock.expect(mMockDevice.getPartitionFreeSpace(EasyMock.eq("/data2")))
+                .andReturn(54L * 1024); // 54MB
+        EasyMock.replay(mMockDevice);
+        assertEquals(CheckStatus.SUCCESS, mChecker.preExecutionCheck(mMockDevice).getStatus());
+        EasyMock.verify(mMockDevice);
+    }
+
+    /** Test that device checker fails if device has not enough storage on 1 partition. */
+    @Test
+    public void testInEnoughDeviceStorageOn1Partition() throws Exception {
+        EasyMock.expect(mMockDevice.getPartitionFreeSpace(EasyMock.eq("/data")))
+            .andReturn(48L * 1024); // 48MB
+        EasyMock.expect(mMockDevice.getPartitionFreeSpace(EasyMock.eq("/data2")))
+            .andReturn(54L * 1024); // 54MB
+        EasyMock.replay(mMockDevice);
+        assertEquals(CheckStatus.FAILED, mChecker.preExecutionCheck(mMockDevice).getStatus());
+        EasyMock.verify(mMockDevice);
+    }
+
+    /** Test that device checker fails if device has not enough given storage. */
+    @Test
+    public void testNotEnoughDeviceStorageWithGivenStorageParameter() throws Exception {
+        mOptionSetter.setOptionValue("minimal-storage-bytes", "104857600"); // 100MB
+        EasyMock.expect(mMockDevice.getPartitionFreeSpace(EasyMock.eq("/data")))
+                .andReturn(54L * 1024); // 54MB
+        EasyMock.expect(mMockDevice.getPartitionFreeSpace(EasyMock.eq("/data2")))
+                .andReturn(54L * 1024); // 54MB
+        EasyMock.replay(mMockDevice);
+        assertEquals(CheckStatus.FAILED, mChecker.preExecutionCheck(mMockDevice).getStatus());
+        EasyMock.verify(mMockDevice);
+    }
+
+    /** Test that device checker passes if device has enough given storage. */
+    @Test
+    public void testEnoughDeviceStorageWithGivenStorageParameter() throws Exception {
+        mOptionSetter.setOptionValue("minimal-storage-bytes", "104857600"); // 100MB
+        EasyMock.expect(mMockDevice.getPartitionFreeSpace(EasyMock.eq("/data")))
+                .andReturn(101L * 1024); // 101MB
+        EasyMock.expect(mMockDevice.getPartitionFreeSpace(EasyMock.eq("/data2")))
+                .andReturn(101L * 1024); // 101MB
+        EasyMock.replay(mMockDevice);
+        assertEquals(CheckStatus.SUCCESS, mChecker.preExecutionCheck(mMockDevice).getStatus());
+        EasyMock.verify(mMockDevice);
+    }
+}