Skip to content

Add better testing support for TransportRuntime. #3670

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Apr 21, 2022
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions subprojects.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,4 @@ transport
transport:transport-api
transport:transport-backend-cct
transport:transport-runtime
transport:transport-runtime-testing
19 changes: 19 additions & 0 deletions transport/transport-runtime-testing/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<!-- Copyright 2018 Google LLC -->
<!-- -->
<!-- Licensed under the Apache License, Version 2.0 (the "License"); -->
<!-- you may not use this file except in compliance with the License. -->
<!-- You may obtain a copy of the License at -->
<!-- -->
<!-- http://www.apache.org/licenses/LICENSE-2.0 -->
<!-- -->
<!-- Unless required by applicable law or agreed to in writing, software -->
<!-- distributed under the License is distributed on an "AS IS" BASIS, -->
<!-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -->
<!-- See the License for the specific language governing permissions and -->
<!-- limitations under the License. -->

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.google.android.datatransport.runtime.testing">
<!--Although the *SdkVersion is captured in gradle build files, this is required for non gradle builds-->
<!--<uses-sdk android:minSdkVersion="14"/>-->
</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.android.datatransport.runtime;

import com.google.android.datatransport.Priority;
import com.google.android.datatransport.runtime.backends.BackendResponse;
import com.google.android.datatransport.runtime.scheduling.jobscheduling.UploadTestSupport;

/** Test support for {@link TransportRuntime}. */
public final class TransportRuntimeTesting {
private TransportRuntimeTesting() {}

/** Synchronously force upload all scheduled events for a given destination and priority. */
public static BackendResponse forceUpload(Destination destination, Priority priority) {
return UploadTestSupport.forceUpload(
TransportContext.builder()
.setBackendName(destination.getName())
.setExtras(destination.getExtras())
.setPriority(priority)
.build());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.android.datatransport.runtime.scheduling.jobscheduling;

import com.google.android.datatransport.runtime.TransportContext;
import com.google.android.datatransport.runtime.TransportRuntime;
import com.google.android.datatransport.runtime.backends.BackendResponse;

/**
* Support class that avoids making {@link Uploader#logAndUpdateState(TransportContext, int) }
* method public in the SDK code.
*/
public class UploadTestSupport {
private UploadTestSupport() {}

public static BackendResponse forceUpload(TransportContext context) {
return TransportRuntime.getInstance().getUploader().logAndUpdateState(context, 1);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

plugins {
// not a firebase-library, since we don't intend to release this artifact.
id 'com.android.library'
}

android {
compileSdkVersion project.targetSdkVersion
defaultConfig {
minSdkVersion project.minSdkVersion
targetSdkVersion project.targetSdkVersion
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
testOptions.unitTests {
includeAndroidResources = true
}
}

dependencies {
implementation project(':transport:transport-api')
implementation project(':transport:transport-runtime')
implementation 'androidx.annotation:annotation:1.3.0'

implementation project(':transport:transport-backend-cct')
androidTestImplementation 'junit:junit:4.13.2'
androidTestImplementation "com.google.truth:truth:$googleTruthVersion"
androidTestImplementation 'androidx.test:runner:1.4.0'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test:rules:1.4.0'
}
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ public static Builder builder() {
*
* @hide
*/
@RestrictTo(RestrictTo.Scope.LIBRARY)
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
public TransportContext withPriority(Priority priority) {
return builder()
.setBackendName(getBackendName())
Expand All @@ -89,7 +89,7 @@ public abstract static class Builder {
public abstract Builder setExtras(@Nullable byte[] extras);

/** @hide */
@RestrictTo(RestrictTo.Scope.LIBRARY)
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
public abstract Builder setPriority(Priority priority);

public abstract TransportContext build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ private static Set<Encoding> getSupportedEncodings(Destination destination) {
return Collections.singleton(Encoding.of("proto"));
}

@RestrictTo(RestrictTo.Scope.LIBRARY)
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
public Uploader getUploader() {
return uploader;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,20 +111,20 @@ public void upload(TransportContext transportContext, int attemptNumber, Runnabl
});
}

void logAndUpdateState(TransportContext transportContext, int attemptNumber) {
BackendResponse logAndUpdateState(TransportContext transportContext, int attemptNumber) {
TransportBackend backend = backendRegistry.get(transportContext.getBackendName());
long maxNextRequestWaitMillis = 0;

BackendResponse response = BackendResponse.ok(maxNextRequestWaitMillis);
while (guard.runCriticalSection(() -> eventStore.hasPendingEventsFor(transportContext))) {
Iterable<PersistedEvent> persistedEvents =
guard.runCriticalSection(() -> eventStore.loadBatch(transportContext));

// Do not make a call to the backend if the list is empty.
if (!persistedEvents.iterator().hasNext()) {
return;
return response;
}

BackendResponse response;
if (backend == null) {
Logging.d(
LOG_TAG, "Unknown backend for %s, deleting event batch for it...", transportContext);
Expand Down Expand Up @@ -157,7 +157,7 @@ void logAndUpdateState(TransportContext transportContext, int attemptNumber) {
return null;
});
workScheduler.schedule(transportContext, attemptNumber + 1, true);
return;
return response;
} else {
guard.runCriticalSection(
() -> {
Expand Down Expand Up @@ -202,6 +202,7 @@ void logAndUpdateState(TransportContext transportContext, int attemptNumber) {
transportContext, clock.getTime() + finalMaxNextRequestWaitMillis);
return null;
});
return response;
}

@VisibleForTesting
Expand Down