@@ -68,15 +68,18 @@ public class DefaultCredentialProviderTest extends TestCase {
6868 + "==\n -----END PRIVATE KEY-----\n " ;
6969 private static final String ACCESS_TOKEN = "1/MkSJoj1xsli0AccessToken_NKPY2" ;
7070
71+ private static final String GAE_SIGNAL_CLASS = "com.google.appengine.api.utils.SystemProperty" ;
72+
7173 private static final Lock lock = new ReentrantLock ();
7274
7375 private static File tempDirectory = null ;
7476
75- public void testDefaultCredentialAppEngine () throws IOException {
77+ public void testDefaultCredentialAppEngineDeployed () throws IOException {
7678 HttpTransport transport = new MockHttpTransport ();
7779 TestDefaultCredentialProvider testProvider = new TestDefaultCredentialProvider ();
7880 testProvider .addType (DefaultCredentialProvider .APP_ENGINE_CREDENTIAL_CLASS ,
7981 MockAppEngineCredential .class );
82+ testProvider .addType (GAE_SIGNAL_CLASS , MockAppEngineSystemProperty .class );
8083
8184 Credential defaultCredential = testProvider .getDefaultCredential (transport , JSON_FACTORY );
8285
@@ -86,7 +89,38 @@ public void testDefaultCredentialAppEngine() throws IOException {
8689 assertSame (JSON_FACTORY , defaultCredential .getJsonFactory ());
8790 }
8891
89- public void testDefaultCredentialAppEngineSingleAttempt () {
92+ public void testDefaultCredentialAppEngineComponentOffAppEngineGivesNotFoundError () {
93+ HttpTransport transport = new MockHttpTransport ();
94+ TestDefaultCredentialProvider testProvider = new TestDefaultCredentialProvider ();
95+ testProvider .addType (DefaultCredentialProvider .APP_ENGINE_CREDENTIAL_CLASS ,
96+ MockAppEngineCredential .class );
97+ testProvider .addType (GAE_SIGNAL_CLASS , MockOffAppEngineSystemProperty .class );
98+
99+ try {
100+ testProvider .getDefaultCredential (transport , JSON_FACTORY );
101+ fail ("No credential expected when not on App Engine." );
102+ } catch (IOException e ) {
103+ String message = e .getMessage ();
104+ assertTrue (message .contains (DefaultCredentialProvider .HELP_PERMALINK ));
105+ }
106+ }
107+
108+ public void testDefaultCredentialAppEngineWithoutDependencyThrowsHelpfulLoadError () {
109+ HttpTransport transport = new MockHttpTransport ();
110+ TestDefaultCredentialProvider testProvider = new TestDefaultCredentialProvider ();
111+ testProvider .addType (GAE_SIGNAL_CLASS , MockAppEngineSystemProperty .class );
112+
113+ try {
114+ testProvider .getDefaultCredential (transport , JSON_FACTORY );
115+ fail ("Credential expected to fail to load if credential class not present." );
116+ } catch (IOException e ) {
117+ String message = e .getMessage ();
118+ assertFalse (message .contains (DefaultCredentialProvider .HELP_PERMALINK ));
119+ assertTrue (message .contains (DefaultCredentialProvider .APP_ENGINE_CREDENTIAL_CLASS ));
120+ }
121+ }
122+
123+ public void testDefaultCredentialAppEngineSingleClassLoadAttempt () {
90124 HttpTransport transport = new MockHttpTransport ();
91125 TestDefaultCredentialProvider testProvider = new TestDefaultCredentialProvider ();
92126 try {
@@ -109,6 +143,7 @@ public void testDefaultCredentialCaches() throws IOException {
109143 TestDefaultCredentialProvider testProvider = new TestDefaultCredentialProvider ();
110144 testProvider .addType (DefaultCredentialProvider .APP_ENGINE_CREDENTIAL_CLASS ,
111145 MockAppEngineCredential .class );
146+ testProvider .addType (GAE_SIGNAL_CLASS , MockAppEngineSystemProperty .class );
112147
113148 Credential firstCall = testProvider .getDefaultCredential (transport , JSON_FACTORY );
114149
@@ -448,6 +483,46 @@ public MockAppEngineCredential(HttpTransport transport, JsonFactory jsonFactory)
448483 }
449484 }
450485
486+ /*
487+ * App Engine is detected by calling SystemProperty.environment.value() via Reflection.
488+ * The following mock types simulate the shape and behavior of that call sequence.
489+ */
490+
491+ private static class MockAppEngineSystemProperty {
492+
493+ @ SuppressWarnings ("unused" )
494+ public static final MockEnvironment environment =
495+ new MockEnvironment (MockEnvironmentEnum .Production );
496+ }
497+
498+ private static class MockOffAppEngineSystemProperty {
499+
500+ @ SuppressWarnings ("unused" )
501+ public static final MockEnvironment environment = new MockEnvironment (null );
502+ }
503+
504+ private enum MockEnvironmentEnum {
505+ Production ,
506+ Development ;
507+ }
508+
509+ public static class MockEnvironment {
510+
511+ private MockEnvironmentEnum innerValue ;
512+
513+ MockEnvironment (MockEnvironmentEnum value ) {
514+ this .innerValue = value ;
515+ }
516+
517+ public MockEnvironmentEnum value () {
518+ return innerValue ;
519+ }
520+ }
521+
522+ /*
523+ * End of types simulating SystemProperty.environment.value()
524+ */
525+
451526 private static class MockRequestCountingTransport extends MockHttpTransport {
452527 int requestCount = 0 ;
453528
0 commit comments