// Path: core/src/main/java/org/codeandmagic/promise/Callback.java
// public interface Callback<T> {
// 
//     void onCallback(final T result);
// }
// 
// Path: core/src/main/java/org/codeandmagic/promise/Transformation.java
// public interface Transformation<T1, T2> {
// 
//     T2 transform(T1 value);
// 
// }
// 
// Path: sample/src/main/java/org/codeandmagic/promise/sample/PlanetsActivity.java
// public class PlanetsActivity extends ActionBarActivity {
// 
//     private final static String EARTH = "https://farm3.staticflickr.com/2116/2222523978_f48bf28571_o.jpg";
//     private final static String MARS = "https://farm6.staticflickr.com/5328/6897598788_a748a78bb8_o.png";
//     private final static String VENUS = "https://farm8.staticflickr.com/7233/7302574832_ed3fa543b2_o.jpg";
// 
//     private TextView mProgress1, mProgress2, mProgress3, mLog;
//     private Button mStart;
// 
//     @Override
//     public void onCreate(Bundle savedInstanceState) {
//         super.onCreate(savedInstanceState);
//         setContentView(R.layout.planets_activity);
// 
//         mLog = (TextView) findViewById(R.id.log);
// 
//         mProgress1 = (TextView) findViewById(R.id.progress1);
//         mProgress2 = (TextView) findViewById(R.id.progress2);
//         mProgress3 = (TextView) findViewById(R.id.progress3);
// 
//         mStart = (Button) findViewById(R.id.start);
//         mStart.setOnClickListener(new View.OnClickListener() {
//             @Override
//             public void onClick(View v) {
//                 startTasks();
//             }
//         });
//     }
// 
//     private void startTasks() {
//         final Promise<File> promise1 = createPromise(EARTH, "Earth", mProgress1);
//         final Promise<File> promise2 = createPromise(MARS, "Mars", mProgress2);
//         final Promise<File> promise3 = createPromise(VENUS, "Venus", mProgress3);
// 
//         DeferredObject.merge(File.class, promise1, promise2, promise3)
//             .runOnUiThread()
//             .onSuccess(new Callback<File[]>() {
//                 @Override
//                 public void onCallback(File[] result) {
//                     mStart.setText(R.string.all_done);
//                     mStart.setEnabled(true);
//                     reset(mProgress1, mProgress2, mProgress3);
//                 }
//             })
//             .onFailure(new Callback<Throwable>() {
//                 @Override
//                 public void onCallback(Throwable result) {
//                     mStart.setText(R.string.failure);
//                     mStart.setEnabled(true);
//                 }
//             })
//             .onProgress(new Callback<Float>() {
//                 @Override
//                 public void onCallback(Float result) {
//                     mLog.append(" (" + result + " out of 3)");
//                 }
//             });
// 
//     }
// 
//     private void done(TextView progress) {
//         progress.getCompoundDrawables()[1].setLevel(1);
//     }
// 
//     private void reset(TextView... progress) {
//         for (TextView p : progress) {
//             p.getCompoundDrawables()[1].setLevel(0);
//             p.setText(R.string.no_progress);
//         }
//     }
// 
//     private Promise<File> createPromise(String url, String fileName, TextView progress) {
//         try {
//             return new DownloadPromise(new URL(url), getSdCardFile(fileName))
//                 .runOnUiThread()
//                 .onSuccess(successCallback(progress))
//                 .onFailure(failureCallback(url))
//                 .onProgress(TextViewUtils.setPercent(progress));
//         } catch (IOException e) {
//             mLog.setText("Can't mStart download " + url + " due to exception: " + e.getMessage());
//             return null;
//         }
//     }
// 
//     private Callback<File> successCallback(final TextView textView) {
//         return new Callback<File>() {
//             @Override
//             public void onCallback(File result) {
//                 mLog.append("\nFile stored in " + result.getPath());
//                 done(textView);
//             }
//         };
//     }
// 
//     private Callback<Throwable> failureCallback(final String fileName) {
//         return new Callback<Throwable>() {
//             @Override
//             public void onCallback(Throwable e) {
//                 mLog.append("\nFailed " + fileName + " because " + e.getClass().getName() + " " + e.getMessage());
//             }
//         };
//     }
// }


import android.test.ActivityInstrumentationTestCase2;
import com.android.volley.Request.Method;
import com.android.volley.RequestQueue;
import com.android.volley.toolbox.Volley;
import org.codeandmagic.promise.Callback;
import org.codeandmagic.promise.Transformation;
import org.codeandmagic.promise.sample.PlanetsActivity;
import org.codeandmagic.promise.volley.VolleyJsonPromise;
import org.codeandmagic.promise.volley.VolleyRequest.RObject;
import org.json.JSONObject;
import static org.mockito.Mockito.*;

        verify(successCallback, times(2)).onCallback(any(JSONObject.class));
        verify(failureCallback, never()).onCallback(any(Throwable.class));
    }

    public void testFailedRequest() {
        Callback<JSONObject> successCallback = mock(Callback.class);
        Callback<Throwable> failureCallback = mock(Callback.class);

        RequestQueue queue = Volley.newRequestQueue(getActivity().getApplicationContext());
        VolleyJsonPromise.jsonObjectPromise(queue, Method.GET, FAILURE_URL, null)
                .onSuccess(successCallback)
                .onFailure(failureCallback);

        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        verify(successCallback, never()).onCallback(any(JSONObject.class));
        verify(failureCallback, only()).onCallback(any(Throwable.class));
    }

    public void testExtendedRequest() {
        Callback<JSONObject> successCallback = mock(Callback.class);
        Callback<Throwable> failureCallback = mock(Callback.class);

        RequestQueue queue = Volley.newRequestQueue(getActivity().getApplicationContext());
        VolleyJsonPromise.jsonObjectPromise(Method.GET, SUCCESS_URL, null)
// Path: core/src/main/java/org/codeandmagic/promise/Callback.java
// public interface Callback<T> {
// 
//     void onCallback(final T result);
// }
// 
// Path: core/src/main/java/org/codeandmagic/promise/Transformation.java
// public interface Transformation<T1, T2> {
// 
//     T2 transform(T1 value);
// 
// }
// 
// Path: sample/src/main/java/org/codeandmagic/promise/sample/PlanetsActivity.java
// public class PlanetsActivity extends ActionBarActivity {
// 
//     private final static String EARTH = "https://farm3.staticflickr.com/2116/2222523978_f48bf28571_o.jpg";
//     private final static String MARS = "https://farm6.staticflickr.com/5328/6897598788_a748a78bb8_o.png";
//     private final static String VENUS = "https://farm8.staticflickr.com/7233/7302574832_ed3fa543b2_o.jpg";
// 
//     private TextView mProgress1, mProgress2, mProgress3, mLog;
//     private Button mStart;
// 
//     @Override
//     public void onCreate(Bundle savedInstanceState) {
//         super.onCreate(savedInstanceState);
//         setContentView(R.layout.planets_activity);
// 
//         mLog = (TextView) findViewById(R.id.log);
// 
//         mProgress1 = (TextView) findViewById(R.id.progress1);
//         mProgress2 = (TextView) findViewById(R.id.progress2);
//         mProgress3 = (TextView) findViewById(R.id.progress3);
// 
//         mStart = (Button) findViewById(R.id.start);
//         mStart.setOnClickListener(new View.OnClickListener() {
//             @Override
//             public void onClick(View v) {
//                 startTasks();
//             }
//         });
//     }
// 
//     private void startTasks() {
//         final Promise<File> promise1 = createPromise(EARTH, "Earth", mProgress1);
//         final Promise<File> promise2 = createPromise(MARS, "Mars", mProgress2);
//         final Promise<File> promise3 = createPromise(VENUS, "Venus", mProgress3);
// 
//         DeferredObject.merge(File.class, promise1, promise2, promise3)
//             .runOnUiThread()
//             .onSuccess(new Callback<File[]>() {
//                 @Override
//                 public void onCallback(File[] result) {
//                     mStart.setText(R.string.all_done);
//                     mStart.setEnabled(true);
//                     reset(mProgress1, mProgress2, mProgress3);
//                 }
//             })
//             .onFailure(new Callback<Throwable>() {
//                 @Override
//                 public void onCallback(Throwable result) {
//                     mStart.setText(R.string.failure);
//                     mStart.setEnabled(true);
//                 }
//             })
//             .onProgress(new Callback<Float>() {
//                 @Override
//                 public void onCallback(Float result) {
//                     mLog.append(" (" + result + " out of 3)");
//                 }
//             });
// 
//     }
// 
//     private void done(TextView progress) {
//         progress.getCompoundDrawables()[1].setLevel(1);
//     }
// 
//     private void reset(TextView... progress) {
//         for (TextView p : progress) {
//             p.getCompoundDrawables()[1].setLevel(0);
//             p.setText(R.string.no_progress);
//         }
//     }
// 
//     private Promise<File> createPromise(String url, String fileName, TextView progress) {
//         try {
//             return new DownloadPromise(new URL(url), getSdCardFile(fileName))
//                 .runOnUiThread()
//                 .onSuccess(successCallback(progress))
//                 .onFailure(failureCallback(url))
//                 .onProgress(TextViewUtils.setPercent(progress));
//         } catch (IOException e) {
//             mLog.setText("Can't mStart download " + url + " due to exception: " + e.getMessage());
//             return null;
//         }
//     }
// 
//     private Callback<File> successCallback(final TextView textView) {
//         return new Callback<File>() {
//             @Override
//             public void onCallback(File result) {
//                 mLog.append("\nFile stored in " + result.getPath());
//                 done(textView);
//             }
//         };
//     }
// 
//     private Callback<Throwable> failureCallback(final String fileName) {
//         return new Callback<Throwable>() {
//             @Override
//             public void onCallback(Throwable e) {
//                 mLog.append("\nFailed " + fileName + " because " + e.getClass().getName() + " " + e.getMessage());
//             }
//         };
//     }
// }


// Path: sample/src/instrumentTest/java/org/codeandmagic/promise/volley/tests/VolleyJsonObjectTests.java
import android.test.ActivityInstrumentationTestCase2;
import com.android.volley.Request.Method;
import com.android.volley.RequestQueue;
import com.android.volley.toolbox.Volley;
import org.codeandmagic.promise.Callback;
import org.codeandmagic.promise.Transformation;
import org.codeandmagic.promise.sample.PlanetsActivity;
import org.codeandmagic.promise.volley.VolleyJsonPromise;
import org.codeandmagic.promise.volley.VolleyRequest.RObject;
import org.json.JSONObject;
import static org.mockito.Mockito.*;


        verify(successCallback, times(2)).onCallback(any(JSONObject.class));
        verify(failureCallback, never()).onCallback(any(Throwable.class));
    }

    public void testFailedRequest() {
        Callback<JSONObject> successCallback = mock(Callback.class);
        Callback<Throwable> failureCallback = mock(Callback.class);

        RequestQueue queue = Volley.newRequestQueue(getActivity().getApplicationContext());
        VolleyJsonPromise.jsonObjectPromise(queue, Method.GET, FAILURE_URL, null)
                .onSuccess(successCallback)
                .onFailure(failureCallback);

        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        verify(successCallback, never()).onCallback(any(JSONObject.class));
        verify(failureCallback, only()).onCallback(any(Throwable.class));
    }

    public void testExtendedRequest() {
        Callback<JSONObject> successCallback = mock(Callback.class);
        Callback<Throwable> failureCallback = mock(Callback.class);

        RequestQueue queue = Volley.newRequestQueue(getActivity().getApplicationContext());
        VolleyJsonPromise.jsonObjectPromise(Method.GET, SUCCESS_URL, null)
                .map(new Transformation<RObject, RObject>() {