Permalink
Browse files

Add UnitTests and Utilities.

Add UnitTest project.
Add Utilities project.
Add Target SDK to API Level 10.
  • Loading branch information...
1 parent 1eca7c7 commit 8b19546de549a014a4abeb156e970f4cc9167688 Simon Krueger committed Oct 1, 2012
Showing with 3,759 additions and 1 deletion.
  1. +1 −1 sample/AndroidManifest.xml
  2. +9 −0 unittest/.classpath
  3. +35 −0 unittest/.project
  4. +15 −0 unittest/AndroidManifest.xml
  5. +93 −0 unittest/build.xml
  6. +40 −0 unittest/proguard.cfg
  7. +13 −0 unittest/project.properties
  8. +46 −0 unittest/src/com/microsoft/live/TestUtils.java
  9. +349 −0 unittest/src/com/microsoft/live/unittest/ApiTest.java
  10. +87 −0 unittest/src/com/microsoft/live/unittest/CopyTest.java
  11. +143 −0 unittest/src/com/microsoft/live/unittest/DeleteTest.java
  12. +133 −0 unittest/src/com/microsoft/live/unittest/DownloadTest.java
  13. +91 −0 unittest/src/com/microsoft/live/unittest/FileOperationApiTest.java
  14. +150 −0 unittest/src/com/microsoft/live/unittest/GetTest.java
  15. +45 −0 unittest/src/com/microsoft/live/unittest/JsonEnclosingApiTest.java
  16. +87 −0 unittest/src/com/microsoft/live/unittest/MoveTest.java
  17. +212 −0 unittest/src/com/microsoft/live/unittest/PostTest.java
  18. +218 −0 unittest/src/com/microsoft/live/unittest/PutTest.java
  19. +363 −0 unittest/src/com/microsoft/live/unittest/UploadTest.java
  20. +8 −0 utilities/.classpath
  21. +33 −0 utilities/.project
  22. +9 −0 utilities/AndroidManifest.xml
  23. +90 −0 utilities/build.xml
  24. +40 −0 utilities/proguard.cfg
  25. +13 −0 utilities/project.properties
  26. +11 −0 utilities/src/com/microsoft/live/constants/ErrorCodes.java
  27. +25 −0 utilities/src/com/microsoft/live/constants/ErrorMessages.java
  28. +37 −0 utilities/src/com/microsoft/live/constants/JsonKeys.java
  29. +13 −0 utilities/src/com/microsoft/live/constants/Paths.java
  30. +38 −0 utilities/src/com/microsoft/live/constants/Scopes.java
  31. +133 −0 utilities/src/com/microsoft/live/mock/MockHttpClient.java
  32. +96 −0 utilities/src/com/microsoft/live/mock/MockHttpEntity.java
  33. +180 −0 utilities/src/com/microsoft/live/mock/MockHttpResponse.java
  34. +8 −0 utilities/src/com/microsoft/live/test/util/AssertMessages.java
  35. +52 −0 utilities/src/com/microsoft/live/test/util/AsyncRunnable.java
  36. +108 −0 utilities/src/com/microsoft/live/test/util/AsyncRunnableWithBody.java
  37. +31 −0 utilities/src/com/microsoft/live/test/util/AsyncRunnableWithDestination.java
  38. +45 −0 utilities/src/com/microsoft/live/test/util/CopyAsyncRunnable.java
  39. +35 −0 utilities/src/com/microsoft/live/test/util/DeleteAsyncRunnable.java
  40. +66 −0 utilities/src/com/microsoft/live/test/util/DownloadAsyncRunnable.java
  41. +34 −0 utilities/src/com/microsoft/live/test/util/DownloadOperationQueueingListener.java
  42. +35 −0 utilities/src/com/microsoft/live/test/util/GetAsyncRunnable.java
  43. +39 −0 utilities/src/com/microsoft/live/test/util/MoveAsyncRunnable.java
  44. +28 −0 utilities/src/com/microsoft/live/test/util/OperationQueueingListener.java
  45. +67 −0 utilities/src/com/microsoft/live/test/util/PostAsyncRunnable.java
  46. +67 −0 utilities/src/com/microsoft/live/test/util/PutAsyncRunnable.java
  47. +16 −0 utilities/src/com/microsoft/live/test/util/QueueingListener.java
  48. +150 −0 utilities/src/com/microsoft/live/test/util/UploadAsyncRunnable.java
  49. +32 −0 utilities/src/com/microsoft/live/test/util/UploadOperationQueueingListener.java
  50. +20 −0 utilities/src/com/microsoft/live/util/NullLiveAuthListener.java
  51. +27 −0 utilities/src/com/microsoft/live/util/NullLiveDownloadOperationListener.java
  52. +19 −0 utilities/src/com/microsoft/live/util/NullLiveOperationListener.java
  53. +24 −0 utilities/src/com/microsoft/live/util/NullLiveUploadOperationListener.java
View
2 sample/AndroidManifest.xml
@@ -2,7 +2,7 @@
<manifest package="com.microsoft.live.sample"
android:versionCode="1"
android:versionName="1.0" xmlns:android="http://schemas.android.com/apk/res/android">
- <uses-sdk android:minSdkVersion="8" />
+ <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="10"/>
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<application
View
9 unittest/.classpath
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="src" path="gen"/>
+ <classpathentry combineaccessrules="false" kind="src" path="/LiveSdk"/>
+ <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
+ <classpathentry kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
+ <classpathentry kind="output" path="bin/classes"/>
+</classpath>
View
35 unittest/.project
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>LiveSdkUnitTest</name>
+ <comment></comment>
+ <projects>
+ <project>LiveSdk</project>
+ <project>LiveSdkSample</project>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>com.android.ide.eclipse.adt.ApkBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>com.android.ide.eclipse.adt.AndroidNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
View
15 unittest/AndroidManifest.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.microsoft.live.unittest"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="10"/>
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
+ <instrumentation android:name="android.test.InstrumentationTestRunner" android:targetPackage="com.microsoft.live.sample"></instrumentation>
+
+ <application>
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+</manifest>
View
93 unittest/build.xml
@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project name="LiveSdkUnitTest" default="help">
+
+ <!-- build.properties has the sdk.dir.
+ Must load environment variables before including it. -->
+ <property environment="env" />
+ <property file="../build.properties" />
+
+ <!-- The local.properties file is created and updated by the 'android' tool.
+ It contains the path to the SDK. It should *NOT* be checked into
+ Version Control Systems. -->
+ <property file="local.properties" />
+
+ <!-- The ant.properties file can be created by you. It is only edited by the
+ 'android' tool to add properties to it.
+ This is the place to change some Ant specific build properties.
+ Here are some properties you may want to change/update:
+
+ source.dir
+ The name of the source directory. Default is 'src'.
+ out.dir
+ The name of the output directory. Default is 'bin'.
+
+ For other overridable properties, look at the beginning of the rules
+ files in the SDK, at tools/ant/build.xml
+
+ Properties related to the SDK location or the project target should
+ be updated using the 'android' tool with the 'update' action.
+
+ This file is an integral part of the build system for your
+ application and should be checked into Version Control Systems.
+
+ -->
+ <property file="ant.properties" />
+
+ <!-- The project.properties file is created and updated by the 'android'
+ tool, as well as ADT.
+
+ This contains project specific properties such as project target, and library
+ dependencies. Lower level build properties are stored in ant.properties
+ (or in .classpath for Eclipse projects).
+
+ This file is an integral part of the build system for your
+ application and should be checked into Version Control Systems. -->
+ <loadproperties srcFile="project.properties" />
+
+ <!-- quick check on sdk.dir -->
+ <fail
+ message="sdk.dir is missing. Make sure to generate local.properties using 'android update project'"
+ unless="sdk.dir"
+ />
+
+
+<!-- extension targets. Uncomment the ones where you want to do custom work
+ in between standard targets -->
+<!--
+ <target name="-pre-build">
+ </target>
+ <target name="-pre-compile">
+ </target>
+
+ /* This is typically used for code obfuscation.
+ Compiled code location: ${out.classes.absolute.dir}
+ If this is not done in place, override ${out.dex.input.absolute.dir} */
+ <target name="-post-compile">
+ </target>
+-->
+
+ <!-- Import the actual build file.
+
+ To customize existing targets, there are two options:
+ - Customize only one target:
+ - copy/paste the target into this file, *before* the
+ <import> task.
+ - customize it to your needs.
+ - Customize the whole content of build.xml
+ - copy/paste the content of the rules files (minus the top node)
+ into this file, replacing the <import> task.
+ - customize to your needs.
+
+ ***********************
+ ****** IMPORTANT ******
+ ***********************
+ In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
+ in order to avoid having your file be overridden by tools such as "android update project"
+ -->
+ <!-- version-tag: custom -->
+ <import file="${sdk.dir}/tools/ant/build.xml" />
+
+
+
+
+</project>
View
40 unittest/proguard.cfg
@@ -0,0 +1,40 @@
+-optimizationpasses 5
+-dontusemixedcaseclassnames
+-dontskipnonpubliclibraryclasses
+-dontpreverify
+-verbose
+-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
+
+-keep public class * extends android.app.Activity
+-keep public class * extends android.app.Application
+-keep public class * extends android.app.Service
+-keep public class * extends android.content.BroadcastReceiver
+-keep public class * extends android.content.ContentProvider
+-keep public class * extends android.app.backup.BackupAgentHelper
+-keep public class * extends android.preference.Preference
+-keep public class com.android.vending.licensing.ILicensingService
+
+-keepclasseswithmembernames class * {
+ native <methods>;
+}
+
+-keepclasseswithmembers class * {
+ public <init>(android.content.Context, android.util.AttributeSet);
+}
+
+-keepclasseswithmembers class * {
+ public <init>(android.content.Context, android.util.AttributeSet, int);
+}
+
+-keepclassmembers class * extends android.app.Activity {
+ public void *(android.view.View);
+}
+
+-keepclassmembers enum * {
+ public static **[] values();
+ public static ** valueOf(java.lang.String);
+}
+
+-keep class * implements android.os.Parcelable {
+ public static final android.os.Parcelable$Creator *;
+}
View
13 unittest/project.properties
@@ -0,0 +1,13 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system use,
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+
+# Project target.
+target=android-8
+android.library.reference.1=../src
+android.library.reference.2=../utilities
View
46 unittest/src/com/microsoft/live/TestUtils.java
@@ -0,0 +1,46 @@
+package com.microsoft.live;
+
+
+import java.util.Arrays;
+import java.util.Calendar;
+
+import org.apache.http.client.HttpClient;
+
+import android.content.Context;
+import android.test.mock.MockApplication;
+
+/**
+ * This class has access to default (i.e., internal) classes and methods inside of com.microsoft.live.
+ * It is used to assist test cases.
+ */
+public final class TestUtils {
+
+ public static LiveConnectClient newLiveConnectClient(HttpClient client) {
+ LiveAuthClient authClient = new LiveAuthClient(new MockApplication() {
+ @Override
+ public Context getApplicationContext() {
+ return this;
+ }
+ }, "someclientid");
+
+ LiveConnectSession session = new LiveConnectSession(authClient);
+ session.setAccessToken("access_token");
+ session.setAuthenticationToken("authentication_token");
+
+ Calendar calendar = Calendar.getInstance();
+ calendar.add(Calendar.SECOND, 3600);
+ session.setExpiresIn(calendar.getTime());
+
+ String[] scopes = {"scope"};
+ session.setScopes(Arrays.asList(scopes));
+ session.setRefreshToken("refresh_token");
+ session.setTokenType("token_type");
+
+ LiveConnectClient liveClient = new LiveConnectClient(session);
+ liveClient.setHttpClient(client);
+
+ return liveClient;
+ }
+
+ private TestUtils() { throw new AssertionError(); }
+}
View
349 unittest/src/com/microsoft/live/unittest/ApiTest.java
@@ -0,0 +1,349 @@
+package com.microsoft.live.unittest;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.http.Header;
+import org.apache.http.HttpResponse;
+import org.apache.http.HttpStatus;
+import org.apache.http.HttpVersion;
+import org.apache.http.StatusLine;
+import org.apache.http.client.ClientProtocolException;
+import org.apache.http.client.methods.HttpUriRequest;
+import org.apache.http.message.BasicStatusLine;
+import org.apache.http.protocol.HTTP;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import android.os.Build;
+import android.test.InstrumentationTestCase;
+
+import com.microsoft.live.LiveConnectClient;
+import com.microsoft.live.LiveDownloadOperation;
+import com.microsoft.live.LiveOperation;
+import com.microsoft.live.LiveOperationException;
+import com.microsoft.live.TestUtils;
+import com.microsoft.live.constants.ErrorCodes;
+import com.microsoft.live.constants.ErrorMessages;
+import com.microsoft.live.constants.JsonKeys;
+import com.microsoft.live.mock.MockHttpClient;
+import com.microsoft.live.mock.MockHttpEntity;
+import com.microsoft.live.mock.MockHttpResponse;
+import com.microsoft.live.test.util.AssertMessages;
+import com.microsoft.live.test.util.AsyncRunnable;
+
+public abstract class ApiTest<OperationType, ListenerType> extends InstrumentationTestCase {
+
+ private static final String INVALID_FORMAT = "!@#098 {} [] This is an invalid formated " +
+ "response body asdfkaj{}dfa(*&!@#";
+
+ /**
+ * Changes the mockClient to one that checks if the incoming requests contains the
+ * Live Library header and then reverts to the original mockClient.
+ */
+ protected void loadLiveLibraryHeaderChecker() {
+ final MockHttpClient currentMockClient = this.mockClient;
+ MockHttpClient liveLibraryHeaderCheckerClient = new MockHttpClient() {
+ @Override
+ public HttpResponse execute(HttpUriRequest request) throws IOException,
+ ClientProtocolException {
+ Header header = request.getFirstHeader("X-HTTP-Live-Library");
+
+ assertEquals("android/" + Build.VERSION.RELEASE + "_5.0", header.getValue());
+
+ // load the old mock client back after we check.
+ mockClient = currentMockClient;
+ return currentMockClient.execute(request);
+ }
+
+ @Override
+ public HttpResponse getHttpResponse() {
+ return currentMockClient.getHttpResponse();
+ }
+
+ @Override
+ public void setHttpResponse(HttpResponse httpResponse) {
+ currentMockClient.setHttpResponse(httpResponse);
+ }
+
+ @Override
+ public void addHttpResponse(HttpResponse httpResponse) {
+ currentMockClient.addHttpResponse(httpResponse);
+ }
+
+ @Override
+ public void clearHttpResponseQueue() {
+ currentMockClient.clearHttpResponseQueue();
+ }
+ };
+
+ this.mockClient = liveLibraryHeaderCheckerClient;
+ }
+
+ /** wait time to retrieve a response from a blocking queue for an async call*/
+ protected static int WAIT_TIME_IN_SECS = 10;
+
+ protected static void assertEquals(InputStream is, String response) throws IOException {
+ BufferedReader reader = new BufferedReader(new InputStreamReader(is));
+ StringBuilder sb = new StringBuilder();
+
+ try {
+ String line;
+ while ((line = reader.readLine()) != null) {
+ sb.append(line);
+ }
+ } finally {
+ // Close silently.
+ // Close could throw an exception, and if we don't catch it, it will trump
+ // the originally thrown exception.
+ // Unfortunately, this means that if there was a problem only with close the reader,
+ // it will be ignored. I assume we can safely ignore this case, because if there is
+ // a problem closing a stream, there is little we can do to correc this.
+ try { reader.close(); } catch (Exception e) { }
+ }
+
+ assertEquals(response, sb.toString());
+ }
+
+ protected BlockingQueue<LiveOperationException> exceptionQueue;
+ protected LiveConnectClient liveConnectClient;
+ protected MockHttpClient mockClient;
+ protected MockHttpEntity mockEntity;
+ protected MockHttpResponse mockResponse;
+ protected ListenerType queueingListener;
+ protected BlockingQueue<OperationType> responseQueue;
+
+ public abstract void testAsyncResponseBodyInvalid() throws Throwable;
+ public abstract void testAsyncResponseBodyValid() throws Throwable;
+ public abstract void testAsyncResponseBodyValidWithUserState() throws Throwable;
+ public abstract void testSyncResponseBodyInvalid() throws Exception;
+ public abstract void testSyncResponseBodyValid() throws Exception;
+
+ protected abstract void checkValidResponseBody(OperationType operation) throws Exception;
+ protected abstract AsyncRunnable<OperationType, ListenerType> createAsyncRunnable(String requestPath);
+ protected abstract AsyncRunnable<OperationType, ListenerType> createAsyncRunnable(String requestPath,
+ Object userState);
+ protected abstract void loadValidResponseBody() throws Exception;
+ protected abstract String getMethod();
+
+ protected void checkOperationMembers(LiveDownloadOperation operation,
+ String method,
+ String path) {
+ this.checkOperationMembers(operation, method, path, null);
+ }
+
+
+ protected void checkOperationMembers(LiveDownloadOperation operation,
+ String method,
+ String path,
+ Object userState) {
+ assertEquals(method, operation.getMethod());
+ assertEquals(path, operation.getPath());
+ assertEquals(userState, operation.getUserState());
+ }
+
+ /**
+ * Asserts that the given LiveOperation has the correct method, path, and userState
+ *
+ * @param operation
+ * @param method
+ * @param path
+ */
+ protected void checkOperationMembers(LiveOperation operation,
+ String method,
+ String path) {
+ this.checkOperationMembers(operation, method, path, null);
+ }
+
+ /**
+ * Asserts that the given LiveOperation has the correct method, path, and userState.
+ *
+ * @param operation
+ * @param method
+ * @param path
+ * @param userState
+ */
+ protected void checkOperationMembers(LiveOperation operation,
+ String method,
+ String path,
+ Object userState) {
+ assertEquals(method, operation.getMethod());
+ assertEquals(path, operation.getPath());
+ assertEquals(userState, operation.getUserState());
+ }
+
+ /**
+ * Asserts the response contains the error for an Invalid Path.
+ *
+ * @param operation
+ * @param requestPath
+ * @throws JSONException
+ */
+ protected void checkPathInvalid(LiveOperation operation,
+ String requestPath) throws JSONException {
+ JSONObject result = operation.getResult();
+ JSONObject error = result.getJSONObject(JsonKeys.ERROR);
+ String message = error.getString(JsonKeys.MESSAGE);
+ String code = error.getString(JsonKeys.CODE);
+
+ assertEquals(String.format(ErrorMessages.URL_NOT_VALID, requestPath.toLowerCase()),
+ message);
+ assertEquals(ErrorCodes.REQUEST_URL_INVALID, code);
+
+ String rawResult = operation.getRawResult();
+ assertEquals(result.toString(), rawResult);
+ }
+
+ protected void checkResponseBodyInvalid(LiveDownloadOperation operation) throws IOException {
+ InputStream is = operation.getStream();
+ ApiTest.assertEquals(is, INVALID_FORMAT);
+ }
+
+ /**
+ * Asserts the LiveOperation's result and raw result members are null.
+ *
+ * @param operation
+ */
+ protected void checkResponseBodyInvalid(LiveOperation operation) {
+ JSONObject result = operation.getResult();
+ assertNull(result);
+
+ String rawResult = operation.getRawResult();
+ assertNull(rawResult);
+ }
+
+ protected void checkReturnedException(LiveDownloadOperation fromMethod,
+ LiveDownloadOperation fromCallback,
+ LiveOperationException exception) throws IOException {
+ assertNotNull(exception.getMessage());
+
+ this.checkReturnedOperations(fromMethod, fromCallback);
+ }
+
+ /**
+ * Asserts the returned exception is not null and the LiveOperations from the method,
+ * and the callback listener are the same object. Also, asserts the responseQueue,
+ * and exceptionQueue are empty.
+ *
+ * @param fromMethod
+ * @param fromCallback
+ * @param exception
+ */
+ protected void checkReturnedException(LiveOperation fromMethod,
+ LiveOperation fromCallback,
+ LiveOperationException exception) {
+ assertNotNull(exception.getMessage());
+
+ this.checkReturnedOperations(fromMethod, fromCallback);
+
+ this.checkResponseBodyInvalid(fromMethod);
+ }
+
+ /**
+ * Asserts the returned LiveOperations from the method, and from the callback listener
+ * are the same object. Also, asserts the responseQueue and exceptionQueue are empty.
+ *
+ * @param fromMethod
+ * @param fromCallback
+ */
+ protected <T> void checkReturnedOperations(T fromMethod, T fromCallback) {
+ assertTrue(fromMethod == fromCallback);
+ assertTrue(this.responseQueue.isEmpty());
+ assertTrue(this.exceptionQueue.isEmpty());
+ }
+
+ protected void failNoIllegalArgumentExceptionThrown() {
+ this.failNoExceptionThrown(IllegalArgumentException.class);
+ }
+
+ protected void failNoLiveOperationExceptionThrown() {
+ this.failNoExceptionThrown(LiveOperationException.class);
+ }
+
+ protected void failNoNullPointerExceptionThrown() {
+ this.failNoExceptionThrown(NullPointerException.class);
+ }
+
+ /** Loads an invalid formated body into the HttpClient
+ * @throws Exception */
+ protected void loadInvalidResponseBody() throws Exception {
+ byte[] bytes = INVALID_FORMAT.getBytes();
+ this.mockResponse.addHeader(HTTP.CONTENT_LEN, Long.toString(bytes.length));
+ this.mockEntity.setInputStream(new ByteArrayInputStream(bytes));
+ this.mockClient.setHttpResponse(mockResponse);
+ }
+
+ /**
+ * Loads an invalid path response into the HttpClient.
+ *
+ * @param requestPath
+ * @throws Exception
+ */
+ protected void loadPathInvalidResponse(String requestPath) throws Exception {
+ JSONObject error = new JSONObject();
+ error.put(JsonKeys.CODE, ErrorCodes.REQUEST_URL_INVALID);
+
+ String message = String.format(ErrorMessages.URL_NOT_VALID,
+ requestPath.toLowerCase());
+ error.put(JsonKeys.MESSAGE, message);
+
+ JSONObject response = new JSONObject();
+ response.put(JsonKeys.ERROR, error);
+
+ byte[] bytes = response.toString().getBytes();
+ this.mockResponse.addHeader(HTTP.CONTENT_LEN, Long.toString(bytes.length));
+ this.mockEntity.setInputStream(new ByteArrayInputStream(bytes));
+ StatusLine status = new BasicStatusLine(HttpVersion.HTTP_1_1,
+ HttpStatus.SC_BAD_REQUEST,
+ "Bad Request");
+ this.mockResponse.setStatusLine(status);
+ this.mockClient.setHttpResponse(this.mockResponse);
+ }
+
+ protected LiveOperationException pollExceptionQueue() throws InterruptedException {
+ return this.exceptionQueue.poll(WAIT_TIME_IN_SECS, TimeUnit.SECONDS);
+ }
+
+ protected OperationType pollResponseQueue() throws InterruptedException {
+ return this.responseQueue.poll(WAIT_TIME_IN_SECS, TimeUnit.SECONDS);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ // Set up the MockClient
+ this.mockEntity = new MockHttpEntity();
+
+ StatusLine statusLine = new BasicStatusLine(HttpVersion.HTTP_1_1,
+ HttpStatus.SC_OK,
+ "OK");
+ this.mockResponse = new MockHttpResponse(this.mockEntity, statusLine);
+ this.mockClient = new MockHttpClient(this.mockResponse);
+ this.loadLiveLibraryHeaderChecker();
+ this.exceptionQueue = new LinkedBlockingQueue<LiveOperationException>();
+ this.liveConnectClient = TestUtils.newLiveConnectClient(this.mockClient);
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+
+ this.mockEntity = null;
+ this.mockClient = null;
+ this.responseQueue = null;
+ this.exceptionQueue = null;
+ this.queueingListener = null;
+ this.liveConnectClient = null;
+ }
+
+ private void failNoExceptionThrown(Class<?> cl) {
+ fail(String.format(AssertMessages.NO_EXCEPTION_THROWN, cl));
+ }
+}
View
87 unittest/src/com/microsoft/live/unittest/CopyTest.java
@@ -0,0 +1,87 @@
+package com.microsoft.live.unittest;
+
+import java.io.ByteArrayInputStream;
+
+import org.json.JSONObject;
+
+import android.text.TextUtils;
+
+import com.microsoft.live.LiveOperation;
+import com.microsoft.live.LiveOperationException;
+import com.microsoft.live.test.util.CopyAsyncRunnable;
+
+public class CopyTest extends FileOperationApiTest {
+
+ private static final String KEY = "key";
+
+ /** HTTP method this class is testing */
+ private static final String METHOD = "COPY";
+
+ private static final String VALUE = "value";
+
+ @Override
+ public void testSyncResponseBodyInvalid() throws Exception {
+ this.loadInvalidResponseBody();
+
+ try {
+ String requestPath = "folder.12319";
+ String destination = "folder.1239081";
+ this.liveConnectClient.copy(requestPath, destination);
+ this.failNoLiveOperationExceptionThrown();
+ } catch (LiveOperationException e) {
+ assertFalse(TextUtils.isEmpty(e.getMessage()));
+ }
+ }
+
+ @Override
+ public void testSyncResponseBodyValid() throws Exception {
+ this.loadValidResponseBody();
+
+ String requestPath = "folder.181231";
+ String destination = "folder.1231";
+ LiveOperation operation = this.liveConnectClient.copy(requestPath, destination);
+
+ this.checkOperationMembers(operation, METHOD, requestPath);
+ this.checkValidResponseBody(operation);
+ }
+
+ @Override
+ protected void checkValidResponseBody(LiveOperation operation) throws Exception {
+ JSONObject result = operation.getResult();
+ assertEquals(VALUE, result.getString(KEY));
+ }
+
+ @Override
+ protected CopyAsyncRunnable createAsyncRunnable(String requestPath,
+ String destination) {
+ return new CopyAsyncRunnable(this.responseQueue,
+ this.liveConnectClient,
+ requestPath,
+ destination,
+ this.queueingListener);
+ }
+
+ @Override
+ protected CopyAsyncRunnable createAsyncRunnable(String requestPath,
+ String destination,
+ Object userState) {
+ return new CopyAsyncRunnable(this.responseQueue,
+ this.liveConnectClient,
+ requestPath,
+ destination,
+ this.queueingListener,
+ userState);
+ }
+
+ @Override
+ protected String getMethod() {
+ return METHOD;
+ }
+
+ @Override
+ protected void loadValidResponseBody() throws Exception {
+ JSONObject responseBody = new JSONObject();
+ responseBody.put(KEY, VALUE);
+ this.mockEntity.setInputStream(new ByteArrayInputStream(responseBody.toString().getBytes()));
+ }
+}
View
143 unittest/src/com/microsoft/live/unittest/DeleteTest.java
@@ -0,0 +1,143 @@
+package com.microsoft.live.unittest;
+
+
+import java.io.ByteArrayInputStream;
+import java.util.concurrent.LinkedBlockingQueue;
+
+import org.json.JSONObject;
+
+import android.text.TextUtils;
+
+import com.microsoft.live.LiveOperation;
+import com.microsoft.live.LiveOperationException;
+import com.microsoft.live.LiveOperationListener;
+import com.microsoft.live.test.util.DeleteAsyncRunnable;
+import com.microsoft.live.test.util.OperationQueueingListener;
+
+public class DeleteTest extends ApiTest<LiveOperation, LiveOperationListener> {
+
+ /** HTTP method this class is testing */
+ private static final String METHOD = "DELETE";
+
+ private String calendarId;
+
+ @Override
+ public void testAsyncResponseBodyInvalid() throws Throwable {
+ this.loadInvalidResponseBody();
+
+ String requestPath = this.calendarId;
+ this.runTestOnUiThread(createAsyncRunnable(requestPath));
+
+ LiveOperation fromMethod = this.responseQueue.take();
+ LiveOperation fromCallback = this.pollResponseQueue();
+ LiveOperationException exception = this.pollExceptionQueue();
+
+ this.checkReturnedException(fromMethod, fromCallback, exception);
+ this.checkOperationMembers(fromMethod, METHOD, requestPath);
+ this.checkResponseBodyInvalid(fromMethod);
+ }
+
+ @Override
+ public void testAsyncResponseBodyValid() throws Throwable {
+ this.loadValidResponseBody();
+
+ String requestPath = this.calendarId;
+ this.runTestOnUiThread(createAsyncRunnable(requestPath));
+
+ LiveOperation fromMethod = this.responseQueue.take();
+ LiveOperation fromCallback = this.pollResponseQueue();
+
+ this.checkReturnedOperations(fromMethod, fromCallback);
+ this.checkOperationMembers(fromMethod, METHOD, requestPath);
+ this.checkValidResponseBody(fromMethod);
+ }
+
+ @Override
+ public void testAsyncResponseBodyValidWithUserState() throws Throwable {
+ this.loadValidResponseBody();
+
+ Object userState = new Object();
+ String requestPath = this.calendarId;
+ this.runTestOnUiThread(createAsyncRunnable(requestPath, userState));
+
+ LiveOperation fromMethod = this.responseQueue.take();
+ LiveOperation fromCallback = this.pollResponseQueue();
+
+ this.checkReturnedOperations(fromMethod, fromCallback);
+ this.checkOperationMembers(fromMethod, METHOD, requestPath, userState);
+ this.checkValidResponseBody(fromMethod);
+ }
+
+
+ @Override
+ public void testSyncResponseBodyInvalid() throws Exception {
+ this.loadInvalidResponseBody();
+
+ try {
+ String requestPath = this.calendarId;
+ this.liveConnectClient.delete(requestPath);
+ this.failNoLiveOperationExceptionThrown();
+ } catch (LiveOperationException e) {
+ assertFalse(TextUtils.isEmpty(e.getMessage()));
+ }
+ }
+
+ @Override
+ public void testSyncResponseBodyValid() throws Exception {
+ this.loadValidResponseBody();
+
+ String requestPath = this.calendarId;
+ LiveOperation operation = this.liveConnectClient.delete(requestPath);
+
+ this.checkOperationMembers(operation, METHOD, requestPath);
+ this.checkValidResponseBody(operation);
+ }
+
+ @Override
+ protected void checkValidResponseBody(LiveOperation operation) {
+ JSONObject result = operation.getResult();
+ assertEquals(0, result.length());
+
+ String rawResult = operation.getRawResult();
+ assertEquals("{}", rawResult);
+ }
+
+ @Override
+ protected DeleteAsyncRunnable createAsyncRunnable(String requestPath) {
+ return new DeleteAsyncRunnable(this.responseQueue,
+ this.liveConnectClient,
+ requestPath,
+ this.queueingListener);
+ }
+
+ @Override
+ protected DeleteAsyncRunnable createAsyncRunnable(String requestPath, Object userState) {
+ return new DeleteAsyncRunnable(this.responseQueue,
+ this.liveConnectClient,
+ requestPath,
+ this.queueingListener,
+ userState);
+ }
+
+ @Override
+ protected String getMethod() {
+ return METHOD;
+ }
+
+ @Override
+ protected void loadValidResponseBody() {
+ // valid delete bodies are empty strings
+ String validResponseBody = "";
+ this.mockEntity.setInputStream(new ByteArrayInputStream(validResponseBody.getBytes()));
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ this.calendarId = "calendar.013123";
+ this.responseQueue = new LinkedBlockingQueue<LiveOperation>();
+ this.queueingListener = new OperationQueueingListener(this.exceptionQueue,
+ this.responseQueue);
+ }
+}
View
133 unittest/src/com/microsoft/live/unittest/DownloadTest.java
@@ -0,0 +1,133 @@
+package com.microsoft.live.unittest;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.util.concurrent.LinkedBlockingQueue;
+
+import org.apache.http.protocol.HTTP;
+
+import com.microsoft.live.LiveDownloadOperation;
+import com.microsoft.live.LiveDownloadOperationListener;
+import com.microsoft.live.test.util.DownloadAsyncRunnable;
+import com.microsoft.live.test.util.DownloadOperationQueueingListener;
+
+public class DownloadTest extends ApiTest<LiveDownloadOperation, LiveDownloadOperationListener> {
+
+ private static final String VALID_PATH = "file.123/content";
+ private static final String RESPONSE = "Some random data";
+
+ @Override
+ public void testAsyncResponseBodyInvalid() throws Throwable {
+ this.loadInvalidResponseBody();
+
+ String requestPath = VALID_PATH;
+ this.runTestOnUiThread(this.createAsyncRunnable(requestPath));
+
+ LiveDownloadOperation fromMethod = this.responseQueue.take();
+ LiveDownloadOperation fromCallback = this.pollResponseQueue();
+
+ this.checkReturnedOperations(fromMethod, fromCallback);
+ this.checkOperationMembers(fromMethod, this.getMethod(), requestPath);
+ this.checkResponseBodyInvalid(fromMethod);
+ }
+
+ @Override
+ public void testAsyncResponseBodyValid() throws Throwable {
+ this.loadValidResponseBody();
+ String requestPath = VALID_PATH;
+
+ this.runTestOnUiThread(this.createAsyncRunnable(requestPath));
+
+ LiveDownloadOperation fromMethod = this.responseQueue.take();
+ LiveDownloadOperation fromCallback = this.pollResponseQueue();
+
+ this.checkReturnedOperations(fromMethod, fromCallback);
+ this.checkOperationMembers(fromMethod, this.getMethod(), requestPath);
+ this.checkValidResponseBody(fromMethod);
+ }
+
+ @Override
+ public void testAsyncResponseBodyValidWithUserState() throws Throwable {
+ this.loadValidResponseBody();
+ String requestPath = VALID_PATH;
+ Object userState = new Object();
+
+ this.runTestOnUiThread(this.createAsyncRunnable(requestPath, userState));
+
+ LiveDownloadOperation fromMethod = this.responseQueue.take();
+ LiveDownloadOperation fromCallback = this.pollResponseQueue();
+
+ this.checkReturnedOperations(fromMethod, fromCallback);
+ this.checkOperationMembers(fromMethod, this.getMethod(), requestPath, userState);
+ this.checkValidResponseBody(fromMethod);
+
+ }
+
+
+ @Override
+ public void testSyncResponseBodyInvalid() throws Exception {
+ this.loadInvalidResponseBody();
+
+ String requestPath = VALID_PATH;
+
+ LiveDownloadOperation operation = this.liveConnectClient.download(requestPath);
+
+ this.checkOperationMembers(operation, this.getMethod(), requestPath);
+ this.checkResponseBodyInvalid(operation);
+ }
+
+ @Override
+ public void testSyncResponseBodyValid() throws Exception {
+ this.loadValidResponseBody();
+ String requestPath = VALID_PATH;
+
+ LiveDownloadOperation operation = this.liveConnectClient.download(requestPath);
+
+ this.checkOperationMembers(operation, this.getMethod(), requestPath);
+ this.checkValidResponseBody(operation);
+ }
+
+ @Override
+ protected void checkValidResponseBody(LiveDownloadOperation operation) throws Exception {
+ InputStream is = operation.getStream();
+ ApiTest.assertEquals(is, RESPONSE);
+ }
+
+ @Override
+ protected DownloadAsyncRunnable createAsyncRunnable(String requestPath) {
+ return new DownloadAsyncRunnable(this.responseQueue,
+ this.liveConnectClient,
+ requestPath,
+ this.queueingListener);
+ }
+
+ @Override
+ protected DownloadAsyncRunnable createAsyncRunnable(String requestPath, Object userState) {
+ return new DownloadAsyncRunnable(this.responseQueue,
+ this.liveConnectClient,
+ requestPath,
+ this.queueingListener,
+ userState);
+ }
+
+ @Override
+ protected String getMethod() {
+ return "GET";
+ }
+
+ @Override
+ protected void loadValidResponseBody() throws Exception {
+ byte[] bytes = RESPONSE.getBytes();
+ this.mockResponse.addHeader(HTTP.CONTENT_LEN, Long.toString(bytes.length));
+ this.mockEntity.setInputStream(new ByteArrayInputStream(bytes));
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ this.responseQueue = new LinkedBlockingQueue<LiveDownloadOperation>();
+ this.queueingListener = new DownloadOperationQueueingListener(this.exceptionQueue,
+ this.responseQueue);
+ }
+}
View
91 unittest/src/com/microsoft/live/unittest/FileOperationApiTest.java
@@ -0,0 +1,91 @@
+package com.microsoft.live.unittest;
+
+import java.util.concurrent.LinkedBlockingQueue;
+
+import com.microsoft.live.LiveOperation;
+import com.microsoft.live.LiveOperationException;
+import com.microsoft.live.LiveOperationListener;
+import com.microsoft.live.test.util.AsyncRunnable;
+import com.microsoft.live.test.util.AsyncRunnableWithDestination;
+import com.microsoft.live.test.util.OperationQueueingListener;
+
+public abstract class FileOperationApiTest extends ApiTest<LiveOperation, LiveOperationListener> {
+
+ @Override
+ public void testAsyncResponseBodyInvalid() throws Throwable {
+ this.loadInvalidResponseBody();
+
+ String requestPath = "file.123123";
+ String destination = "file.123109";
+ this.runTestOnUiThread(createAsyncRunnable(requestPath, destination));
+
+ LiveOperation fromMethod = this.responseQueue.take();
+ LiveOperation fromCallback = this.pollResponseQueue();
+ LiveOperationException exception = this.pollExceptionQueue();
+
+ this.checkReturnedException(fromMethod, fromCallback, exception);
+ this.checkOperationMembers(fromMethod, this.getMethod(), requestPath);
+ this.checkResponseBodyInvalid(fromMethod);
+
+ }
+
+ @Override
+ public void testAsyncResponseBodyValid() throws Throwable {
+ this.loadValidResponseBody();
+
+ String requestPath = "file.123123";
+ String destination = "file.123109";
+ this.runTestOnUiThread(createAsyncRunnable(requestPath, destination));
+
+ LiveOperation fromMethod = this.responseQueue.take();
+ LiveOperation fromCallback = this.pollResponseQueue();
+
+ this.checkReturnedOperations(fromMethod, fromCallback);
+ this.checkOperationMembers(fromMethod, this.getMethod(), requestPath);
+ this.checkValidResponseBody(fromMethod);
+ }
+
+ @Override
+ public void testAsyncResponseBodyValidWithUserState() throws Throwable {
+ this.loadValidResponseBody();
+
+ String requestPath = "file.123123";
+ String destination = "file.123109";
+ Object userState = new Object();
+
+ this.runTestOnUiThread(createAsyncRunnable(requestPath, destination, userState));
+
+ LiveOperation fromMethod = this.responseQueue.take();
+ LiveOperation fromCallback = this.pollResponseQueue();
+
+ this.checkReturnedOperations(fromMethod, fromCallback);
+ this.checkOperationMembers(fromMethod, this.getMethod(), requestPath, userState);
+ this.checkValidResponseBody(fromMethod);
+ }
+
+ protected abstract AsyncRunnableWithDestination<LiveOperation, LiveOperationListener>
+ createAsyncRunnable(String requestPath, String destination);
+
+ protected abstract AsyncRunnableWithDestination<LiveOperation, LiveOperationListener>
+ createAsyncRunnable(String requestPath, String destination, Object userState);
+
+ @Override
+ protected AsyncRunnable<LiveOperation, LiveOperationListener> createAsyncRunnable(String requestPath) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ protected AsyncRunnable<LiveOperation, LiveOperationListener> createAsyncRunnable(String requestPath,
+ Object userState) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ this.responseQueue = new LinkedBlockingQueue<LiveOperation>();
+ this.queueingListener = new OperationQueueingListener(this.exceptionQueue,
+ this.responseQueue);
+ }
+}
View
150 unittest/src/com/microsoft/live/unittest/GetTest.java
@@ -0,0 +1,150 @@
+package com.microsoft.live.unittest;
+
+
+import java.io.ByteArrayInputStream;
+import java.util.concurrent.LinkedBlockingQueue;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import com.microsoft.live.LiveOperation;
+import com.microsoft.live.LiveOperationException;
+import com.microsoft.live.LiveOperationListener;
+import com.microsoft.live.constants.JsonKeys;
+import com.microsoft.live.constants.Paths;
+import com.microsoft.live.test.util.GetAsyncRunnable;
+import com.microsoft.live.test.util.OperationQueueingListener;
+
+/**
+ * Tests all the get operations of the LiveConnectClient.
+ */
+public class GetTest extends ApiTest<LiveOperation, LiveOperationListener> {
+
+ private static final String METHOD = "GET";
+
+ private static final String USERNAME = "username@live.com";
+
+ @Override
+ public void testAsyncResponseBodyInvalid() throws Throwable {
+ this.loadInvalidResponseBody();
+
+ String requestPath = Paths.ME;
+ this.runTestOnUiThread(createAsyncRunnable(requestPath));
+
+ LiveOperation fromMethod = this.responseQueue.take();
+ LiveOperation fromCallback = this.pollResponseQueue();
+ LiveOperationException exception = this.pollExceptionQueue();
+
+ this.checkReturnedException(fromMethod, fromCallback, exception);
+ this.checkOperationMembers(fromMethod, METHOD, requestPath);
+ this.checkResponseBodyInvalid(fromMethod);
+ }
+
+ @Override
+ public void testAsyncResponseBodyValid() throws Throwable {
+ this.loadValidResponseBody();
+
+ String requestPath = Paths.ME;
+ this.runTestOnUiThread(createAsyncRunnable(requestPath));
+
+ LiveOperation fromMethod = this.responseQueue.take();
+ LiveOperation fromCallback = this.pollResponseQueue();
+
+ this.checkReturnedOperations(fromMethod, fromCallback);
+ this.checkOperationMembers(fromMethod, METHOD, requestPath);
+ this.checkValidResponseBody(fromMethod);
+ }
+
+ @Override
+ public void testAsyncResponseBodyValidWithUserState() throws Throwable {
+ this.loadValidResponseBody();
+
+ Object userState = new Object();
+ String requestPath = Paths.ME;
+ this.runTestOnUiThread(createAsyncRunnable(requestPath, userState));
+
+ LiveOperation fromMethod = this.responseQueue.take();
+ LiveOperation fromCallback = this.pollResponseQueue();
+
+ this.checkReturnedOperations(fromMethod, fromCallback);
+ this.checkOperationMembers(fromMethod, METHOD, requestPath, userState);
+ this.checkValidResponseBody(fromMethod);
+ }
+
+
+ @Override
+ public void testSyncResponseBodyInvalid() throws Exception {
+ this.loadInvalidResponseBody();
+
+ try {
+ this.liveConnectClient.get(Paths.ME);
+ this.failNoLiveOperationExceptionThrown();
+ } catch (LiveOperationException e) {
+ assertNotNull(e.getMessage());
+ }
+ }
+
+ @Override
+ public void testSyncResponseBodyValid() throws Exception {
+ this.loadValidResponseBody();
+
+ String requestPath = Paths.ME;
+ LiveOperation operation = this.liveConnectClient.get(requestPath);
+
+ this.checkOperationMembers(operation, METHOD, requestPath);
+ this.checkValidResponseBody(operation);
+ }
+
+ @Override
+ protected void checkValidResponseBody(LiveOperation operation) throws JSONException {
+ JSONObject response = operation.getResult();
+ JSONObject emails = response.getJSONObject(JsonKeys.EMAILS);
+ String account = emails.getString(JsonKeys.ACCOUNT);
+
+ assertEquals(USERNAME, account);
+ }
+
+ @Override
+ protected GetAsyncRunnable createAsyncRunnable(String requestPath) {
+ return new GetAsyncRunnable(this.responseQueue,
+ this.liveConnectClient,
+ requestPath,
+ this.queueingListener);
+ }
+
+ @Override
+ protected GetAsyncRunnable createAsyncRunnable(String requestPath, Object userState) {
+ return new GetAsyncRunnable(this.responseQueue,
+ this.liveConnectClient,
+ requestPath,
+ this.queueingListener,
+ userState);
+ }
+
+ @Override
+ protected String getMethod() {
+ return METHOD;
+ }
+
+ @Override
+ protected void loadValidResponseBody() throws JSONException {
+ String injectedAccount = USERNAME;
+ JSONObject injectedEmails = new JSONObject();
+ injectedEmails.put(JsonKeys.ACCOUNT, injectedAccount);
+
+ JSONObject injectedResponse = new JSONObject();
+ injectedResponse.put(JsonKeys.EMAILS, injectedEmails);
+
+ byte[] bytes = injectedResponse.toString().getBytes();
+ this.mockEntity.setInputStream(new ByteArrayInputStream(bytes));
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ this.responseQueue = new LinkedBlockingQueue<LiveOperation>();
+ this.queueingListener = new OperationQueueingListener(this.exceptionQueue,
+ this.responseQueue);
+ }
+}
View
45 unittest/src/com/microsoft/live/unittest/JsonEnclosingApiTest.java
@@ -0,0 +1,45 @@
+package com.microsoft.live.unittest;
+
+import java.util.concurrent.LinkedBlockingQueue;
+
+import org.json.JSONObject;
+
+import com.microsoft.live.LiveOperation;
+import com.microsoft.live.LiveOperationListener;
+import com.microsoft.live.test.util.AsyncRunnable;
+import com.microsoft.live.test.util.AsyncRunnableWithBody;
+import com.microsoft.live.test.util.OperationQueueingListener;
+
+public abstract class JsonEnclosingApiTest extends ApiTest<LiveOperation, LiveOperationListener> {
+ protected abstract AsyncRunnableWithBody<LiveOperation, LiveOperationListener>
+ createAsyncRunnable(String requestPath, JSONObject body);
+
+ protected abstract AsyncRunnableWithBody<LiveOperation, LiveOperationListener>
+ createAsyncRunnable(String requestPath, JSONObject body, Object userState);
+
+ protected abstract AsyncRunnableWithBody<LiveOperation, LiveOperationListener>
+ createAsyncRunnable(String requestPath, String body);
+
+ protected abstract AsyncRunnableWithBody<LiveOperation, LiveOperationListener>
+ createAsyncRunnable(String requestPath, String body, Object userState);
+
+ @Override
+ protected AsyncRunnable<LiveOperation, LiveOperationListener> createAsyncRunnable(String requestPath) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ protected AsyncRunnable<LiveOperation, LiveOperationListener> createAsyncRunnable(String requestPath,
+ Object userState) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ this.responseQueue = new LinkedBlockingQueue<LiveOperation>();
+ this.queueingListener = new OperationQueueingListener(this.exceptionQueue,
+ this.responseQueue);
+ }
+}
View
87 unittest/src/com/microsoft/live/unittest/MoveTest.java
@@ -0,0 +1,87 @@
+package com.microsoft.live.unittest;
+
+import java.io.ByteArrayInputStream;
+
+import org.json.JSONObject;
+
+import android.text.TextUtils;
+
+import com.microsoft.live.LiveOperation;
+import com.microsoft.live.LiveOperationException;
+import com.microsoft.live.test.util.MoveAsyncRunnable;
+
+public class MoveTest extends FileOperationApiTest {
+
+ private static final String KEY = "key";
+
+ /** HTTP method this class is testing */
+ private static final String METHOD = "MOVE";
+
+ private static final String VALUE = "value";
+
+ @Override
+ public void testSyncResponseBodyInvalid() throws Exception {
+ this.loadInvalidResponseBody();
+
+ try {
+ String requestPath = "folder.12319";
+ String destination = "folder.1239081";
+ this.liveConnectClient.move(requestPath, destination);
+ this.failNoLiveOperationExceptionThrown();
+ } catch (LiveOperationException e) {
+ assertFalse(TextUtils.isEmpty(e.getMessage()));
+ }
+ }
+
+ @Override
+ public void testSyncResponseBodyValid() throws Exception {
+ this.loadValidResponseBody();
+
+ String requestPath = "folder.181231";
+ String destination = "folder.1231";
+ LiveOperation operation = this.liveConnectClient.move(requestPath, destination);
+
+ this.checkOperationMembers(operation, METHOD, requestPath);
+ this.checkValidResponseBody(operation);
+ }
+
+ @Override
+ protected void checkValidResponseBody(LiveOperation operation) throws Exception {
+ JSONObject result = operation.getResult();
+ assertEquals(VALUE, result.getString(KEY));
+ }
+
+ @Override
+ protected MoveAsyncRunnable createAsyncRunnable(String requestPath,
+ String destination) {
+ return new MoveAsyncRunnable(this.responseQueue,
+ this.liveConnectClient,
+ requestPath,
+ destination,
+ this.queueingListener);
+ }
+
+ @Override
+ protected MoveAsyncRunnable createAsyncRunnable(String requestPath,
+ String destination,
+ Object userState) {
+ return new MoveAsyncRunnable(this.responseQueue,
+ this.liveConnectClient,
+ requestPath,
+ destination,
+ this.queueingListener,
+ userState);
+ }
+
+ @Override
+ protected String getMethod() {
+ return METHOD;
+ }
+
+ @Override
+ protected void loadValidResponseBody() throws Exception {
+ JSONObject responseBody = new JSONObject();
+ responseBody.put(KEY, VALUE);
+ this.mockEntity.setInputStream(new ByteArrayInputStream(responseBody.toString().getBytes()));
+ }
+}
View
212 unittest/src/com/microsoft/live/unittest/PostTest.java
@@ -0,0 +1,212 @@
+package com.microsoft.live.unittest;
+
+
+import java.io.ByteArrayInputStream;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import android.text.TextUtils;
+
+import com.microsoft.live.LiveOperation;
+import com.microsoft.live.LiveOperationException;
+import com.microsoft.live.constants.JsonKeys;
+import com.microsoft.live.constants.Paths;
+import com.microsoft.live.test.util.PostAsyncRunnable;
+
+
+public class PostTest extends JsonEnclosingApiTest {
+
+ /** The body of the post request. */
+ private static final JSONObject CALENDAR;
+
+ private static final String METHOD = "POST";
+
+ /** Name of the calendar to be created */
+ private static final String NAME = "Test Calendar";
+
+ static {
+ Map<String, String> calendar = new HashMap<String, String>();
+ calendar.put(JsonKeys.NAME, NAME);
+
+ CALENDAR = new JSONObject(calendar);
+ }
+
+
+ @Override
+ public void testAsyncResponseBodyInvalid() throws Throwable {
+ this.loadInvalidResponseBody();
+
+ String requestPath = Paths.INVALID;
+
+ this.runTestOnUiThread(createAsyncRunnable(requestPath, CALENDAR));
+
+ LiveOperation fromMethod = this.responseQueue.take();
+ LiveOperation fromCallback = this.pollResponseQueue();
+ LiveOperationException exception = this.pollExceptionQueue();
+
+ this.checkReturnedException(fromMethod, fromCallback, exception);
+ this.checkOperationMembers(fromMethod, METHOD, requestPath);
+ this.checkResponseBodyInvalid(fromMethod);
+ }
+
+ @Override
+ public void testAsyncResponseBodyValid() throws Throwable {
+ this.loadValidResponseBody();
+
+ String requestPath = Paths.ME_CALENDARS;
+
+ this.runTestOnUiThread(createAsyncRunnable(requestPath, CALENDAR));
+
+ LiveOperation fromMethod = this.responseQueue.take();
+ LiveOperation fromCallback = this.pollResponseQueue();
+
+ this.checkReturnedOperations(fromMethod, fromCallback);
+ this.checkOperationMembers(fromMethod, METHOD, requestPath);
+
+ this.checkValidResponseBody(fromMethod);
+ }
+
+ @Override
+ public void testAsyncResponseBodyValidWithUserState() throws Throwable {
+ this.loadValidResponseBody();
+
+ Object userState = new Object();
+ String requestPath = Paths.ME_CALENDARS;
+
+ this.runTestOnUiThread(createAsyncRunnable(requestPath, CALENDAR, userState));
+
+ LiveOperation fromMethod = this.responseQueue.take();
+ LiveOperation fromCallback = this.pollResponseQueue();
+
+ this.checkReturnedOperations(fromMethod, fromCallback);
+ this.checkOperationMembers(fromMethod, METHOD, requestPath, userState);
+
+ this.checkValidResponseBody(fromMethod);
+ }
+
+
+ @Override
+ public void testSyncResponseBodyInvalid() throws Exception {
+ this.loadInvalidResponseBody();
+
+ try {
+ this.liveConnectClient.post(Paths.ME_CALENDARS, CALENDAR);
+ this.failNoLiveOperationExceptionThrown();
+ } catch (LiveOperationException e) {
+ assertFalse(TextUtils.isEmpty(e.getMessage()));
+ }
+ }
+
+ @Override
+ public void testSyncResponseBodyValid() throws Exception {
+ this.loadValidResponseBody();
+
+ String requestPath = Paths.ME_CALENDARS;
+
+ LiveOperation operation = this.liveConnectClient.post(requestPath, CALENDAR);
+
+ this.checkOperationMembers(operation, METHOD, requestPath);
+ this.checkValidResponseBody(operation);
+ }
+
+ @Override
+ protected void checkValidResponseBody(LiveOperation operation) throws JSONException {
+ JSONObject result = operation.getResult();
+ String id = result.getString(JsonKeys.ID);
+ Object description = result.get(JsonKeys.DESCRIPTION);
+ String name = result.getString(JsonKeys.NAME);
+ String permissions = result.getString(JsonKeys.PERMISSIONS);
+ boolean isDefault = result.getBoolean(JsonKeys.IS_DEFAULT);
+
+ JSONObject from = result.getJSONObject(JsonKeys.FROM);
+ String fromId = from.getString(JsonKeys.ID);
+ String fromName = from.getString(JsonKeys.NAME);
+
+ Object subscriptionLocation = result.get(JsonKeys.SUBSCRIPTION_LOCATION);
+ String createdTime = result.getString(JsonKeys.CREATED_TIME);
+ String updatedTime = result.getString(JsonKeys.UPDATED_TIME);
+
+ assertEquals("calendar_id", id);
+ assertEquals(JSONObject.NULL, description);
+ assertEquals("name", name);
+ assertEquals("owner", permissions);
+ assertEquals(false, isDefault);
+ assertEquals("from_id", fromId);
+ assertEquals("from_name", fromName);
+ assertEquals(JSONObject.NULL, subscriptionLocation);
+ assertEquals("2011-12-10T02:48:33+0000", createdTime);
+ assertEquals("2011-12-10T02:48:33+0000", updatedTime);
+ }
+
+ @Override
+ protected PostAsyncRunnable createAsyncRunnable(String requestPath, JSONObject body) {
+ return new PostAsyncRunnable(this.responseQueue,
+ this.liveConnectClient,
+ requestPath,
+ body,
+ this.queueingListener);
+ }
+
+ @Override
+ protected PostAsyncRunnable createAsyncRunnable(String requestPath,
+ JSONObject body,
+ Object userState) {
+ return new PostAsyncRunnable(this.responseQueue,
+ this.liveConnectClient,
+ requestPath,
+ body,
+ this.queueingListener,
+ userState);
+ }
+
+ @Override
+ protected PostAsyncRunnable createAsyncRunnable(String requestPath, String body) {
+ return new PostAsyncRunnable(this.responseQueue,
+ this.liveConnectClient,
+ requestPath,
+ body,
+ this.queueingListener);
+ }
+
+ @Override
+ protected PostAsyncRunnable createAsyncRunnable(String requestPath,
+ String body,
+ Object userState) {
+ return new PostAsyncRunnable(this.responseQueue,
+ this.liveConnectClient,
+ requestPath,
+ body,
+ this.queueingListener,
+ userState);
+ }
+
+ @Override
+ protected String getMethod() {
+ return METHOD;
+ }
+
+ @Override
+ protected void loadValidResponseBody() throws JSONException {
+ JSONObject calendar = new JSONObject();
+ calendar.put(JsonKeys.ID, "calendar_id");
+ calendar.put(JsonKeys.DESCRIPTION, JSONObject.NULL);
+ calendar.put(JsonKeys.NAME, "name");
+ calendar.put(JsonKeys.PERMISSIONS, "owner");
+ calendar.put(JsonKeys.IS_DEFAULT, false);
+
+ JSONObject from = new JSONObject();
+ from.put(JsonKeys.ID, "from_id");
+ from.put(JsonKeys.NAME, "from_name");
+
+ calendar.put(JsonKeys.FROM, from);
+ calendar.put(JsonKeys.SUBSCRIPTION_LOCATION, JSONObject.NULL);
+ calendar.put(JsonKeys.CREATED_TIME, "2011-12-10T02:48:33+0000");
+ calendar.put(JsonKeys.UPDATED_TIME, "2011-12-10T02:48:33+0000");
+
+ byte[] bytes = calendar.toString().getBytes();
+ this.mockEntity.setInputStream(new ByteArrayInputStream(bytes));
+ }
+}
View
218 unittest/src/com/microsoft/live/unittest/PutTest.java
@@ -0,0 +1,218 @@
+package com.microsoft.live.unittest;
+
+import java.io.ByteArrayInputStream;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import android.text.TextUtils;
+
+import com.microsoft.live.LiveOperation;
+import com.microsoft.live.LiveOperationException;
+import com.microsoft.live.constants.JsonKeys;
+import com.microsoft.live.constants.Paths;
+import com.microsoft.live.test.util.PutAsyncRunnable;
+
+public class PutTest extends JsonEnclosingApiTest {
+
+ /** The Calendar object created. */
+ private static final JSONObject CALENDAR;
+
+ private static final String METHOD = "PUT";
+
+ /** Name of the calendar to be updated */
+ private static final String NAME = "Test Calendar Updated";
+
+ static {
+ Map<String, String> calendar = new HashMap<String, String>();
+ calendar.put(JsonKeys.NAME, NAME);
+
+ CALENDAR = new JSONObject(calendar);
+ }
+
+ private String calendarId;
+
+ @Override
+ public void testAsyncResponseBodyInvalid() throws Throwable {
+ this.loadInvalidResponseBody();
+
+ String requestPath = Paths.INVALID;
+
+ this.runTestOnUiThread(createAsyncRunnable(requestPath, CALENDAR));
+
+ LiveOperation fromMethod = this.responseQueue.take();
+ LiveOperation fromCallback = this.pollResponseQueue();
+ LiveOperationException exception = this.pollExceptionQueue();
+
+ this.checkReturnedException(fromMethod, fromCallback, exception);
+ this.checkOperationMembers(fromMethod, METHOD, requestPath);
+ this.checkResponseBodyInvalid(fromMethod);
+ }
+
+ @Override
+ public void testAsyncResponseBodyValid() throws Throwable {
+ this.loadValidResponseBody();
+
+ String requestPath = this.calendarId;
+
+ this.runTestOnUiThread(createAsyncRunnable(requestPath, CALENDAR));
+
+ LiveOperation fromMethod = this.responseQueue.take();
+ LiveOperation fromCallback = this.pollResponseQueue();
+
+ this.checkReturnedOperations(fromMethod, fromCallback);
+ this.checkOperationMembers(fromMethod, METHOD, requestPath);
+
+ this.checkValidResponseBody(fromMethod);
+ }
+
+ @Override
+ public void testAsyncResponseBodyValidWithUserState() throws Throwable {
+ this.loadValidResponseBody();
+
+ Object userState = new Object();
+ String requestPath = this.calendarId;
+
+ this.runTestOnUiThread(createAsyncRunnable(requestPath, CALENDAR, userState));
+
+ LiveOperation fromMethod = this.responseQueue.take();
+ LiveOperation fromCallback = this.pollResponseQueue();
+
+ this.checkReturnedOperations(fromMethod, fromCallback);
+ this.checkOperationMembers(fromMethod, METHOD, requestPath, userState);
+
+ this.checkValidResponseBody(fromMethod);
+ }
+
+
+ @Override
+ public void testSyncResponseBodyInvalid() throws Exception {
+ this.loadInvalidResponseBody();
+
+ try {
+ this.liveConnectClient.put(Paths.ME_CALENDARS, CALENDAR);
+ this.failNoLiveOperationExceptionThrown();
+ } catch (LiveOperationException e) {
+ assertFalse(TextUtils.isEmpty(e.getMessage()));
+ }
+ }
+
+ @Override
+ public void testSyncResponseBodyValid() throws Exception {
+ this.loadValidResponseBody();
+
+ String requestPath = this.calendarId;
+
+ LiveOperation operation = this.liveConnectClient.put(requestPath, CALENDAR);
+
+ this.checkOperationMembers(operation, METHOD, requestPath);
+ this.checkValidResponseBody(operation);
+ }
+
+ @Override
+ protected void checkValidResponseBody(LiveOperation operation) throws JSONException {
+ JSONObject result = operation.getResult();
+ String id = result.getString(JsonKeys.ID);
+ Object description = result.get(JsonKeys.DESCRIPTION);
+ String name = result.getString(JsonKeys.NAME);
+ String permissions = result.getString(JsonKeys.PERMISSIONS);
+ boolean isDefault = result.getBoolean(JsonKeys.IS_DEFAULT);
+
+ JSONObject from = result.getJSONObject(JsonKeys.FROM);
+ String fromId = from.getString(JsonKeys.ID);
+ String fromName = from.getString(JsonKeys.NAME);
+
+ Object subscriptionLocation = result.get(JsonKeys.SUBSCRIPTION_LOCATION);
+ String createdTime = result.getString(JsonKeys.CREATED_TIME);
+ String updatedTime = result.getString(JsonKeys.UPDATED_TIME);
+
+ assertEquals("calendar_id", id);
+ assertEquals(JSONObject.NULL, description);
+ assertEquals("name", name);
+ assertEquals("owner", permissions);
+ assertEquals(false, isDefault);
+ assertEquals("from_id", fromId);
+ assertEquals("from_name", fromName);
+ assertEquals(JSONObject.NULL, subscriptionLocation);
+ assertEquals("2011-12-10T02:48:33+0000", createdTime);
+ assertEquals("2011-12-10T02:48:33+0000", updatedTime);
+ }
+
+ @Override
+ protected PutAsyncRunnable createAsyncRunnable(String requestPath, JSONObject body) {
+ return new PutAsyncRunnable(this.responseQueue,
+ this.liveConnectClient,
+ requestPath,
+ body,
+ this.queueingListener);
+ }
+
+ @Override
+ protected PutAsyncRunnable createAsyncRunnable(String requestPath,
+ JSONObject body,
+ Object userState) {
+ return new PutAsyncRunnable(this.responseQueue,
+ this.liveConnectClient,
+ requestPath,
+ body,
+ this.queueingListener,
+ userState);
+ }
+
+ @Override
+ protected PutAsyncRunnable createAsyncRunnable(String requestPath, String body) {
+ return new PutAsyncRunnable(this.responseQueue,
+ this.liveConnectClient,
+ requestPath,
+ body,
+ this.queueingListener);
+ }
+
+ @Override
+ protected PutAsyncRunnable createAsyncRunnable(String requestPath,
+ String body,
+ Object userState) {
+ return new PutAsyncRunnable(this.responseQueue,
+ this.liveConnectClient,
+ requestPath,
+ body,
+ this.queueingListener,
+ userState);
+ }
+
+ @Override
+ protected String getMethod() {
+ return METHOD;
+ }
+
+ @Override
+ protected void loadValidResponseBody() throws JSONException {
+ JSONObject calendar = new JSONObject();
+ calendar.put(JsonKeys.ID, "calendar_id");
+ calendar.put(JsonKeys.DESCRIPTION, JSONObject.NULL);
+ calendar.put(JsonKeys.NAME, "name");
+ calendar.put(JsonKeys.PERMISSIONS, "owner");
+ calendar.put(JsonKeys.IS_DEFAULT, false);
+
+ JSONObject from = new JSONObject();
+ from.put(JsonKeys.ID, "from_id");
+ from.put(JsonKeys.NAME, "from_name");
+
+ calendar.put(JsonKeys.FROM, from);
+ calendar.put(JsonKeys.SUBSCRIPTION_LOCATION, JSONObject.NULL);
+ calendar.put(JsonKeys.CREATED_TIME, "2011-12-10T02:48:33+0000");
+ calendar.put(JsonKeys.UPDATED_TIME, "2011-12-10T02:48:33+0000");
+
+ byte[] bytes = calendar.toString().getBytes();
+ this.mockEntity.setInputStream(new ByteArrayInputStream(bytes));
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ this.calendarId = "calendar.123131";
+ }
+}
View
363 unittest/src/com/microsoft/live/unittest/UploadTest.java
@@ -0,0 +1,363 @@
+package com.microsoft.live.unittest;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.InputStream;
+import java.util.concurrent.LinkedBlockingQueue;
+
+import org.apache.http.HttpResponse;
+import org.apache.http.HttpStatus;
+import org.apache.http.HttpVersion;
+import org.apache.http.StatusLine;
+import org.apache.http.client.methods.HttpPut;
+import org.apache.http.message.BasicStatusLine;
+import org.json.JSONObject;
+
+import android.text.TextUtils;
+
+import com.microsoft.live.LiveOperation;
+import com.microsoft.live.LiveOperationException;
+import com.microsoft.live.LiveUploadOperationListener;
+import com.microsoft.live.OverwriteOption;
+import com.microsoft.live.constants.JsonKeys;
+import com.microsoft.live.constants.Paths;
+import com.microsoft.live.mock.MockHttpEntity;
+import com.microsoft.live.mock.MockHttpResponse;
+import com.microsoft.live.test.util.UploadAsyncRunnable;
+import com.microsoft.live.test.util.UploadOperationQueueingListener;
+import com.microsoft.live.util.NullLiveUploadOperationListener;
+
+public class UploadTest extends ApiTest<LiveOperation, LiveUploadOperationListener> {
+
+ private static final String SOURCE = "http://download.location.com/some/path";
+ private static final InputStream FILE;
+ private static final String FILE_ID = "file.1231";
+ private static final String FILENAME = "some_file.txt";
+
+ static {
+ FILE = new ByteArrayInputStream("File contents".getBytes());
+ }
+
+
+ public void testAsyncFileNull() {
+ try {
+ this.liveConnectClient.uploadAsync(Paths.ME_SKYDRIVE,
+ null,
+ FILE,
+ NullLiveUploadOperationListener.INSTANCE);
+ this.failNoNullPointerExceptionThrown();
+ } catch (NullPointerException e) {
+ assertNotNull(e.getMessage());
+ }
+ }
+
+ public void testAsyncFilenameNull() {
+ try {
+ this.liveConnectClient.uploadAsync(Paths.ME_SKYDRIVE,
+ FILENAME,
+ (InputStream)null,
+ NullLiveUploadOperationListener.INSTANCE);
+ this.failNoNullPointerExceptionThrown();
+ } catch (NullPointerException e) {
+ assertNotNull(e.getMessage());
+ }
+
+ try {
+ this.liveConnectClient.uploadAsync(Paths.ME_SKYDRIVE,
+ FILENAME,
+ (File)null,
+ NullLiveUploadOperationListener.INSTANCE);
+ this.failNoNullPointerExceptionThrown();
+ } catch (NullPointerException e) {
+ assertNotNull(e.getMessage());
+ }
+ }
+
+ @Override
+ public void testAsyncResponseBodyInvalid() throws Throwable {
+ this.loadInvalidResponseBody();
+
+ String requestPath = Paths.ME_SKYDRIVE;
+ this.runTestOnUiThread(createAsyncRunnable(requestPath, FILENAME, FILE));
+
+ LiveOperation fromMethod = this.responseQueue.take();
+ LiveOperation fromCallback = this.pollResponseQueue();
+ LiveOperationException exception = this.pollExceptionQueue();
+
+ this.checkReturnedException(fromMethod, fromCallback, exception);
+ this.checkOperationMembers(fromMethod, getMethod(), requestPath);
+ this.checkResponseBodyInvalid(fromMethod);
+ }
+
+ @Override
+ public void testAsyncResponseBodyValid() throws Throwable {
+ this.loadUploadLocationResponseBody();
+ this.loadValidResponseBody();
+
+ String requestPath = Paths.ME_SKYDRIVE;
+
+ this.runTestOnUiThread(createAsyncRunnable(requestPath, FILENAME, FILE));
+
+ LiveOperation fromMethod = this.responseQueue.take();
+ LiveOperation fromCallback = this.pollResponseQueue();
+
+ this.checkReturnedOperations(fromMethod, fromCallback);
+ this.checkOperationMembers(fromMethod, getMethod(), requestPath);
+ this.checkValidResponseBody(fromMethod);
+ }
+
+ @Override
+ public void testAsyncResponseBodyValidWithUserState() throws Throwable {
+ this.loadUploadLocationResponseBody();
+ this.loadValidResponseBody();
+
+ String requestPath = Paths.ME_SKYDRIVE;
+ Object userState = new Object();
+
+ this.runTestOnUiThread(createAsyncRunnable(requestPath, FILENAME, FILE, userState));
+
+ LiveOperation fromMethod = this.responseQueue.take();
+ LiveOperation fromCallback = this.pollResponseQueue();
+
+ this.checkReturnedOperations(fromMethod, fromCallback);
+ this.checkOperationMembers(fromMethod, getMethod(), requestPath, userState);
+ this.checkValidResponseBody(fromMethod);
+ }
+
+ public void testAsyncResponseBodyValidWithOverwrite() throws Throwable {
+ this.loadUploadLocationResponseBody();
+ this.loadValidResponseBody();
+
+ String requestPath = Paths.ME_SKYDRIVE;
+ Object userState = new Object();
+
+ this.runTestOnUiThread(createAsyncRunnable(
+ requestPath,
+ FILENAME,
+ OverwriteOption.Overwrite,
+ FILE,
+ userState));
+
+ LiveOperation fromMethod = this.responseQueue.take();
+ LiveOperation fromCallback = this.pollResponseQueue();
+
+ this.checkReturnedOperations(fromMethod, fromCallback);
+ this.checkOperationMembers(fromMethod, getMethod(), requestPath, userState);
+ this.checkValidResponseBody(fromMethod);
+ }
+
+ public void testSyncFileNull() throws Exception {
+ try {
+ this.liveConnectClient.upload(Paths.ME_SKYDRIVE, FILENAME, (InputStream)null);
+ this.failNoNullPointerExceptionThrown();
+ } catch (NullPointerException e) {
+ assertNotNull(e.getMessage());
+ }
+
+ try {
+ this.liveConnectClient.upload(Paths.ME_SKYDRIVE, FILENAME, (File)null);
+ this.failNoNullPointerExceptionThrown();
+ } catch (NullPointerException e) {
+ assertNotNull(e.getMessage());
+ }
+ }
+
+ public void testSyncFilenameNull() throws Exception {
+ try {
+ this.liveConnectClient.upload(Paths.ME_SKYDRIVE, null, FILE);
+ this.failNoNullPointerExceptionThrown();
+ } catch (NullPointerException e) {
+ assertNotNull(e.getMessage());
+ }
+ }
+
+ @Override
+ public void testSyncResponseBodyInvalid() throws Exception {
+ this.loadInvalidResponseBody();
+
+ String requestPath = Paths.ME_SKYDRIVE;
+
+ try {
+ this.liveConnectClient.upload(requestPath, FILENAME, FILE);
+ this.failNoLiveOperationExceptionThrown();
+ } catch (LiveOperationException e) {
+ assertFalse(TextUtils.isEmpty(e.getMessage()));
+ }
+ }
+
+ public void testSyncResponseBodyInvalidWithOverwrite() throws Exception {
+ this.loadInvalidResponseBody();
+
+ String requestPath = Paths.ME_SKYDRIVE;
+
+ try {
+ this.liveConnectClient.upload(requestPath, FILENAME, FILE, OverwriteOption.Overwrite);
+ this.failNoLiveOperationExceptionThrown();
+ } catch (LiveOperationException e) {
+ assertFalse(TextUtils.isEmpty(e.getMessage()));
+ }
+ }
+
+ @Override
+ public void testSyncResponseBodyValid() throws Exception {
+ this.loadUploadLocationResponseBody();
+ this.loadValidResponseBody();
+
+ String requestPath = Paths.ME_SKYDRIVE;
+
+ LiveOperation operation = this.liveConnectClient.upload(requestPath, FILENAME, FILE);
+
+ this.checkOperationMembers(operation, getMethod(), requestPath);
+ this.checkValidResponseBody(operation);
+ }
+
+ public void testSyncResponseBodyValidWithOverwrite() throws Exception {
+ this.loadUploadLocationResponseBody();
+ this.loadValidResponseBody();
+
+ String requestPath = Paths.ME_SKYDRIVE;
+
+ LiveOperation operation = this.liveConnectClient.upload(
+ requestPath,
+ FILENAME,
+ FILE,
+ OverwriteOption.Overwrite);
+
+ this.checkOperationMembers(operation, getMethod(), requestPath);
+ this.checkValidResponseBody(operation);
+ }
+
+ @Override
+ protected void checkValidResponseBody(LiveOperation operation) throws Exception {
+ JSONObject result = operation.getResult();
+
+ assertEquals(2, result.length());
+
+ String id = result.getString(JsonKeys.ID);
+ assertEquals(FILE_ID, id);
+
+ String source = result.getString(JsonKeys.SOURCE);
+ assertEquals(SOURCE, source);
+ }
+
+ protected UploadAsyncRunnable createAsyncRunnable(String requestPath,
+ String filename,
+ InputStream file) {
+ return new UploadAsyncRunnable(this.responseQueue,
+ this.liveConnectClient,
+ requestPath,
+ filename,
+ file,
+ this.queueingListener);
+ }
+
+ protected UploadAsyncRunnable createAsyncRunnable(String requestPath,
+ String filename,
+ InputStream file,
+ Object userState) {
+ return new UploadAsyncRunnable(this.responseQueue,
+ this.liveConnectClient,
+ requestPath,
+ filename,
+ file,
+ this.queueingListener,
+ userState);
+ }
+
+ protected UploadAsyncRunnable createAsyncRunnable(String requestPath,
+ String filename,
+ OverwriteOption overwrite,
+ InputStream file,
+ Object userState) {
+ return new UploadAsyncRunnable(this.responseQueue,
+ this.liveConnectClient,
+ requestPath,
+ filename,
+ overwrite,
+ file,
+ this.queueingListener,
+ userState);
+ }
+
+ @Override
+ protected final UploadAsyncRunnable createAsyncRunnable(String requestPath) {
+ throw new UnsupportedOperationException("Unable to create UploadAsyncRunnable from only " +
+ "a requestPath");
+ }
+
+ @Override
+ protected final UploadAsyncRunnable createAsyncRunnable(String requestPath, Object userState) {
+ throw new UnsupportedOperationException("Unable to create UploadAsyncRunnable from only " +
+ "a requestPath and an userState");
+ }
+
+ @Override
+ protected void loadInvalidResponseBody() throws Exception {
+ super.loadInvalidResponseBody();
+
+ HttpResponse invalidResponse = this.mockClient.getHttpResponse();
+
+ this.mockClient.clearHttpResponseQueue();
+ this.loadUploadLocationResponseBody();
+ this.mockClient.addHttpResponse(invalidResponse);
+ }
+
+ @Override
+ protected void loadPathInvalidResponse(String requestPath) throws Exception {
+ super.loadPathInvalidResponse(requestPath);
+
+ // we have to load the uploadLocationResponse first
+ // so store the invalidResponse and load it in again after the uploadlocation
+ // has been added.
+ HttpResponse invalidResponse = this.mockClient.getHttpResponse();
+
+ this.mockClient.clearHttpResponseQueue();
+ this.loadUploadLocationResponseBody();
+ this.mockClient.addHttpResponse(invalidResponse);
+ }
+
+ @Override
+ protected void loadValidResponseBody() throws Exception {
+ JSONObject jsonResponseBody = new JSONObject();
+ jsonResponseBody.put(JsonKeys.ID, FILE_ID);
+ jsonResponseBody.put(JsonKeys.SOURCE, SOURCE);
+
+ InputStream responseStream =
+ new ByteArrayInputStream(jsonResponseBody.toString().getBytes());
+ MockHttpEntity responseEntity = new MockHttpEntity(responseStream);
+ StatusLine created = new BasicStatusLine(HttpVersion.HTTP_1_1, HttpStatus.SC_CREATED, "");
+ MockHttpResponse response = new MockHttpResponse(responseEntity, created);
+
+ this.mockClient.addHttpResponse(response);
+ }
+
+ protected void loadUploadLocationResponseBody() throws Exception {
+ /* create folder response */
+ JSONObject folder = new JSONObject();
+ folder.put(JsonKeys.UPLOAD_LOCATION, "https://upload.location.com/some/path");
+
+ InputStream uploadLocationStream =
+ new ByteArrayInputStream(folder.toString().getBytes());
+ MockHttpEntity uploadLocationEntity = new MockHttpEntity(uploadLocationStream);
+ StatusLine ok = new BasicStatusLine(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "");
+ MockHttpResponse uploadLocationResponse = new MockHttpResponse(uploadLocationEntity, ok);
+ this.mockClient.setHttpResponse(uploadLocationResponse);
+ }
+
+ @Override
+ protected String getMethod() {
+ return HttpPut.METHOD_NAME;
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ // some upload requests perform two http requests, so clear any responses that may have
+ // been entered already. each test here is responsible for loading 1 or two responses.
+ this.mockClient.clearHttpResponseQueue();
+ this.responseQueue = new LinkedBlockingQueue<LiveOperation>();
+ this.queueingListener = new UploadOperationQueueingListener(this.exceptionQueue,
+ this.responseQueue);
+ }
+}
View
8 utilities/.classpath
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="src" path="gen"/>
+ <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
+ <classpathentry kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
+ <classpathentry kind="output" path="bin/classes"/>
+</classpath>
View
33 utilities/.project
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>LiveSdkUtilities</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>com.android.ide.eclipse.adt.ApkBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>com.android.ide.eclipse.adt.AndroidNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
View
9 utilities/AndroidManifest.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.microsoft.live.util"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk android:minSdkVersion="8" />
+
+</manifest>
View
90 utilities/build.xml
@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project name="LiveSdkUtilities" default="help">
+
+ <!-- build.properties has the sdk.dir.
+ Must load environment variables before including it. -->
+ <property environment="env" />
+ <property file="../build.properties" />
+
+ <!-- The local.properties file is created and updated by the 'android' tool.
+ It contains the path to the SDK. It should *NOT* be checked into
+ Version Control Systems. -->
+ <property file="local.properties" />
+
+ <!-- The ant.properties file can be created by you. It is only edited by the
+ 'android' tool to add properties to it.
+ This is the place to change some Ant specific build properties.