package net.hockeyapp.android;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Build;
import android.text.TextUtils;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.powermock.reflect.Whitebox;
import java.lang.ref.WeakReference;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
import static org.mockito.Matchers.any;
import static org.powermock.api.mockito.PowerMockito.mock;
import static org.powermock.api.mockito.PowerMockito.mockStatic;
import static org.powermock.api.mockito.PowerMockito.when;
@RunWith(PowerMockRunner.class)
@PrepareForTest({Build.VERSION.class, TextUtils.class})
public class UpdateManagerTest {
private Context mockContext;
private PackageManager mockPackageManager;
private WeakReference<Context> contextWeakReference;
@Before
public void setUp() throws NoSuchFieldException, IllegalAccessException {
// Reset Build version code
Whitebox.setInternalState(Build.VERSION.class, "SDK_INT", Build.VERSION_CODES.BASE);
mockContext = mock(Context.class);
mockPackageManager = mock(PackageManager.class);
mockStatic(TextUtils.class);
PowerMockito.when(TextUtils.isEmpty(any(CharSequence.class))).thenAnswer(new Answer<Boolean>() {
@Override
public Boolean answer(InvocationOnMock invocation) throws Throwable {
CharSequence a = (CharSequence) invocation.getArguments()[0];
return !(a != null && a.length() > 0);
}
});
PowerMockito.when(TextUtils.equals(any(CharSequence.class), any(CharSequence.class))).thenAnswer(new Answer<Boolean>() {
@Override
public Boolean answer(InvocationOnMock invocation) throws Throwable {
CharSequence a = (CharSequence) invocation.getArguments()[0];
CharSequence b = (CharSequence) invocation.getArguments()[1];
return a.equals(b);
}
});
when(mockContext.getPackageManager()).thenReturn(mockPackageManager);
contextWeakReference = new WeakReference<>(mockContext);
}
@Test
public void testInstalledViaADBDefault() {
when(mockPackageManager.getInstallerPackageName(any(String.class))).thenReturn(null);
// Typically, the installer string for ADB is null
assertFalse(UpdateManager.installedFromMarket(contextWeakReference));
// or an empty string
when(mockPackageManager.getInstallerPackageName(any(String.class))).thenReturn("");
assertFalse(UpdateManager.installedFromMarket(contextWeakReference));
// Verify this also works on Android Nougat
Whitebox.setInternalState(Build.VERSION.class, "SDK_INT", Build.VERSION_CODES.N);
assertFalse(UpdateManager.installedFromMarket(contextWeakReference));
}
@Test
public void testInstalledViaGooglePlay() {
// Set typical identifier for Google Play and check
when(mockPackageManager.getInstallerPackageName(any(String.class))).thenReturn("com.google.play");
assertTrue(UpdateManager.installedFromMarket(contextWeakReference));
Whitebox.setInternalState(Build.VERSION.class, "SDK_INT", Build.VERSION_CODES.N);
assertTrue(UpdateManager.installedFromMarket(contextWeakReference));
}
@Test
public void testInstalledViaADBXiaomi() {
// On some devices, e.g. Xiaomi devices, launching via USB will return "adb" for the installer
when(mockPackageManager.getInstallerPackageName(any(String.class))).thenReturn("adb");
assertFalse(UpdateManager.installedFromMarket(contextWeakReference));
Whitebox.setInternalState(Build.VERSION.class, "SDK_INT", Build.VERSION_CODES.N);
assertFalse(UpdateManager.installedFromMarket(contextWeakReference));
}
@Test
public void testInstalledViaPackageManagerNougat() {
// On Android Nougat, installing packages using HockeyApp (using the package manager) will list the following installer identifier
when(mockPackageManager.getInstallerPackageName(any(String.class))).thenReturn("com.google.android.packageinstaller");
// When not on Android Nougat this is considered "store"
assertTrue(UpdateManager.installedFromMarket(contextWeakReference));
// Test desired behavior on Android Nougat
Whitebox.setInternalState(Build.VERSION.class, "SDK_INT", Build.VERSION_CODES.N);
assertFalse(UpdateManager.installedFromMarket(contextWeakReference));
}
@Test
public void testInstalledViaPackageManagerNougat2() {
// On Android Nougat, installing packages using HockeyApp (using the package manager) will list the following installer identifier
when(mockPackageManager.getInstallerPackageName(any(String.class))).thenReturn("com.android.packageinstaller");
// When not on Android Nougat this is considered "store"
assertTrue(UpdateManager.installedFromMarket(contextWeakReference));
// Test desired behavior on Android Nougat
Whitebox.setInternalState(Build.VERSION.class, "SDK_INT", Build.VERSION_CODES.N);
assertFalse(UpdateManager.installedFromMarket(contextWeakReference));
}
}