entry = iterator.next();
+ invokeAction(entry.getKey(), entry.getValue(), false);
+ iterator.remove();
+ }
+ }
+ }
+
/**
* Clear the initiated DeployGate instance.
*
@@ -1191,7 +1273,7 @@ public static void installUpdate() {
return;
}
- sInstance.invokeAction(DeployGateEvent.ACTION_INSTALL_UPDATE, null);
+ sInstance.invokeAction(DeployGateEvent.ACTION_INSTALL_UPDATE, null, false);
}
/**
@@ -1207,7 +1289,7 @@ public static void openComments() {
return;
}
- sInstance.invokeAction(DeployGateEvent.ACTION_OPEN_COMMENTS, null);
+ sInstance.invokeAction(DeployGateEvent.ACTION_OPEN_COMMENTS, null, false);
}
/**
@@ -1240,7 +1322,7 @@ public static void composeComment(String defaultComment) {
Bundle extras = new Bundle();
extras.putString(DeployGateEvent.EXTRA_COMMENT, defaultComment);
- sInstance.invokeAction(DeployGateEvent.ACTION_COMPOSE_COMMENT, extras);
+ sInstance.invokeAction(DeployGateEvent.ACTION_COMPOSE_COMMENT, extras, false);
}
/**
diff --git a/sdk/src/main/java/com/deploygate/sdk/ILogcatInstructionSerializer.java b/sdk/src/main/java/com/deploygate/sdk/ILogcatInstructionSerializer.java
index c348ba5..2302724 100644
--- a/sdk/src/main/java/com/deploygate/sdk/ILogcatInstructionSerializer.java
+++ b/sdk/src/main/java/com/deploygate/sdk/ILogcatInstructionSerializer.java
@@ -20,8 +20,11 @@ interface ILogcatInstructionSerializer {
/**
* Create and enqueue a request to start sending oneshot logcat
+ *
+ * @param captureId
+ * this is nullable. Set to non-null if this logcat is for a capture.
*/
- boolean requestOneshotLogcat();
+ boolean requestOneshotLogcat(String captureId);
/**
* Create and enqueue a request to start sending streamed logcat
@@ -56,8 +59,8 @@ public void disconnect() {
}
@Override
- public boolean requestOneshotLogcat() {
- Logger.d("Logcat (no-op): requestOneshotLogcat");
+ public boolean requestOneshotLogcat(String captureId) {
+ Logger.d("Logcat (no-op): requestOneshotLogcat(%s)", captureId != null ? captureId : "null");
return false;
}
diff --git a/sdk/src/main/java/com/deploygate/sdk/LogcatInstructionSerializer.java b/sdk/src/main/java/com/deploygate/sdk/LogcatInstructionSerializer.java
index c81ed6e..fd4dc45 100644
--- a/sdk/src/main/java/com/deploygate/sdk/LogcatInstructionSerializer.java
+++ b/sdk/src/main/java/com/deploygate/sdk/LogcatInstructionSerializer.java
@@ -67,21 +67,25 @@ class LogcatInstructionSerializer implements ILogcatInstructionSerializer {
this.logcatProcess = new LogcatProcess(new LogcatProcess.Callback() {
@Override
public void onStarted(String processId) {
+ //noinspection ConstantConditions
handler.enqueueSendLogcatMessageInstruction(SendLogcatRequest.createBeginning(processId));
}
@Override
public void emit(
String processId,
- ArrayList logcatLines
+ ArrayList logcatLines,
+ String captureId
) {
ensureHandlerPrepared();
- handler.enqueueSendLogcatMessageInstruction(new SendLogcatRequest(processId, logcatLines));
+ //noinspection ConstantConditions
+ handler.enqueueSendLogcatMessageInstruction(new SendLogcatRequest(processId, logcatLines, captureId));
}
@Override
public void onFinished(String processId) {
+ //noinspection ConstantConditions
handler.enqueueSendLogcatMessageInstruction(SendLogcatRequest.createTermination(processId));
}
});
@@ -91,6 +95,7 @@ public void onFinished(String processId) {
@Override
public final synchronized void connect(IDeployGateSdkService service) {
+ //noinspection ConstantConditions
if (service == null) {
throw new IllegalArgumentException("service must not be null");
}
@@ -107,8 +112,8 @@ public final void disconnect() {
}
@Override
- public final synchronized boolean requestOneshotLogcat() {
- return requestLogcat(null);
+ public final synchronized boolean requestOneshotLogcat(String captureId) {
+ return requestLogcat(null, captureId);
}
@Override
@@ -136,7 +141,10 @@ public final void setEnabled(boolean enabled) {
public final void stopStream() {
ensureHandlerPrepared();
- logcatProcess.stop();
+ if (logcatProcess != null) {
+ logcatProcess.stop();
+ }
+ //noinspection ConstantConditions
handler.cancelPendingSendLogcatInstruction();
}
@@ -216,13 +224,28 @@ int sendSingleChunk(
* @return true if new process has lauched
*/
private boolean requestLogcat(String streamSessionKey) {
+ return requestLogcat(streamSessionKey, null);
+ }
+
+ /**
+ * @param streamSessionKey
+ * nullable. sdk can not generate this key.
+ * @param captureId
+ * nullable.
+ *
+ * @return true if new process has lauched
+ */
+ private boolean requestLogcat(
+ String streamSessionKey,
+ String captureId
+ ) {
ensureHandlerPrepared();
- if (!isEnabled) {
+ if (!isEnabled || logcatProcess == null) {
return false;
}
- Pair ids = logcatProcess.execute(streamSessionKey);
+ Pair ids = logcatProcess.execute(streamSessionKey, captureId);
String retiredId = ids.first;
String newId = ids.second;
@@ -234,6 +257,7 @@ private boolean requestLogcat(String streamSessionKey) {
if (!LogcatProcess.UNKNOWN_PROCESS_ID.equals(retiredId)) {
// the previous on-going execution has been retied
+ //noinspection ConstantConditions
handler.cancelPendingSendLogcatInstruction(retiredId);
}
@@ -287,10 +311,11 @@ private int sendChunkedLogcats(
*/
/**
- * @return the handler instance or null if not prepared.
+ * @return the handler instance
*/
Handler getHandler() {
ensureHandlerPrepared();
+ //noinspection ConstantConditions
return handler;
}
@@ -327,8 +352,6 @@ private static class LogcatHandler extends Handler {
/**
* Cancel the send-logcat instruction of all watchers in the handler message queue.
- *
- * @return true if canceled, otherwise false.
*/
void cancelPendingSendLogcatInstruction() {
synchronized (requestMap) {
@@ -341,8 +364,6 @@ void cancelPendingSendLogcatInstruction() {
/**
* Cancel the send-logcat instruction of the specific watcher in the handler message queue.
- *
- * @return true if canceled, otherwise false.
*/
void cancelPendingSendLogcatInstruction(String bundleId) {
acquireRequests(bundleId);
diff --git a/sdk/src/main/java/com/deploygate/sdk/LogcatProcess.java b/sdk/src/main/java/com/deploygate/sdk/LogcatProcess.java
index 994c9f9..2d272ef 100644
--- a/sdk/src/main/java/com/deploygate/sdk/LogcatProcess.java
+++ b/sdk/src/main/java/com/deploygate/sdk/LogcatProcess.java
@@ -27,7 +27,8 @@ interface Callback {
void emit(
String processId,
- ArrayList logcatLines
+ ArrayList logcatLines,
+ String captureId
);
void onFinished(String processId);
@@ -58,7 +59,8 @@ void emit(
* @return a pair of watcher ids (non-nulls). first is the previous watcher id, second is the new watcher id.
*/
Pair execute(
- @Experimental String streamSessionKey
+ @Experimental String streamSessionKey,
+ String captureId
) {
Pair ids;
@@ -77,7 +79,7 @@ Pair execute(
return Pair.create(currentPid, currentPid);
}
- final LogcatWatcher newWatcher = new LogcatWatcher(streamSessionKey, callback);
+ final LogcatWatcher newWatcher = new LogcatWatcher(streamSessionKey, captureId, callback);
try {
this.latestLogcatWatcher = newWatcher;
@@ -121,16 +123,23 @@ static class LogcatWatcher implements Runnable {
private final String processId;
private final boolean isOneShot;
+ private final String captureId;
private final WeakReference callback;
private final AtomicReference processRef;
private final AtomicInteger state;
LogcatWatcher(
@Experimental String streamSessionKey,
+ String captureId,
Callback callback
) {
+ if (streamSessionKey != null && captureId != null) {
+ throw new IllegalArgumentException("streaming and capture cannot be specified at once");
+ }
+
this.processId = streamSessionKey != null ? streamSessionKey : ClientId.generate();
this.isOneShot = streamSessionKey == null;
+ this.captureId = captureId;
this.callback = new WeakReference<>(callback);
this.processRef = new AtomicReference<>();
this.state = new AtomicInteger(STATE_READY);
@@ -228,10 +237,10 @@ public void run() {
if (isOneShot) {
continue;
} else if (logcatBuf.size() >= MAX_LINES) {
- callback.emit(processId, toArrayList(logcatBuf));
+ callback.emit(processId, toArrayList(logcatBuf), captureId);
logcatBuf = createBuffer(MAX_LINES); // Don't reuse to make sure releasing the reference
} else if (!bufferedReader.ready()) {
- callback.emit(processId, toArrayList(logcatBuf));
+ callback.emit(processId, toArrayList(logcatBuf), captureId);
logcatBuf = createBuffer(MAX_LINES); // Don't reuse to make sure releasing the reference
} else {
continue;
@@ -248,7 +257,7 @@ public void run() {
Callback callback = this.callback.get();
if (callback != null) {
- callback.emit(processId, toArrayList(logcatBuf));
+ callback.emit(processId, toArrayList(logcatBuf), captureId);
}
}
diff --git a/sdk/src/main/java/com/deploygate/sdk/SendLogcatRequest.java b/sdk/src/main/java/com/deploygate/sdk/SendLogcatRequest.java
index 3050348..f0eed77 100644
--- a/sdk/src/main/java/com/deploygate/sdk/SendLogcatRequest.java
+++ b/sdk/src/main/java/com/deploygate/sdk/SendLogcatRequest.java
@@ -31,22 +31,24 @@ private String label() {
}
public static SendLogcatRequest createTermination(String processId) {
- return new SendLogcatRequest(processId, new ArrayList(), Position.Termination);
+ return new SendLogcatRequest(processId, new ArrayList(), Position.Termination, null);
}
public static SendLogcatRequest createBeginning(String processId) {
- return new SendLogcatRequest(processId, new ArrayList(), Position.Beginning);
+ return new SendLogcatRequest(processId, new ArrayList(), Position.Beginning, null);
}
public final ArrayList lines;
public final Position position;
+ public final String captureId;
private int retryCount;
SendLogcatRequest(
String pid,
- List lines
+ List lines,
+ String captureId
) {
- this(pid, lines, Position.Content);
+ this(pid, lines, Position.Content, captureId);
}
/**
@@ -56,15 +58,19 @@ public static SendLogcatRequest createBeginning(String processId) {
* logcat contents if available. Zero value is an empty list.
* @param position
* a position of this request. non-null
+ * @param captureId
+ * the id of the capture. nullable
*/
private SendLogcatRequest(
String pid,
List lines,
- Position position
+ Position position,
+ String captureId
) {
super(pid);
this.lines = lines instanceof ArrayList ? (ArrayList) lines : new ArrayList<>(lines);
this.position = position;
+ this.captureId = captureId;
}
/**
@@ -95,7 +101,7 @@ List splitInto(int count) {
for (int i = 0, offset = 0, step = size / count; i < count; i++, offset += step) {
final int endIndex = (i == count - 1) ? size : offset + step;
- splits.add(new SendLogcatRequest(gid, lines.subList(offset, endIndex), Position.Content));
+ splits.add(new SendLogcatRequest(gid, lines.subList(offset, endIndex), Position.Content, captureId));
}
return splits;
@@ -105,5 +111,8 @@ List splitInto(int count) {
void applyValues(Bundle extras) {
extras.putStringArrayList(DeployGateEvent.EXTRA_LOG, lines);
extras.putString(DeployGateEvent.EXTRA_BUNDLE_POSITION, position.label());
+ if (captureId != null) {
+ extras.putString(DeployGateEvent.EXTRA_CAPTURE_ID, captureId);
+ }
}
}
diff --git a/sdk/src/main/java/com/deploygate/sdk/internal/VisibilityLifecycleCallbacks.java b/sdk/src/main/java/com/deploygate/sdk/internal/VisibilityLifecycleCallbacks.java
new file mode 100644
index 0000000..3a21a56
--- /dev/null
+++ b/sdk/src/main/java/com/deploygate/sdk/internal/VisibilityLifecycleCallbacks.java
@@ -0,0 +1,86 @@
+package com.deploygate.sdk.internal;
+
+import android.app.Activity;
+import android.app.Application;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.SystemClock;
+
+import java.util.concurrent.TimeUnit;
+
+public final class VisibilityLifecycleCallbacks implements Application.ActivityLifecycleCallbacks {
+ public interface OnVisibilityChangeListener {
+ void onForeground(
+ long elapsedRealtime,
+ TimeUnit timeUnit
+ );
+
+ void onBackground(
+ long elapsedRealtime,
+ TimeUnit timeUnit
+ );
+ }
+
+ private int onResumeCount = 0; // this is manipulated from the single thread
+
+ private final OnVisibilityChangeListener listener;
+
+ public VisibilityLifecycleCallbacks(OnVisibilityChangeListener listener) {
+ this.listener = listener;
+ }
+
+ @Override
+ public void onActivityCreated(
+ Activity activity,
+ Bundle savedInstanceState
+ ) {
+ // no-op
+ }
+
+ @Override
+ public void onActivityStarted(Activity activity) {
+ // no-op
+ }
+
+ @Override
+ public void onActivityResumed(Activity activity) {
+ onResumeCount++;
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
+ listener.onForeground(SystemClock.elapsedRealtimeNanos(), TimeUnit.NANOSECONDS);
+ } else {
+ listener.onForeground(SystemClock.elapsedRealtime(), TimeUnit.MILLISECONDS);
+ }
+ }
+
+ @Override
+ public void onActivityPaused(Activity activity) {
+ onResumeCount = Math.max(onResumeCount - 1, 0); // cuz uint is unavailable.
+
+ if (onResumeCount == 0) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
+ listener.onBackground(SystemClock.elapsedRealtimeNanos(), TimeUnit.NANOSECONDS);
+ } else {
+ listener.onBackground(SystemClock.elapsedRealtime(), TimeUnit.MILLISECONDS);
+ }
+ }
+ }
+
+ @Override
+ public void onActivityStopped(Activity activity) {
+ // no-op
+ }
+
+ @Override
+ public void onActivitySaveInstanceState(
+ Activity activity,
+ Bundle outState
+ ) {
+ // no-op
+ }
+
+ @Override
+ public void onActivityDestroyed(Activity activity) {
+ // no-op
+ }
+}
diff --git a/sdk/src/main/java/com/deploygate/service/DeployGateEvent.java b/sdk/src/main/java/com/deploygate/service/DeployGateEvent.java
index d0d29dd..f188c50 100644
--- a/sdk/src/main/java/com/deploygate/service/DeployGateEvent.java
+++ b/sdk/src/main/java/com/deploygate/service/DeployGateEvent.java
@@ -25,6 +25,7 @@ public interface DeployGateEvent {
public static final String ACTION_OPEN_APP_DETAIL = "openAppDetail";
public static final String ACTION_OPEN_COMMENTS = "openComments";
public static final String ACTION_COMPOSE_COMMENT = "composeComment";
+ public static final String ACTION_VISIBILITY_EVENT = "a.visibility-event";
public static final String EXTRA_AUTHOR = "author";
public static final String EXTRA_EXPECTED_AUTHOR = "expectedAuthor";
@@ -85,4 +86,25 @@ public interface DeployGateEvent {
public static final String EXTRA_DEPLOYGATE_VERSION_CODE = "deploygateVersionCode";
public static final String EXTRA_COMMENT = "comment";
public static final String EXTRA_DISTRIBUTION_USER_NAME = "distributionUserName";
+
+ /**
+ * the id of the capture.
+ */
+ public static final String EXTRA_CAPTURE_ID = "e.capture-id";
+
+ /**
+ * A event type for the app goes to foreground/background.
+ */
+ public static final String EXTRA_VISIBILITY_EVENT_TYPE = "e.visibility-event-type";
+
+ /**
+ * The elapsed real time since boot at the time when the app goes to foreground/background.
+ * this value must be nano times.
+ */
+ public static final String EXTRA_VISIBILITY_EVENT_ELAPSED_REAL_TIME_IN_NANOS = "e.visibility-event-elapsed-real-time";
+
+ interface VisibilityType {
+ int BACKGROUND = 0;
+ int FOREGROUND = 1;
+ }
}
diff --git a/sdk/src/test/java/com/deploygate/sdk/CustomLogInstructionSerializerTest.java b/sdk/src/test/java/com/deploygate/sdk/CustomLogInstructionSerializerTest.java
index 0c555fc..7bb8228 100644
--- a/sdk/src/test/java/com/deploygate/sdk/CustomLogInstructionSerializerTest.java
+++ b/sdk/src/test/java/com/deploygate/sdk/CustomLogInstructionSerializerTest.java
@@ -1,5 +1,15 @@
package com.deploygate.sdk;
+import static com.deploygate.sdk.mockito.BundleMatcher.eq;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.robolectric.annotation.LooperMode.Mode.PAUSED;
+
import android.os.Bundle;
import android.os.DeadObjectException;
import android.os.RemoteException;
@@ -26,16 +36,6 @@
import java.util.List;
import java.util.concurrent.TimeUnit;
-import static com.deploygate.sdk.mockito.BundleMatcher.eq;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.doThrow;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.times;
-import static org.robolectric.annotation.LooperMode.Mode.PAUSED;
-
@RunWith(AndroidJUnit4.class)
@LooperMode(PAUSED)
public class CustomLogInstructionSerializerTest {
diff --git a/sdk/src/test/java/com/deploygate/sdk/DeployGateClientTest.java b/sdk/src/test/java/com/deploygate/sdk/DeployGateClientTest.java
index ccea880..fb4d016 100644
--- a/sdk/src/test/java/com/deploygate/sdk/DeployGateClientTest.java
+++ b/sdk/src/test/java/com/deploygate/sdk/DeployGateClientTest.java
@@ -1,5 +1,7 @@
package com.deploygate.sdk;
+import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
+
import android.app.Application;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
@@ -21,8 +23,6 @@
import org.robolectric.Shadows;
import org.robolectric.shadows.ShadowPackageManager;
-import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
-
@RunWith(AndroidJUnit4.class)
public class DeployGateClientTest {
@NonNull
diff --git a/sdk/src/test/java/com/deploygate/sdk/DeployGateInterfaceTest.java b/sdk/src/test/java/com/deploygate/sdk/DeployGateInterfaceTest.java
index e2349f9..e5d4e15 100644
--- a/sdk/src/test/java/com/deploygate/sdk/DeployGateInterfaceTest.java
+++ b/sdk/src/test/java/com/deploygate/sdk/DeployGateInterfaceTest.java
@@ -1,5 +1,7 @@
package com.deploygate.sdk;
+import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
+
import android.app.Application;
import androidx.annotation.NonNull;
@@ -11,8 +13,6 @@
import org.junit.Test;
import org.junit.runner.RunWith;
-import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
-
/**
* This test class will make sure all *public* interfaces are defined as expected
diff --git a/sdk/src/test/java/com/deploygate/sdk/HostAppTest.java b/sdk/src/test/java/com/deploygate/sdk/HostAppTest.java
index 4686656..afc8e39 100644
--- a/sdk/src/test/java/com/deploygate/sdk/HostAppTest.java
+++ b/sdk/src/test/java/com/deploygate/sdk/HostAppTest.java
@@ -1,5 +1,7 @@
package com.deploygate.sdk;
+import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
+
import android.content.Context;
import androidx.annotation.NonNull;
@@ -12,8 +14,6 @@
import org.junit.runner.RunWith;
import org.robolectric.annotation.Config;
-import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
-
@RunWith(AndroidJUnit4.class)
public class HostAppTest {
@NonNull
diff --git a/sdk/src/test/java/com/deploygate/sdk/LogcatInstructionSerializerTest.java b/sdk/src/test/java/com/deploygate/sdk/LogcatInstructionSerializerTest.java
index 1d6667d..25a99d0 100644
--- a/sdk/src/test/java/com/deploygate/sdk/LogcatInstructionSerializerTest.java
+++ b/sdk/src/test/java/com/deploygate/sdk/LogcatInstructionSerializerTest.java
@@ -1,5 +1,15 @@
package com.deploygate.sdk;
+import static com.deploygate.sdk.mockito.BundleMatcher.eq;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.mockStatic;
+import static org.robolectric.annotation.LooperMode.Mode.PAUSED;
+
import android.os.Bundle;
import android.os.RemoteException;
import android.os.TransactionTooLargeException;
@@ -7,7 +17,6 @@
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.deploygate.sdk.helper.FakeLogcat;
-import com.deploygate.sdk.mockito.BundleMatcher;
import com.deploygate.service.DeployGateEvent;
import com.deploygate.service.FakeDeployGateClientService;
import com.google.common.truth.Truth;
@@ -29,17 +38,6 @@
import java.util.List;
import java.util.Random;
-import static com.deploygate.sdk.mockito.BundleMatcher.eq;
-import static com.deploygate.sdk.mockito.BundleMatcher.eq;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyBoolean;
-import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.doThrow;
-import static org.mockito.Mockito.mockStatic;
-import static org.robolectric.annotation.LooperMode.Mode.PAUSED;
-
@RunWith(AndroidJUnit4.class)
@LooperMode(PAUSED)
public class LogcatInstructionSerializerTest {
@@ -87,7 +85,7 @@ public void after() {
instructionSerializer.halt();
}
- for (Process process: processes) {
+ for (Process process : processes) {
if (process.isAlive()) {
process.destroy();
}
@@ -102,11 +100,30 @@ public void after() {
public void sendSingleChunk_always_returns_retriable_status_if_service_is_none() throws RemoteException {
instructionSerializer = new LogcatInstructionSerializer(PACKAGE_NAME);
- instructionSerializer.requestOneshotLogcat();
+ instructionSerializer.requestOneshotLogcat(null);
+
+ SendLogcatRequest chunk1 = new SendLogcatRequest("tid1", new ArrayList<>(Arrays.asList("line1", "line2", "line3")), null);
+ SendLogcatRequest chunk2 = new SendLogcatRequest("tid2", new ArrayList<>(Arrays.asList("line4", "line5", "line6")), null);
+ SendLogcatRequest chunk3 = new SendLogcatRequest("tid3", new ArrayList<>(Arrays.asList("line7", "line8", "line9")), null);
+
+ doNothing().when(service).sendEvent(anyString(), anyString(), any(Bundle.class));
+
+ Truth.assertThat(instructionSerializer.sendSingleChunk(chunk1)).isEqualTo(LogcatInstructionSerializer.SEND_LOGCAT_RESULT_FAILURE_RETRIABLE);
+ Truth.assertThat(instructionSerializer.sendSingleChunk(chunk2)).isEqualTo(LogcatInstructionSerializer.SEND_LOGCAT_RESULT_FAILURE_RETRIABLE);
+ Truth.assertThat(instructionSerializer.sendSingleChunk(chunk3)).isEqualTo(LogcatInstructionSerializer.SEND_LOGCAT_RESULT_FAILURE_RETRIABLE);
+
+ Mockito.verifyNoInteractions(service);
+ }
+
+ @Test(timeout = 3000L)
+ public void sendSingleChunk_always_returns_retriable_status_if_service_is_none_and_is_in_capture_mode() throws RemoteException {
+ instructionSerializer = new LogcatInstructionSerializer(PACKAGE_NAME);
+
+ instructionSerializer.requestOneshotLogcat("brabra");
- SendLogcatRequest chunk1 = new SendLogcatRequest("tid1", new ArrayList<>(Arrays.asList("line1", "line2", "line3")));
- SendLogcatRequest chunk2 = new SendLogcatRequest("tid2", new ArrayList<>(Arrays.asList("line4", "line5", "line6")));
- SendLogcatRequest chunk3 = new SendLogcatRequest("tid3", new ArrayList<>(Arrays.asList("line7", "line8", "line9")));
+ SendLogcatRequest chunk1 = new SendLogcatRequest("tid1", new ArrayList<>(Arrays.asList("line1", "line2", "line3")), "brabra");
+ SendLogcatRequest chunk2 = new SendLogcatRequest("tid2", new ArrayList<>(Arrays.asList("line4", "line5", "line6")), "brabra");
+ SendLogcatRequest chunk3 = new SendLogcatRequest("tid3", new ArrayList<>(Arrays.asList("line7", "line8", "line9")), "brabra");
doNothing().when(service).sendEvent(anyString(), anyString(), any(Bundle.class));
@@ -124,10 +141,10 @@ public void sendSingleChunk_uses_retry_barrier() throws RemoteException {
Shadows.shadowOf(instructionSerializer.getHandler().getLooper()).pause();
- SendLogcatRequest noIssue = new SendLogcatRequest("noIssue", new ArrayList<>(Arrays.asList("line1", "line2", "line3")));
- SendLogcatRequest successAfterRetries = new SendLogcatRequest("successAfterRetries", new ArrayList<>(Arrays.asList("line4", "line5", "line6")));
- SendLogcatRequest retryExceeded = new SendLogcatRequest("retryExceeded", new ArrayList<>(Arrays.asList("line7", "line8", "line9")));
- SendLogcatRequest chunkRequest = new SendLogcatRequest("chunkRequest", new ArrayList<>(Arrays.asList("line10", "line11", "line12")));
+ SendLogcatRequest noIssue = new SendLogcatRequest("noIssue", new ArrayList<>(Arrays.asList("line1", "line2", "line3")), null);
+ SendLogcatRequest successAfterRetries = new SendLogcatRequest("successAfterRetries", new ArrayList<>(Arrays.asList("line4", "line5", "line6")), null);
+ SendLogcatRequest retryExceeded = new SendLogcatRequest("retryExceeded", new ArrayList<>(Arrays.asList("line7", "line8", "line9")), null);
+ SendLogcatRequest chunkRequest = new SendLogcatRequest("chunkRequest", new ArrayList<>(Arrays.asList("line10", "line11", "line12")), null);
SendLogcatRequest beginningRequest = SendLogcatRequest.createBeginning("beginningRequest");
SendLogcatRequest terminationRequest = SendLogcatRequest.createTermination("terminationRequest");
@@ -188,7 +205,15 @@ public void requestSendingLogcat_works_regardless_of_service() throws RemoteExce
// don't fail
for (int i = 0; i < 10; i++) {
- instructionSerializer.requestOneshotLogcat();
+ instructionSerializer.requestOneshotLogcat(null);
+ }
+
+ Shadows.shadowOf(instructionSerializer.getHandler().getLooper()).idle();
+
+ // don't fail
+
+ for (int i = 0; i < 10; i++) {
+ instructionSerializer.requestOneshotLogcat("brabra");
}
Shadows.shadowOf(instructionSerializer.getHandler().getLooper()).idle();
@@ -203,10 +228,19 @@ public void requestSendingLogcat_does_nothing_if_disabled() throws RemoteExcepti
instructionSerializer.setEnabled(false);
for (int i = 0; i < 30; i++) {
- if (i % 2 == 0) {
- Truth.assertThat(instructionSerializer.requestOneshotLogcat()).isFalse();
- } else {
- Truth.assertThat(instructionSerializer.requestStreamedLogcat("bsk")).isFalse();
+ switch (i % 3) {
+ case 0: {
+ Truth.assertThat(instructionSerializer.requestOneshotLogcat(null)).isFalse();
+ break;
+ }
+ case 1: {
+ Truth.assertThat(instructionSerializer.requestStreamedLogcat("bsk")).isFalse();
+ break;
+ }
+ case 2: {
+ Truth.assertThat(instructionSerializer.requestOneshotLogcat("brabra")).isFalse();
+ break;
+ }
}
}
@@ -214,10 +248,19 @@ public void requestSendingLogcat_does_nothing_if_disabled() throws RemoteExcepti
instructionSerializer.connect(service);
for (int i = 0; i < 30; i++) {
- if (i % 2 == 0) {
- Truth.assertThat(instructionSerializer.requestOneshotLogcat()).isFalse();
- } else {
- Truth.assertThat(instructionSerializer.requestStreamedLogcat("bsk")).isFalse();
+ switch (i % 3) {
+ case 0: {
+ Truth.assertThat(instructionSerializer.requestOneshotLogcat(null)).isFalse();
+ break;
+ }
+ case 1: {
+ Truth.assertThat(instructionSerializer.requestStreamedLogcat("bsk")).isFalse();
+ break;
+ }
+ case 2: {
+ Truth.assertThat(instructionSerializer.requestOneshotLogcat("brabra")).isFalse();
+ break;
+ }
}
}
diff --git a/sdk/src/test/java/com/deploygate/sdk/LogcatProcessTest.java b/sdk/src/test/java/com/deploygate/sdk/LogcatProcessTest.java
index 4a0dd0d..6b27d49 100644
--- a/sdk/src/test/java/com/deploygate/sdk/LogcatProcessTest.java
+++ b/sdk/src/test/java/com/deploygate/sdk/LogcatProcessTest.java
@@ -1,5 +1,10 @@
package com.deploygate.sdk;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.Mockito.mockStatic;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.deploygate.sdk.helper.FakeLogcat;
@@ -22,9 +27,6 @@
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
-import static org.mockito.ArgumentMatchers.anyBoolean;
-import static org.mockito.Mockito.mockStatic;
-
@RunWith(AndroidJUnit4.class)
public class LogcatProcessTest {
private FakeLogcat fakeLogcat;
@@ -72,7 +74,7 @@ public void nonOneShot_emits_multiple_log_chunks() {
try {
fakeLogcat = new FakeLogcat(10);
- LogcatProcess.LogcatWatcher watcher = new LogcatProcess.LogcatWatcher("bsk1", capture);
+ LogcatProcess.LogcatWatcher watcher = new LogcatProcess.LogcatWatcher("bsk1", null, capture);
watcher.run();
@@ -89,7 +91,7 @@ public void nonOneShot_emits_multiple_log_chunks() {
try {
fakeLogcat = new FakeLogcat(501);
- LogcatProcess.LogcatWatcher watcher = new LogcatProcess.LogcatWatcher("bks2", capture);
+ LogcatProcess.LogcatWatcher watcher = new LogcatProcess.LogcatWatcher("bsk2", null, capture);
watcher.run();
@@ -110,7 +112,7 @@ public void nonOneShot_emits_multiple_log_chunks() {
try {
fakeLogcat = new FakeLogcat(1000);
- LogcatProcess.LogcatWatcher watcher = new LogcatProcess.LogcatWatcher("bks3", capture);
+ LogcatProcess.LogcatWatcher watcher = new LogcatProcess.LogcatWatcher("bks3", null, capture);
watcher.run();
@@ -136,7 +138,7 @@ public void OneShot_emits_single_log_chunk() {
try {
fakeLogcat = new FakeLogcat(10);
- LogcatProcess.LogcatWatcher watcher = new LogcatProcess.LogcatWatcher(null, capture);
+ LogcatProcess.LogcatWatcher watcher = new LogcatProcess.LogcatWatcher(null, null, capture);
watcher.run();
@@ -153,7 +155,7 @@ public void OneShot_emits_single_log_chunk() {
try {
fakeLogcat = new FakeLogcat(501);
- LogcatProcess.LogcatWatcher watcher = new LogcatProcess.LogcatWatcher(null, capture);
+ LogcatProcess.LogcatWatcher watcher = new LogcatProcess.LogcatWatcher(null, "cap2", capture);
watcher.run();
@@ -173,7 +175,7 @@ public void OneShot_emits_single_log_chunk() {
try {
fakeLogcat = new FakeLogcat(1000);
- LogcatProcess.LogcatWatcher watcher = new LogcatProcess.LogcatWatcher(null, capture);
+ LogcatProcess.LogcatWatcher watcher = new LogcatProcess.LogcatWatcher(null, null, capture);
watcher.run();
@@ -194,17 +196,17 @@ public void OneShot_emits_single_log_chunk() {
@Test(timeout = 3000L)
public void nonOneShot_interrupt_stops_later_emits() {
- CaptureCallback capture = new CaptureCallback();
+ CaptureCallback callback = new CaptureCallback();
try {
// call the method for the finished process
fakeLogcat = new FakeLogcat(10);
- LogcatProcess.LogcatWatcher watcher = new LogcatProcess.LogcatWatcher("bks1", capture);
+ LogcatProcess.LogcatWatcher watcher = new LogcatProcess.LogcatWatcher("bks1", null, callback);
watcher.run();
- List> linesList = capture.captured.get(watcher.getProcessId());
+ List> linesList = callback.captured.get(watcher.getProcessId());
Truth.assertThat(linesList).hasSize(1);
Truth.assertThat(linesList.get(0)).hasSize(10);
@@ -221,13 +223,13 @@ public void nonOneShot_interrupt_stops_later_emits() {
// interrupt the on-going process that read lines less than MAX_LINES
fakeLogcat = new FakeLogcat(20, 10);
- LogcatProcess.LogcatWatcher watcher = new LogcatProcess.LogcatWatcher("bks2", capture);
+ LogcatProcess.LogcatWatcher watcher = new LogcatProcess.LogcatWatcher("bsk2", null, callback);
destroyWorkerAfter(watcher, 300, TimeUnit.MILLISECONDS);
watcher.run();
- List> linesList = capture.captured.get(watcher.getProcessId());
+ List> linesList = callback.captured.get(watcher.getProcessId());
Truth.assertThat(linesList).isEmpty();
} finally {
@@ -240,7 +242,7 @@ public void nonOneShot_interrupt_stops_later_emits() {
// interrupt the on-going process that read many lines more than MAX_LINES
fakeLogcat = new FakeLogcat(550, 549);
- LogcatProcess.LogcatWatcher watcher = new LogcatProcess.LogcatWatcher("bks3", capture);
+ LogcatProcess.LogcatWatcher watcher = new LogcatProcess.LogcatWatcher("bsk3", null, callback);
destroyWorkerAfter(watcher, 500, TimeUnit.MILLISECONDS);
@@ -248,7 +250,7 @@ public void nonOneShot_interrupt_stops_later_emits() {
List generatedLines = fakeLogcat.getGeneratedLines();
- List> linesList = capture.captured.get(watcher.getProcessId());
+ List> linesList = callback.captured.get(watcher.getProcessId());
// emit the first chunk but second chunk
Truth.assertThat(linesList).hasSize(1);
@@ -269,7 +271,7 @@ public void OneShot_interrupt_stops_emitting_logs() {
// call the method for the finished process
fakeLogcat = new FakeLogcat(10);
- LogcatProcess.LogcatWatcher watcher = new LogcatProcess.LogcatWatcher(null, capture);
+ LogcatProcess.LogcatWatcher watcher = new LogcatProcess.LogcatWatcher("bsk1", null, capture);
watcher.run();
@@ -290,7 +292,7 @@ public void OneShot_interrupt_stops_emitting_logs() {
// interrupt the on-going process that read lines less than MAX_LINES
fakeLogcat = new FakeLogcat(20, 10);
- LogcatProcess.LogcatWatcher watcher = new LogcatProcess.LogcatWatcher(null, capture);
+ LogcatProcess.LogcatWatcher watcher = new LogcatProcess.LogcatWatcher(null, "cap2", capture);
destroyWorkerAfter(watcher, 300, TimeUnit.MILLISECONDS);
@@ -309,7 +311,7 @@ public void OneShot_interrupt_stops_emitting_logs() {
// interrupt the on-going process that read many lines more than MAX_LINES
fakeLogcat = new FakeLogcat(550, 549);
- LogcatProcess.LogcatWatcher watcher = new LogcatProcess.LogcatWatcher(null, capture);
+ LogcatProcess.LogcatWatcher watcher = new LogcatProcess.LogcatWatcher(null, null, capture);
destroyWorkerAfter(watcher, 300, TimeUnit.MILLISECONDS);
@@ -350,7 +352,7 @@ private static class CaptureCallback implements LogcatProcess.Callback {
private final Map finished = new HashMap<>();
@Override
- public void onStarted(String processId) {
+ public void onStarted(@NonNull String processId) {
if (captured.containsKey(processId)) {
throw new IllegalStateException("only unique process id is allowed");
}
@@ -360,14 +362,15 @@ public void onStarted(String processId) {
@Override
public void emit(
- String processId,
- ArrayList logcatLines
+ @NonNull String processId,
+ @NonNull ArrayList logcatLines,
+ @Nullable String captureId
) {
captured.get(processId).add(logcatLines);
}
@Override
- public void onFinished(String processId) {
+ public void onFinished(@NonNull String processId) {
captured.put(processId, Collections.unmodifiableList(captured.get(processId)));
finished.put(processId, true);
}
diff --git a/sdk/src/test/java/com/deploygate/sdk/SendLogcatRequestTest.java b/sdk/src/test/java/com/deploygate/sdk/SendLogcatRequestTest.java
index 5bc5dc2..3231e0a 100644
--- a/sdk/src/test/java/com/deploygate/sdk/SendLogcatRequestTest.java
+++ b/sdk/src/test/java/com/deploygate/sdk/SendLogcatRequestTest.java
@@ -1,5 +1,7 @@
package com.deploygate.sdk;
+import static com.google.common.truth.Truth.assertAbout;
+
import android.os.Bundle;
import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -19,8 +21,7 @@
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
-
-import static com.google.common.truth.Truth.assertAbout;
+import java.util.Objects;
@RunWith(AndroidJUnit4.class)
public class SendLogcatRequestTest {
@@ -37,21 +38,25 @@ public void apply() throws Throwable {
SendLogcatRequest beginning = SendLogcatRequest.createBeginning("bsk1");
- BundleSubject.assertThat(beginning.toExtras()).isEqualTo(createLogExtra("bsk1", "unique_id", new ArrayList(), "beginning"));
+ BundleSubject.assertThat(beginning.toExtras()).isEqualTo(createLogExtra("bsk1", "unique_id", new ArrayList(), "beginning", null));
- SendLogcatRequest content = new SendLogcatRequest("bsk2", new ArrayList<>(Arrays.asList("1", "2")));
+ SendLogcatRequest content = new SendLogcatRequest("bsk2", new ArrayList<>(Arrays.asList("1", "2")), null);
- BundleSubject.assertThat(content.toExtras()).isEqualTo(createLogExtra("bsk2", "unique_id", new ArrayList<>(Arrays.asList("1", "2")), "content"));
+ BundleSubject.assertThat(content.toExtras()).isEqualTo(createLogExtra("bsk2", "unique_id", new ArrayList<>(Arrays.asList("1", "2")), "content", null));
SendLogcatRequest termination = SendLogcatRequest.createTermination("bsk3");
- BundleSubject.assertThat(termination.toExtras()).isEqualTo(createLogExtra("bsk3", "unique_id", new ArrayList(), "termination"));
+ BundleSubject.assertThat(termination.toExtras()).isEqualTo(createLogExtra("bsk3", "unique_id", new ArrayList(), "termination", null));
+
+ SendLogcatRequest capture = new SendLogcatRequest("bsk4", new ArrayList<>(Arrays.asList("1")), "capture_id");
+
+ BundleSubject.assertThat(capture.toExtras()).isEqualTo(createLogExtra("bsk4", "unique_id", new ArrayList<>(Arrays.asList("1")), "content", "capture_id"));
}
}
@Test
public void splitInto_create_n_sublist() {
- SendLogcatRequest request = new SendLogcatRequest("bsk", arrayListOf(0, 10));
+ SendLogcatRequest request = new SendLogcatRequest("bsk", arrayListOf(0, 10), null);
List singleRequests = request.splitInto(1);
@@ -61,39 +66,47 @@ public void splitInto_create_n_sublist() {
List twoRequests = request.splitInto(2);
Truth.assertThat(twoRequests).hasSize(2);
- SendLogcatRequestSubject.assertThat(twoRequests.get(0)).isSameInBundle(request.gid, SendLogcatRequest.Position.Content, arrayListOf(0, 5));
- SendLogcatRequestSubject.assertThat(twoRequests.get(1)).isSameInBundle(request.gid, SendLogcatRequest.Position.Content, arrayListOf(5, 5));
+ SendLogcatRequestSubject.assertThat(twoRequests.get(0)).isSameInBundle(request.gid, SendLogcatRequest.Position.Content, arrayListOf(0, 5), null);
+ SendLogcatRequestSubject.assertThat(twoRequests.get(1)).isSameInBundle(request.gid, SendLogcatRequest.Position.Content, arrayListOf(5, 5), null);
List threeRequests = request.splitInto(3);
Truth.assertThat(threeRequests).hasSize(3);
- SendLogcatRequestSubject.assertThat(threeRequests.get(0)).isSameInBundle(request.gid, SendLogcatRequest.Position.Content, arrayListOf(0, 3));
- SendLogcatRequestSubject.assertThat(threeRequests.get(1)).isSameInBundle(request.gid, SendLogcatRequest.Position.Content, arrayListOf(3, 3));
- SendLogcatRequestSubject.assertThat(threeRequests.get(2)).isSameInBundle(request.gid, SendLogcatRequest.Position.Content, arrayListOf(6, 4));
+ SendLogcatRequestSubject.assertThat(threeRequests.get(0)).isSameInBundle(request.gid, SendLogcatRequest.Position.Content, arrayListOf(0, 3), null);
+ SendLogcatRequestSubject.assertThat(threeRequests.get(1)).isSameInBundle(request.gid, SendLogcatRequest.Position.Content, arrayListOf(3, 3), null);
+ SendLogcatRequestSubject.assertThat(threeRequests.get(2)).isSameInBundle(request.gid, SendLogcatRequest.Position.Content, arrayListOf(6, 4), null);
List nineRequests = request.splitInto(9);
Truth.assertThat(nineRequests).hasSize(9);
- SendLogcatRequestSubject.assertThat(nineRequests.get(0)).isSameInBundle(request.gid, SendLogcatRequest.Position.Content, arrayListOf(0, 1));
- SendLogcatRequestSubject.assertThat(nineRequests.get(1)).isSameInBundle(request.gid, SendLogcatRequest.Position.Content, arrayListOf(1, 1));
- SendLogcatRequestSubject.assertThat(nineRequests.get(2)).isSameInBundle(request.gid, SendLogcatRequest.Position.Content, arrayListOf(2, 1));
- SendLogcatRequestSubject.assertThat(nineRequests.get(3)).isSameInBundle(request.gid, SendLogcatRequest.Position.Content, arrayListOf(3, 1));
- SendLogcatRequestSubject.assertThat(nineRequests.get(4)).isSameInBundle(request.gid, SendLogcatRequest.Position.Content, arrayListOf(4, 1));
- SendLogcatRequestSubject.assertThat(nineRequests.get(5)).isSameInBundle(request.gid, SendLogcatRequest.Position.Content, arrayListOf(5, 1));
- SendLogcatRequestSubject.assertThat(nineRequests.get(6)).isSameInBundle(request.gid, SendLogcatRequest.Position.Content, arrayListOf(6, 1));
- SendLogcatRequestSubject.assertThat(nineRequests.get(7)).isSameInBundle(request.gid, SendLogcatRequest.Position.Content, arrayListOf(7, 1));
- SendLogcatRequestSubject.assertThat(nineRequests.get(8)).isSameInBundle(request.gid, SendLogcatRequest.Position.Content, arrayListOf(8, 2));
+ SendLogcatRequestSubject.assertThat(nineRequests.get(0)).isSameInBundle(request.gid, SendLogcatRequest.Position.Content, arrayListOf(0, 1), null);
+ SendLogcatRequestSubject.assertThat(nineRequests.get(1)).isSameInBundle(request.gid, SendLogcatRequest.Position.Content, arrayListOf(1, 1), null);
+ SendLogcatRequestSubject.assertThat(nineRequests.get(2)).isSameInBundle(request.gid, SendLogcatRequest.Position.Content, arrayListOf(2, 1), null);
+ SendLogcatRequestSubject.assertThat(nineRequests.get(3)).isSameInBundle(request.gid, SendLogcatRequest.Position.Content, arrayListOf(3, 1), null);
+ SendLogcatRequestSubject.assertThat(nineRequests.get(4)).isSameInBundle(request.gid, SendLogcatRequest.Position.Content, arrayListOf(4, 1), null);
+ SendLogcatRequestSubject.assertThat(nineRequests.get(5)).isSameInBundle(request.gid, SendLogcatRequest.Position.Content, arrayListOf(5, 1), null);
+ SendLogcatRequestSubject.assertThat(nineRequests.get(6)).isSameInBundle(request.gid, SendLogcatRequest.Position.Content, arrayListOf(6, 1), null);
+ SendLogcatRequestSubject.assertThat(nineRequests.get(7)).isSameInBundle(request.gid, SendLogcatRequest.Position.Content, arrayListOf(7, 1), null);
+ SendLogcatRequestSubject.assertThat(nineRequests.get(8)).isSameInBundle(request.gid, SendLogcatRequest.Position.Content, arrayListOf(8, 2), null);
List overSplitRequests = request.splitInto(11);
Truth.assertThat(overSplitRequests).hasSize(10);
- SendLogcatRequestSubject.assertThat(overSplitRequests.get(0)).isSameInBundle(request.gid, SendLogcatRequest.Position.Content, arrayListOf(0, 1));
- SendLogcatRequestSubject.assertThat(overSplitRequests.get(1)).isSameInBundle(request.gid, SendLogcatRequest.Position.Content, arrayListOf(1, 1));
- SendLogcatRequestSubject.assertThat(overSplitRequests.get(2)).isSameInBundle(request.gid, SendLogcatRequest.Position.Content, arrayListOf(2, 1));
- SendLogcatRequestSubject.assertThat(overSplitRequests.get(3)).isSameInBundle(request.gid, SendLogcatRequest.Position.Content, arrayListOf(3, 1));
- SendLogcatRequestSubject.assertThat(overSplitRequests.get(4)).isSameInBundle(request.gid, SendLogcatRequest.Position.Content, arrayListOf(4, 1));
- SendLogcatRequestSubject.assertThat(overSplitRequests.get(5)).isSameInBundle(request.gid, SendLogcatRequest.Position.Content, arrayListOf(5, 1));
- SendLogcatRequestSubject.assertThat(overSplitRequests.get(6)).isSameInBundle(request.gid, SendLogcatRequest.Position.Content, arrayListOf(6, 1));
- SendLogcatRequestSubject.assertThat(overSplitRequests.get(7)).isSameInBundle(request.gid, SendLogcatRequest.Position.Content, arrayListOf(7, 1));
- SendLogcatRequestSubject.assertThat(overSplitRequests.get(8)).isSameInBundle(request.gid, SendLogcatRequest.Position.Content, arrayListOf(8, 1));
- SendLogcatRequestSubject.assertThat(overSplitRequests.get(9)).isSameInBundle(request.gid, SendLogcatRequest.Position.Content, arrayListOf(9, 1));
+ SendLogcatRequestSubject.assertThat(overSplitRequests.get(0)).isSameInBundle(request.gid, SendLogcatRequest.Position.Content, arrayListOf(0, 1), null);
+ SendLogcatRequestSubject.assertThat(overSplitRequests.get(1)).isSameInBundle(request.gid, SendLogcatRequest.Position.Content, arrayListOf(1, 1), null);
+ SendLogcatRequestSubject.assertThat(overSplitRequests.get(2)).isSameInBundle(request.gid, SendLogcatRequest.Position.Content, arrayListOf(2, 1), null);
+ SendLogcatRequestSubject.assertThat(overSplitRequests.get(3)).isSameInBundle(request.gid, SendLogcatRequest.Position.Content, arrayListOf(3, 1), null);
+ SendLogcatRequestSubject.assertThat(overSplitRequests.get(4)).isSameInBundle(request.gid, SendLogcatRequest.Position.Content, arrayListOf(4, 1), null);
+ SendLogcatRequestSubject.assertThat(overSplitRequests.get(5)).isSameInBundle(request.gid, SendLogcatRequest.Position.Content, arrayListOf(5, 1), null);
+ SendLogcatRequestSubject.assertThat(overSplitRequests.get(6)).isSameInBundle(request.gid, SendLogcatRequest.Position.Content, arrayListOf(6, 1), null);
+ SendLogcatRequestSubject.assertThat(overSplitRequests.get(7)).isSameInBundle(request.gid, SendLogcatRequest.Position.Content, arrayListOf(7, 1), null);
+ SendLogcatRequestSubject.assertThat(overSplitRequests.get(8)).isSameInBundle(request.gid, SendLogcatRequest.Position.Content, arrayListOf(8, 1), null);
+ SendLogcatRequestSubject.assertThat(overSplitRequests.get(9)).isSameInBundle(request.gid, SendLogcatRequest.Position.Content, arrayListOf(9, 1), null);
+
+ SendLogcatRequest requestWithCapture = new SendLogcatRequest("bsk2", arrayListOf(0, 10), "capture_id");
+
+ List threeRequestsWithCapture = requestWithCapture.splitInto(3);
+ Truth.assertThat(threeRequestsWithCapture).hasSize(3);
+ SendLogcatRequestSubject.assertThat(threeRequestsWithCapture.get(0)).isSameInBundle(requestWithCapture.gid, SendLogcatRequest.Position.Content, arrayListOf(0, 3), "capture_id");
+ SendLogcatRequestSubject.assertThat(threeRequestsWithCapture.get(1)).isSameInBundle(requestWithCapture.gid, SendLogcatRequest.Position.Content, arrayListOf(3, 3), "capture_id");
+ SendLogcatRequestSubject.assertThat(threeRequestsWithCapture.get(2)).isSameInBundle(requestWithCapture.gid, SendLogcatRequest.Position.Content, arrayListOf(6, 4), "capture_id");
}
@Test
@@ -130,17 +143,24 @@ private static Bundle createLogExtra(
String gid,
String cid,
ArrayList lines,
- String positionLabel
+ String positionLabel,
+ String captureId
) {
Bundle bundle = new Bundle();
bundle.putString("e.gid", gid);
bundle.putString("e.cid", cid);
bundle.putStringArrayList("log", lines);
bundle.putString("e.bundle-position", positionLabel);
+ if (captureId != null) {
+ bundle.putString("e.capture-id", captureId);
+ }
return bundle;
}
- private static ArrayList arrayListOf(int startInclusive, int count) {
+ private static ArrayList arrayListOf(
+ int startInclusive,
+ int count
+ ) {
ArrayList list = new ArrayList<>();
for (int i = startInclusive, max = startInclusive + count; i < max; i++) {
@@ -177,7 +197,12 @@ protected SendLogcatRequestSubject(
this.actual = actual;
}
- public void isSameInBundle(String expectedKey, SendLogcatRequest.Position expectedPosition, List expectedLines) {
+ public void isSameInBundle(
+ String expectedKey,
+ SendLogcatRequest.Position expectedPosition,
+ List expectedLines,
+ String captureId
+ ) {
if (!actual.gid.equals(expectedKey)) {
failWithActual(Fact.simpleFact(String.format(Locale.US, "%s is expected of %s", expectedKey, toString(actual))));
return;
@@ -199,6 +224,10 @@ public void isSameInBundle(String expectedKey, SendLogcatRequest.Position expect
return;
}
}
+
+ if (!Objects.equals(actual.captureId, captureId)) {
+ failWithActual(Fact.simpleFact(String.format(Locale.US, "%s is expected to be exactly included in %s", actual.captureId, captureId)));
+ }
}
@Override
@@ -225,6 +254,8 @@ private static String toString(SendLogcatRequest request) {
builder.append(request.position.name());
builder.append(", lines=[");
builder.append(String.join(", ", request.lines));
+ builder.append(", capture_id=");
+ builder.append(request.captureId);
builder.append("]");
builder.append(" }");
return builder.toString();
diff --git a/sdk/src/test/java/com/deploygate/sdk/mockito/BundleMatcher.java b/sdk/src/test/java/com/deploygate/sdk/mockito/BundleMatcher.java
index a9f8771..471df33 100644
--- a/sdk/src/test/java/com/deploygate/sdk/mockito/BundleMatcher.java
+++ b/sdk/src/test/java/com/deploygate/sdk/mockito/BundleMatcher.java
@@ -1,13 +1,13 @@
package com.deploygate.sdk.mockito;
+import static org.mockito.internal.progress.ThreadSafeMockingProgress.mockingProgress;
+
import android.os.Bundle;
import com.deploygate.sdk.helper.Bundles;
import org.mockito.ArgumentMatcher;
-import static org.mockito.internal.progress.ThreadSafeMockingProgress.mockingProgress;
-
public class BundleMatcher {
public static Bundle eq(Bundle expected) {
mockingProgress().getArgumentMatcherStorage().reportMatcher(new Equals(expected));
diff --git a/sdk/src/test/java/com/deploygate/sdk/truth/BundleSubject.java b/sdk/src/test/java/com/deploygate/sdk/truth/BundleSubject.java
index 0e8402b..719483f 100644
--- a/sdk/src/test/java/com/deploygate/sdk/truth/BundleSubject.java
+++ b/sdk/src/test/java/com/deploygate/sdk/truth/BundleSubject.java
@@ -1,5 +1,7 @@
package com.deploygate.sdk.truth;
+import static com.google.common.truth.Truth.assertAbout;
+
import android.os.Bundle;
import com.deploygate.sdk.helper.Bundles;
@@ -9,8 +11,6 @@
import java.util.Locale;
-import static com.google.common.truth.Truth.assertAbout;
-
public class BundleSubject extends Subject {
public static Factory bundles() {
return new Factory() {