Author: fmantek
Date: Fri Mar 23 06:47:53 2007
New Revision: 117

Added:
   trunk/clients/cs/src/core/authexceptions.cs
   trunk/clients/cs/src/unittests/authtest.cs
Modified:
   trunk/clients/cs/RELEASE_NOTES.txt
   trunk/clients/cs/src/VS2003/gdata/gdata.csproj
   trunk/clients/cs/src/VS2005.mobile/GDataMobile/GDataMobile.csproj
   trunk/clients/cs/src/core/gauthrequest.cs
   trunk/clients/cs/src/core/utilities.cs
   trunk/clients/cs/src/unittests/caltest.cs

Log:
- added Captcha Handling and more detailed exceptions when the authentication 
  request fails. See authexceptions.cs for the list of potential exceptions 
thrown


Modified: trunk/clients/cs/RELEASE_NOTES.txt
==============================================================================
--- trunk/clients/cs/RELEASE_NOTES.txt  (original)
+++ trunk/clients/cs/RELEASE_NOTES.txt  Fri Mar 23 06:47:53 2007
@@ -8,6 +8,9 @@
 - fixed an issue with the edit/self uris on the entry. They were not correctly 
setable.
 - fixed an issue that one you used an authenticated service, but did not 
supply credentials, we would send
   an empty authentication header.
+- added Captcha Handling and more detailed exceptions when the authentication 
+  request fails. See authexceptions.cs for the list of potential exceptions 
thrown
+- added some preliminary unittests for the new exceptions
 
 == 1.0.9.4 ==
 - Google Base: fix for incorrect Price attribute behaviour

Modified: trunk/clients/cs/src/VS2003/gdata/gdata.csproj
==============================================================================
--- trunk/clients/cs/src/VS2003/gdata/gdata.csproj      (original)
+++ trunk/clients/cs/src/VS2003/gdata/gdata.csproj      Fri Mar 23 06:47:53 2007
@@ -197,6 +197,12 @@
                     SubType = "Code"
                     BuildAction = "Compile"
                 />
+                 <File
+                    RelPath = "authexceptions.cs"
+                    Link = "..\..\core\authexceptions.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
                 <File
                     RelPath = "authsubutil.cs"
                     Link = "..\..\core\authsubutil.cs"

Modified: trunk/clients/cs/src/VS2005.mobile/GDataMobile/GDataMobile.csproj
==============================================================================
--- trunk/clients/cs/src/VS2005.mobile/GDataMobile/GDataMobile.csproj   
(original)
+++ trunk/clients/cs/src/VS2005.mobile/GDataMobile/GDataMobile.csproj   Fri Mar 
23 06:47:53 2007
@@ -126,7 +126,10 @@
     <Compile Include="..\..\core\feedquery.cs">
       <Link>feedquery.cs</Link>
     </Compile>
-    <Compile Include="..\..\core\gauthrequest.cs">
+    <Compile Include="..\..\core\gauthexceptions.cs">
+      <Link>gauthexceptions.cs</Link>
+    </Compile>
+     <Compile Include="..\..\core\gauthrequest.cs">
       <Link>gauthrequest.cs</Link>
     </Compile>
     <Compile Include="..\..\core\gdatabatch.cs">

Added: trunk/clients/cs/src/core/authexceptions.cs
==============================================================================
--- (empty file)
+++ trunk/clients/cs/src/core/authexceptions.cs Fri Mar 23 06:47:53 2007
@@ -0,0 +1,180 @@
+/* Copyright (c) 2006 Google Inc.
+ *
+ * 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.
+*/
+#region Using directives
+
+#define USE_TRACING
+#define USE_LOGGING
+
+using System;
+using System.Xml; 
+using System.Net;
+using System.Diagnostics;
+#if WindowsCE || PocketPC
+#else 
+using System.Runtime.Serialization;
+#endif
+using System.Security.Permissions;
+using System.IO;
+using System.Text; 
+
+
+
+#endregion
+
+
+//////////////////////////////////////////////////////////////////////
+// <summary>custom exceptions</summary> 
+//////////////////////////////////////////////////////////////////////
+namespace Google.GData.Client
+{
+
+    //////////////////////////////////////////////////////////////////////
+    /// <summary>standard exception class to be used when authentication 
+    /// using Google Client Login fails
+    /// </summary> 
+    //////////////////////////////////////////////////////////////////////
+#if WindowsCE || PocketPC
+#else 
+    [Serializable]
+#endif
+    public class AuthenticationException : LoggedException
+    {
+        //////////////////////////////////////////////////////////////////////
+        /// <summary>default constructor so that FxCop does not 
complain</summary> 
+        //////////////////////////////////////////////////////////////////////
+        public AuthenticationException() {}
+
+        /// <summary>
+        /// base constructor, takes a message text
+        /// </summary> 
+        /// <param name="msg"></param>
+        public AuthenticationException(String msg) :  base(msg) {} 
+     }
+
+    /// <summary>thrown when the credentials are wrong</summary> 
+    public class InvalidCredentialsException : AuthenticationException
+    {
+        //////////////////////////////////////////////////////////////////////
+        /// <summary>default constructor so that FxCop does not 
complain</summary> 
+        //////////////////////////////////////////////////////////////////////
+        public InvalidCredentialsException() {}
+        public InvalidCredentialsException(String msg) :  base(msg) {} 
+    }
+
+    //////////////////////////////////////////////////////////////////////
+    /// <summary>thrown when the account was deleted
+    /// </summary> 
+    //////////////////////////////////////////////////////////////////////
+     public class AccountDeletedException : AuthenticationException
+     {
+            
//////////////////////////////////////////////////////////////////////
+            /// <summary>default constructor so that FxCop does not 
complain</summary> 
+            
//////////////////////////////////////////////////////////////////////
+            public AccountDeletedException() {}
+            public AccountDeletedException(String msg) :  base(msg) {} 
+     }
+
+     //////////////////////////////////////////////////////////////////////
+     /// <summary>thrown when the account was disabled
+     /// </summary> 
+     //////////////////////////////////////////////////////////////////////
+      public class AccountDisabledException : AuthenticationException
+      {
+             
//////////////////////////////////////////////////////////////////////
+             /// <summary>default constructor so that FxCop does not 
complain</summary> 
+             
//////////////////////////////////////////////////////////////////////
+             public AccountDisabledException() {}
+             public AccountDisabledException(String msg) :  base(msg) {} 
+      }
+
+      //////////////////////////////////////////////////////////////////////
+      /// <summary>the account hoder was not verified
+      /// </summary> 
+      //////////////////////////////////////////////////////////////////////
+       public class NotVerifiedException : AuthenticationException
+       {
+              
//////////////////////////////////////////////////////////////////////
+              /// <summary>default constructor so that FxCop does not 
complain</summary> 
+              
//////////////////////////////////////////////////////////////////////
+              public NotVerifiedException() {}
+              public NotVerifiedException(String msg) :  base(msg) {} 
+       }
+
+       //////////////////////////////////////////////////////////////////////
+       /// <summary>The Terms were not agreed with..
+       /// </summary> 
+       //////////////////////////////////////////////////////////////////////
+        public class TermsNotAgreedException : AuthenticationException
+        {
+               
//////////////////////////////////////////////////////////////////////
+               /// <summary>default constructor so that FxCop does not 
complain</summary> 
+               
//////////////////////////////////////////////////////////////////////
+               public TermsNotAgreedException() {}
+               public TermsNotAgreedException(String msg) :  base(msg) {} 
+        }
+
+        //////////////////////////////////////////////////////////////////////
+        /// <summary>The service is current not available
+        /// </summary> 
+        //////////////////////////////////////////////////////////////////////
+         public class ServiceUnavailableException : AuthenticationException
+         {
+                
//////////////////////////////////////////////////////////////////////
+                /// <summary>default constructor so that FxCop does not 
complain</summary> 
+                
//////////////////////////////////////////////////////////////////////
+                public ServiceUnavailableException() {}
+                public ServiceUnavailableException(String msg) :  base(msg) {} 
+         }
+
+         //////////////////////////////////////////////////////////////////////
+         /// <summary>many unsuccessfull logins might create this...
+         /// </summary> 
+         //////////////////////////////////////////////////////////////////////
+          public class CaptchaRequiredException : AuthenticationException
+          {
+                protected string captchaUrl;
+                protected string captchaToken;
+
+             
//////////////////////////////////////////////////////////////////////
+             /// <summary>default constructor so that FxCop does not 
complain</summary> 
+             
//////////////////////////////////////////////////////////////////////
+             public CaptchaRequiredException() {}
+             public CaptchaRequiredException(String msg, String url, String 
token) :  base(msg)
+             {
+                 this.captchaUrl = url;
+                 this.captchaToken = token;
+             }
+
+
+              
//////////////////////////////////////////////////////////////////////
+              /// <summary>Read only accessor for captchaUrl</summary> 
+              
//////////////////////////////////////////////////////////////////////
+              public string Url
+              {
+                  get {return this.captchaUrl;}
+              }
+              // end of accessor for captchaUrl
+    
+              
//////////////////////////////////////////////////////////////////////
+               /// <summary>Read only accessor for captchaToken</summary> 
+              
//////////////////////////////////////////////////////////////////////
+              public string Token
+              {
+                  get {return this.captchaToken;}
+              }
+              // end of accessor for captchaToken
+        }
+
+} ///end of file 
//////////////////////////////////////////////////////////////////////////

Modified: trunk/clients/cs/src/core/gauthrequest.cs
==============================================================================
--- trunk/clients/cs/src/core/gauthrequest.cs   (original)
+++ trunk/clients/cs/src/core/gauthrequest.cs   Fri Mar 23 06:47:53 2007
@@ -37,6 +37,13 @@
     //////////////////////////////////////////////////////////////////////
     public class GoogleAuthentication
     {
+        ///  <summary>account prefix path </summary>
+        public const string AccountPrefix = "/accounts";
+
+        ///  <summary>protocol  </summary>
+        public const string DefaultProtocol = "https";
+        public const string DefaultDomain = "www.google.com";
+
         /// <summary>Google client authentication handler</summary>
         public const string UriHandler = 
"https://www.google.com/accounts/ClientLogin";; 
         /// <summary>Google client authentication email</summary>
@@ -65,6 +72,10 @@
         public const string AccountType = "accountType=";
         /// <summary>default value for the account type</summary>
         public const string AccountTypeDefault = "HOSTED_OR_GOOGLE";
+        /// <summary>captcha url token</summary>
+        public const string CaptchaAnswer = "logincaptcha=";
+        /// <summary>default value for the account type</summary>
+        public const string CaptchaToken = "logintoken=";
     }
     
/////////////////////////////////////////////////////////////////////////////
 
@@ -84,6 +95,8 @@
         private int numberOfRetries;        // holds the number of retries the 
request will undertake
         private bool fStrictRedirect;       // indicates if redirects should 
be handled strictly
         private string accountType;         // indicates the accountType to use
+        private string captchaAnswer;       // indicates the captcha Answer in 
a challenge
+        private string captchaToken;        // indicates the captchaToken in a 
challenge
 
         
                                          
@@ -202,8 +215,27 @@
         }
 
 
+        //////////////////////////////////////////////////////////////////////
+        /// <summary>property to hold the Answer for a challenge</summary> 
+        /// <returns> </returns>
+        //////////////////////////////////////////////////////////////////////
+        public string CaptchaAnswer
+        {
+            get {return this.captchaAnswer;}
+            set {this.captchaAnswer = value;}
+        }
+        // end of accessor public string CaptchaUrl
 
-
+        //////////////////////////////////////////////////////////////////////
+        /// <summary>property to hold the token for a challenge</summary> 
+        /// <returns> </returns>
+        //////////////////////////////////////////////////////////////////////
+        public string CaptchaToken
+        {
+            get {return this.captchaToken;}
+            set {this.captchaToken = value;}
+        }
+        // end of accessor public string CaptchaToken
 
 
         //////////////////////////////////////////////////////////////////////
@@ -415,6 +447,14 @@
                 postData += GoogleAuthentication.Password + "=" + 
Utilities.UriEncodeReserved(nc.Password) + "&";  
                 postData += GoogleAuthentication.Source + "=" + 
Utilities.UriEncodeReserved(this.factory.ApplicationName) + "&"; 
                 postData += GoogleAuthentication.Service + "=" + 
Utilities.UriEncodeReserved(this.factory.Service) + "&"; 
+                if (this.factory.CaptchaAnswer != null)
+                {
+                    postData += GoogleAuthentication.CaptchaAnswer + "=" + 
Utilities.UriEncodeReserved(this.factory.CaptchaAnswer) + "&"; 
+                }
+                if (this.factory.CaptchaToken != null)
+                {
+                    postData += GoogleAuthentication.CaptchaToken + "=" + 
Utilities.UriEncodeReserved(this.factory.CaptchaToken) + "&"; 
+                }
                 postData += accountType; 
 
                 byte[] encodedData = encoder.GetBytes(postData);
@@ -428,18 +468,13 @@
             } 
             catch (WebException e)
             {
-                Tracing.TraceMsg("QueryAuthtoken failed " + e.Status); 
-                throw new GDataRequestException("Execution of authentication 
request failed", e);
+                Tracing.TraceMsg("QueryAuthtoken failed " + e.Status + " " + 
e.Message); 
+                authResponse = e.Response;
             }
             HttpWebResponse response = authResponse as HttpWebResponse;
             if (response != null)
             {
-                int code= (int)response.StatusCode;
-                if (code != 200)
-                {
-                    throw new GDataRequestException("Execution of 
authentication request returned unexpected result: " +code,  this.Response); 
-                }
-                // check the content type, it must be text
+                 // check the content type, it must be text
                 if (!response.ContentType.StartsWith(HttpFormPost.ContentType))
                 {
                     throw new GDataRequestException("Execution of 
authentication request returned unexpected content type: " + 
response.ContentType,  this.Response); 
@@ -449,8 +484,20 @@
                 {
                     throw new GDataRequestException("Execution of 
authentication request returned unexpected large content length: " + 
response.ContentLength,  this.Response); 
                 }
+                TokenCollection tokens = 
Utilities.ParseStreamInTokenCollection(response.GetResponseStream());
+                authToken = Utilities.FindToken(tokens, 
GoogleAuthentication.AuthToken); 
+                
+                if (authToken == null)
+                {
+                    throw getAuthException(tokens);
+                }
+                // failsafe. if getAuthException did not catch an error...
+                int code= (int)response.StatusCode;
+                if (code != 200)
+                {
+                    throw new GDataRequestException("Execution of 
authentication request returned unexpected result: " +code,  this.Response); 
+                }
 
-                authToken = 
Utilities.ParseValueFormStream(response.GetResponseStream(), 
GoogleAuthentication.AuthToken); 
             }
             Tracing.Assert(authToken != null, "did not find an auth token in 
QueryAuthToken");
             if (authResponse != null)
@@ -460,7 +507,62 @@
             return authToken;
         }
         
/////////////////////////////////////////////////////////////////////////////
+    
+        /// <summary>
+        ///  Returns the respective GDataAuthenticationException given the 
return
+        /// values from the login URI handler.
+        /// </summary>
+        /// <param name="tokens">The tokencollection of the parsed return 
form</param>
+        /// <returns>AuthenticationException</returns>
+        private AuthenticationException getAuthException(TokenCollection 
tokens) 
+        {
+        
+            String errorName = Utilities.FindToken(tokens, "Error");
+
+            if ("BadAuthentication".Equals(errorName))
+            {
+                return new InvalidCredentialsException("Invalid credentials");
+            }
+            else if ("AccountDeleted".Equals(errorName))
+            {
+                return new AccountDeletedException("Account deleted");
+            }
+            else if ("AccountDisabled".Equals(errorName))
+            {
+                return new AccountDisabledException("Account disabled");
+            }
+            else if ("NotVerified".Equals(errorName))
+            {
+                return new NotVerifiedException("Not verified");
+            }
+            else if ("TermsNotAgreed".Equals(errorName))
+            {
+                return new TermsNotAgreedException("Terms not agreed");
+            }
+            else if ("ServiceUnavailable".Equals(errorName))
+            {
+                return new ServiceUnavailableException("Service unavailable");
+            }
+            else if ("CaptchaRequired".Equals(errorName))
+            {
+                String captchaPath = Utilities.FindToken(tokens, "CaptchaUrl");
+                String captchaToken = Utilities.FindToken(tokens, 
"CaptchaToken");
+
+                StringBuilder captchaUrl = new StringBuilder();
+                
captchaUrl.Append(GoogleAuthentication.DefaultProtocol).Append("://");
+                captchaUrl.Append(GoogleAuthentication.DefaultDomain);
+                captchaUrl.Append(GoogleAuthentication.AccountPrefix);
+                captchaUrl.Append('/').Append(captchaPath);
+                return new CaptchaRequiredException("Captcha required",
+                                                    captchaUrl.ToString(),
+                                                    captchaToken);
 
+            }
+            else
+            {
+                return new AuthenticationException("Error authenticating 
(check service name)");
+            }
+        }
 
         //////////////////////////////////////////////////////////////////////
         /// <summary>Executes the request and prepares the response stream. 
Also 

Modified: trunk/clients/cs/src/core/utilities.cs
==============================================================================
--- trunk/clients/cs/src/core/utilities.cs      (original)
+++ trunk/clients/cs/src/core/utilities.cs      Fri Mar 23 06:47:53 2007
@@ -371,22 +371,17 @@
         
/////////////////////////////////////////////////////////////////////////////
 
         //////////////////////////////////////////////////////////////////////
-        /// <summary>parses a form response stream in token form for a 
specific value
+        /// <summary>searches tokenCollection for a specific NEXT value. 
+        ///  The collection is assume to be a key/value pair list, so if 
<A,B,C,D> is the list
+        ///   A and C are keys, B and  D are values
         /// </summary> 
-        /// <param name="inputStream">the stream to read and parse</param>
+        /// <param name="tokens">the TokenCollection to search</param>
         /// <param name="key">the key to search for</param>
-        /// <returns> the string in the tokenized stream </returns>
+        /// <returns> the value string</returns>
         //////////////////////////////////////////////////////////////////////
-        static public string ParseValueFormStream(Stream inputStream,  string 
key)
+        static public string FindToken(TokenCollection tokens,  string key)
         {
             string returnValue = null; 
-             // get the body and parse it
-            ASCIIEncoding encoder = new ASCIIEncoding();
-            StreamReader readStream = new StreamReader(inputStream, encoder);
-            String body = readStream.ReadToEnd(); 
-            readStream.Close(); 
-            // all we are interested is the token, so we break the string in 
parts
-            TokenCollection tokens = new TokenCollection(body, new char[2] 
{'=', '\n'}); 
             bool fNextOne=false; 
 
             foreach (string token in tokens )
@@ -406,6 +401,45 @@
             return returnValue; 
         }
         
/////////////////////////////////////////////////////////////////////////////
+
+
+        //////////////////////////////////////////////////////////////////////
+        /// <summary>converts a form response stream to a TokenCollection,
+        ///  by parsing the contents of the stream for newlines and equal signs
+        ///  the input stream is assumed to be an ascii encoded form resonse
+        /// </summary> 
+        /// <param name="inputStream">the stream to read and parse</param>
+        /// <returns> the resulting TokenCollection </returns>
+        //////////////////////////////////////////////////////////////////////
+        static public TokenCollection ParseStreamInTokenCollection(Stream 
inputStream)
+        {
+             // get the body and parse it
+            ASCIIEncoding encoder = new ASCIIEncoding();
+            StreamReader readStream = new StreamReader(inputStream, encoder);
+            String body = readStream.ReadToEnd(); 
+            readStream.Close(); 
+            Tracing.TraceMsg("got the following body back: " + body);
+            // all we are interested is the token, so we break the string in 
parts
+            TokenCollection tokens = new TokenCollection(body, new char[2] 
{'=', '\n'}); 
+            return tokens;
+         }
+        
/////////////////////////////////////////////////////////////////////////////
+
+          
//////////////////////////////////////////////////////////////////////
+        /// <summary>parses a form response stream in token form for a 
specific value
+        /// </summary> 
+        /// <param name="inputStream">the stream to read and parse</param>
+        /// <param name="key">the key to search for</param>
+        /// <returns> the string in the tokenized stream </returns>
+        //////////////////////////////////////////////////////////////////////
+        static public string ParseValueFormStream(Stream inputStream,  string 
key)
+        {
+            TokenCollection tokens = ParseStreamInTokenCollection(inputStream);
+            return FindToken(tokens, key);
+         }
+        
/////////////////////////////////////////////////////////////////////////////
+
+
 
         //////////////////////////////////////////////////////////////////////
         /// <summary>returns a blank emptyDate. That's the default for an 
empty string date</summary> 

Added: trunk/clients/cs/src/unittests/authtest.cs
==============================================================================
--- (empty file)
+++ trunk/clients/cs/src/unittests/authtest.cs  Fri Mar 23 06:47:53 2007
@@ -0,0 +1,235 @@
+/* Copyright (c) 2006 Google Inc.
+ *
+ * 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.
+*/
+#define USE_TRACING
+#define DEBUG
+
+using System;
+using System.IO;
+using System.Xml; 
+using System.Collections;
+using System.Configuration;
+using System.Net; 
+using NUnit.Framework;
+using Google.GData.Client;
+using Google.GData.Extensions;
+using Google.GData.Calendar;
+using Google.GData.Client.UnitTests;
+
+
+
+
+namespace Google.GData.Client.AuthUnitTests
+{
+    [TestFixture] 
+    [Category("GoogleAuthenticationTests")]
+    public class AuthenticationTestSuite : BaseTestClass
+    {
+
+        /// <summary>holds the username to use</summary>
+        protected string userName;
+        /// <summary>holds the password to use</summary>
+        protected string passWord;
+
+        /// <summary>holds the default authhandler</summary> 
+        protected string strAuthHandler; 
+        /// <summary>holds the default UIR to test against</summary> 
+        protected string  defaultUri;
+    
+        //////////////////////////////////////////////////////////////////////
+        /// <summary>default empty constructor</summary> 
+        //////////////////////////////////////////////////////////////////////
+        public AuthenticationTestSuite()
+        {
+        }
+
+        //////////////////////////////////////////////////////////////////////
+        /// <summary>the setup method</summary> 
+        //////////////////////////////////////////////////////////////////////
+        [SetUp] public override void InitTest()
+        {
+            base.InitTest(); 
+            GDataGAuthRequestFactory authFactory = this.factory as 
GDataGAuthRequestFactory; 
+            if (authFactory != null)
+            {
+                authFactory.Handler = this.strAuthHandler; 
+            }
+        }
+        
/////////////////////////////////////////////////////////////////////////////
+
+        ////////////////////////////////////////////////////////////////////
+        /// <summary>the end it all method</summary> 
+        //////////////////////////////////////////////////////////////////////
+        [TearDown] public override void EndTest()
+        {
+            Tracing.ExitTracing();
+        }
+        
/////////////////////////////////////////////////////////////////////////////
+
+
+
+        //////////////////////////////////////////////////////////////////////
+        /// <summary>private void ReadConfigFile()</summary> 
+        /// <returns> </returns>
+        //////////////////////////////////////////////////////////////////////
+        protected override void ReadConfigFile()
+        {
+            base.ReadConfigFile(); 
+
+            IDictionary unitTestDictionary = (IDictionary) 
ConfigurationSettings.GetConfig("unitTestSection");
+
+            if (unitTestDictionary != null)
+            {
+                if (unitTestDictionary["authHandler"] != null)
+                {
+                    this.strAuthHandler = (string) 
unitTestDictionary["authHandler"];
+                    Tracing.TraceInfo("Read authHandler value: " + 
this.strAuthHandler); 
+                }
+                 if (unitTestDictionary["userName"] != null)
+                {
+                    this.userName = (string) unitTestDictionary["userName"];
+                    Tracing.TraceInfo("Read userName value: " + 
this.userName); 
+                }
+                if (unitTestDictionary["passWord"] != null)
+                {
+                    this.passWord = (string) unitTestDictionary["passWord"];
+                    Tracing.TraceInfo("Read passWord value: " + 
this.passWord); 
+                }
+
+                if (unitTestDictionary["calendarURI"] != null)
+                {
+                    this.defaultUri = (string) 
unitTestDictionary["calendarURI"];
+                    Tracing.TraceInfo("Read default URI value: " + 
this.defaultUri); 
+                }
+
+            }
+        }
+        
/////////////////////////////////////////////////////////////////////////////
+
+
+
+        //////////////////////////////////////////////////////////////////////
+        /// <summary>runs an authentication test</summary> 
+        //////////////////////////////////////////////////////////////////////
+        [Test] public void PositiveTest()
+        {
+            Tracing.TraceMsg("Entering PositiveTest");
+
+            FeedQuery query = new FeedQuery();
+            Service service = new Service();
+
+             if (this.defaultUri != null)
+            {
+                if (this.userName != null)
+                {
+                    NetworkCredential nc = new 
NetworkCredential(this.userName, this.passWord); 
+                    service.Credentials = nc;
+                }
+
+                GDataLoggingRequestFactory factory = 
(GDataLoggingRequestFactory) this.factory;
+                factory.MethodOverride = true;
+                service.RequestFactory = this.factory; 
+
+                query.Uri = new Uri(this.defaultUri);
+                service.Query(query);
+                service.Credentials = null;
+                factory.MethodOverride = false;
+            }
+        }
+        
////////////////////////////////////////////////////////////////////////////
+
+         //////////////////////////////////////////////////////////////////////
+        /// <summary>correct account, invalid password</summary> 
+        //////////////////////////////////////////////////////////////////////
+        [Test] public void InvalidCredentialsTest()
+        {
+            Tracing.TraceMsg("Entering InvalidCredentialsTest");
+
+            FeedQuery query = new FeedQuery();
+            Service service = new Service();
+
+            int iCount; 
+
+            if (this.defaultUri != null)
+            {
+                if (this.userName != null)
+                {
+                    NetworkCredential nc = new 
NetworkCredential(this.userName, "wrong"); 
+                    service.Credentials = nc;
+                }
+
+                GDataLoggingRequestFactory factory = 
(GDataLoggingRequestFactory) this.factory;
+                factory.MethodOverride = true;
+                service.RequestFactory = this.factory; 
+
+                query.Uri = new Uri(this.defaultUri);
+                try
+                {
+                    service.Query(query);
+                }  
+                catch (InvalidCredentialsException e)
+                {
+                    Tracing.TraceMsg("Got the correct Exception");
+                }
+                 service.Credentials = null;
+                factory.MethodOverride = false;
+            }
+        }
+        
////////////////////////////////////////////////////////////////////////////
+
+         //////////////////////////////////////////////////////////////////////
+        /// <summary>incorrect account</summary> 
+        //////////////////////////////////////////////////////////////////////
+        [Test] public void InvalidAccountTest()
+        {
+            Tracing.TraceMsg("Entering InvalidAccountTest");
+
+            FeedQuery query = new FeedQuery();
+            Service service = new Service();
+
+            int iCount; 
+
+            if (this.defaultUri != null)
+            {
+                if (this.userName != null)
+                {
+                    NetworkCredential nc = new 
NetworkCredential(this.userName+"xyz",  "wrong"); 
+                    service.Credentials = nc;
+                }
+
+                GDataLoggingRequestFactory factory = 
(GDataLoggingRequestFactory) this.factory;
+                factory.MethodOverride = true;
+                service.RequestFactory = this.factory; 
+
+                query.Uri = new Uri(this.defaultUri);
+                try
+                {
+                    service.Query(query);
+                }  
+                catch (InvalidCredentialsException e)
+                {
+                    Tracing.TraceMsg("Got the correct Exception");
+                }
+                 service.Credentials = null;
+                factory.MethodOverride = false;
+            }
+        }
+        
////////////////////////////////////////////////////////////////////////////
+
+    } 
/////////////////////////////////////////////////////////////////////////////
+}
+
+
+
+

Modified: trunk/clients/cs/src/unittests/caltest.cs
==============================================================================
--- trunk/clients/cs/src/unittests/caltest.cs   (original)
+++ trunk/clients/cs/src/unittests/caltest.cs   Fri Mar 23 06:47:53 2007
@@ -32,6 +32,7 @@
 namespace Google.GData.Client.UnitTests
 {
     [TestFixture] 
+    [Category("GoogleCalendar")]
     public class CalendarTestSuite : BaseTestClass
     {
 

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Google Data API" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/google-help-dataapi?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to