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