1 package org.robolectric.versioning; 2 3 import static com.google.common.truth.Truth.assertThat; 4 import static org.junit.Assert.assertThrows; 5 6 import java.lang.reflect.Field; 7 import java.util.Arrays; 8 import java.util.Collections; 9 import org.junit.Test; 10 import org.junit.runner.RunWith; 11 import org.junit.runners.JUnit4; 12 import org.robolectric.versioning.AndroidVersions.AndroidRelease; 13 import org.robolectric.versioning.AndroidVersions.SdkInformation; 14 15 /** Test more esoteric versions mismatches in sdkInt numbers, and codenames. */ 16 @RunWith(JUnit4.class) 17 public final class AndroidVersionsEdgeCaseTest { 18 forceWarningMode(boolean warnMode)19 private void forceWarningMode(boolean warnMode) { 20 try { 21 Field field = AndroidVersions.class.getDeclaredField("warnOnly"); 22 field.setAccessible(true); 23 field.set(null, warnMode); 24 } catch (NoSuchFieldException | IllegalAccessException ex) { 25 throw new RuntimeException("Could not update warnOnly field", ex); 26 } 27 } 28 29 /** 30 * sdkInt higher than any known release, claims it's released. Expects an error message to update 31 * to update the AndroidVersions.class 32 */ 33 @Test sdkIntHigherThanKnownReleasesClaimsIsReleased_throwsException()34 public void sdkIntHigherThanKnownReleasesClaimsIsReleased_throwsException() { 35 AndroidRelease earliestUnrelease = null; 36 try { 37 forceWarningMode(false); 38 SdkInformation information = AndroidVersions.gatherStaticSdkInformationFromThisClass(); 39 earliestUnrelease = information.earliestUnreleased; 40 information.computeCurrentSdk( 41 earliestUnrelease.getSdkInt(), 42 earliestUnrelease.getVersion(), 43 "REL", 44 Collections.emptyList()); 45 assertThat(this).isNull(); 46 } catch (RuntimeException e) { 47 assertThat(e) 48 .hasMessageThat() 49 .contains( 50 "The current sdk " 51 + earliestUnrelease.getShortCode() 52 + " has been released. Please update the contents of " 53 + AndroidVersions.class.getName() 54 + " to mark sdk " 55 + earliestUnrelease.getShortCode() 56 + " as released."); 57 assertThat(e).isInstanceOf(RuntimeException.class); 58 } 59 } 60 61 /** 62 * sdkInt lower than known release, claims it's released. Expects an error message to update the 63 * jar. 64 */ 65 @Test sdkIntReleasedButStillReportsCodeName_throwsException()66 public void sdkIntReleasedButStillReportsCodeName_throwsException() { 67 AndroidRelease latestRelease = null; 68 try { 69 forceWarningMode(false); 70 SdkInformation information = AndroidVersions.gatherStaticSdkInformationFromThisClass(); 71 latestRelease = 72 information.sdkIntToAllReleases.get(information.latestRelease.getSdkInt() - 1); 73 information.computeCurrentSdk( 74 latestRelease.getSdkInt(), 75 null, 76 latestRelease.getShortCode(), 77 Collections.singletonList(latestRelease.getShortCode())); 78 assertThat(this).isNull(); 79 } catch (RuntimeException e) { 80 assertThat(e) 81 .hasMessageThat() 82 .contains( 83 "The current sdk " 84 + latestRelease.getShortCode() 85 + " has been been marked as released. Please update the contents of current sdk" 86 + " jar to the released version."); 87 assertThat(e).isInstanceOf(RuntimeException.class); 88 } 89 } 90 91 @Test sdkIntReleasedButStillReportsCodeName_warningMode()92 public void sdkIntReleasedButStillReportsCodeName_warningMode() { 93 AndroidRelease latestRelease; 94 try { 95 forceWarningMode(true); 96 SdkInformation information = AndroidVersions.gatherStaticSdkInformationFromThisClass(); 97 latestRelease = 98 information.sdkIntToAllReleases.get(information.latestRelease.getSdkInt() - 1); 99 information.computeCurrentSdk( 100 latestRelease.getSdkInt(), 101 null, 102 information.latestRelease.getShortCode(), 103 Collections.singletonList(latestRelease.getShortCode())); 104 } catch (Throwable t) { 105 assertThat(t).isNull(); 106 } 107 } 108 109 /** 110 * sdkInt lower than known release, claims it's released. Expects an error message to update the 111 * jar if release is older than the latest release, otherwise warn only. 112 */ 113 @Test lastReleasedIntReleasedButStillReportsCodeName_noException()114 public void lastReleasedIntReleasedButStillReportsCodeName_noException() { 115 forceWarningMode(false); 116 SdkInformation information = AndroidVersions.gatherStaticSdkInformationFromThisClass(); 117 AndroidRelease latestRelease = 118 information.sdkIntToAllReleases.get(information.latestRelease.getSdkInt()); 119 information.computeCurrentSdk( 120 latestRelease.getSdkInt(), 121 null, 122 information.latestRelease.getShortCode(), 123 Collections.singletonList(latestRelease.getShortCode())); 124 assertThat(this).isNotNull(); 125 } 126 127 @Test unknownSdkInt_warningMode()128 public void unknownSdkInt_warningMode() { 129 try { 130 forceWarningMode(true); 131 SdkInformation information = AndroidVersions.gatherStaticSdkInformationFromThisClass(); 132 AndroidRelease found = 133 information.computeCurrentSdk( 134 35, "zzzz", "Z", Arrays.asList("wwww", "xxxx", "yyyy", "zzzz")); 135 assertThat(found.getSdkInt()).isEqualTo(10000); 136 } catch (Throwable t) { 137 assertThat(t).isNull(); 138 } 139 } 140 141 @Test compareToNull_throwsNullPointerException()142 public void compareToNull_throwsNullPointerException() { 143 //noinspection DataFlowIssue Passing null to ensure that the right exception is thrown 144 assertThrows(NullPointerException.class, () -> new AndroidVersions.T().compareTo(null)); 145 } 146 } 147