• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2022 Google LLC
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.google.android.libraries.mobiledatadownload.testing;
17 
18 import android.content.Context;
19 
20 import com.google.android.libraries.mobiledatadownload.TimeSource;
21 import com.google.android.libraries.mobiledatadownload.internal.logging.LoggingStateStore;
22 import com.google.android.libraries.mobiledatadownload.internal.logging.SharedPreferencesLoggingState;
23 import com.google.common.base.Optional;
24 import com.google.common.util.concurrent.ListeningExecutorService;
25 import com.google.common.util.concurrent.MoreExecutors;
26 import com.google.common.util.concurrent.ThreadFactoryBuilder;
27 
28 import java.util.Random;
29 import java.util.concurrent.Executor;
30 import java.util.concurrent.Executors;
31 
32 /**
33  * Utility class that provides support for building MDD with different types of dependencies for
34  * Testing.
35  *
36  * <p>If multiple type of dependencies need to be supported across tests, they can be defined here
37  * so all tests can rely on a single definition. This is useful for parameterizing tests, such as
38  * the case for ControlExecutor:
39  *
40  * <pre>{@code
41  * // In the test, define a parameter for ExecutorType
42  * @TestParameter ExecutorType controlExecutorType;
43  *
44  * // When building MDD in the test, rely on the shared provider:
45  * MobileDataDownloadBuilder.newBuilder()
46  *     .setControlExecutor(controlExecutorType.executor())
47  *      // include other dependencies...
48  *     .build();
49  *
50  * }</pre>
51  */
52 public final class MddTestDependencies {
53 
54     private static final String ALPHABET = "abcdefghijklmnopqrstuvwxyz";
55     private static final int INSTANCE_ID_CHAR_LIMIT = 10;
56     private static final Random random = new Random();
57 
MddTestDependencies()58     private MddTestDependencies() {
59     }
60 
61     /**
62      * Generates a random instance id.
63      *
64      * <p>This prevents potential cross test conflicts from occurring since metadata will be siloed
65      * between tests.
66      */
randomInstanceId()67     public static String randomInstanceId() {
68         StringBuilder sb = new StringBuilder();
69         for (int i = 0; i < INSTANCE_ID_CHAR_LIMIT; i++) {
70             sb.append(ALPHABET.charAt(random.nextInt(ALPHABET.length())));
71         }
72         return sb.toString();
73     }
74 
75     /**
76      * Type of executor passed when building MDD.
77      *
78      * <p>Used for parameterizing tests.
79      */
80     public enum ExecutorType {
81         SINGLE_THREADED,
82         MULTI_THREADED;
83 
executor()84         public ListeningExecutorService executor() {
85             switch (this) {
86                 case SINGLE_THREADED:
87                     return MoreExecutors.listeningDecorator(
88                             Executors.newSingleThreadExecutor(
89                                     new ThreadFactoryBuilder().setNameFormat(
90                                             "MddSingleThreaded-%d").build()));
91                 case MULTI_THREADED:
92                     return MoreExecutors.listeningDecorator(
93                             Executors.newCachedThreadPool(
94                                     new ThreadFactoryBuilder().setNameFormat(
95                                             "MddMultiThreaded-%d").build()));
96             }
97             throw new AssertionError("ExecutorType unsupported");
98         }
99     }
100 
101     /**
102      * Differentiates between Downloader Configurations.
103      *
104      * <p>Used for parameterizing tests, as well as for making configuration-specific test
105      * assertions.
106      */
107 //    public enum DownloaderConfigurationType {
108 //        V2_PLATFORM;
109 //
110 //        public Supplier<FileDownloader> fileDownloaderSupplier(
111 //                Context context,
112 //                ListeningExecutorService controlExecutor,
113 //                ListeningScheduledExecutorService downloadExecutor,
114 //                SynchronousFileStorage fileStorage,
115 //                Flags flags,
116 //                Optional<DownloadProgressMonitor> downloadProgressMonitor,
117 //                Optional<String> instanceId) {
118 //
119 //            // Set up file downloader supplier based on the configuration given
120 //            switch (this) {
121 //                case V2_PLATFORM:
122 //                    return () -> {
123 //                        return BaseFileDownloaderModule.createOffroad2FileDownloader(
124 //                                context,
125 //                                downloadExecutor,
126 //                                controlExecutor,
127 //                                fileStorage,
128 //                                new SharedPreferencesDownloadMetadata(
129 //                                        context.getSharedPreferences("downloadmetadata", 0),
130 //                                        controlExecutor),
131 //                                /* downloadProgressMonitor= */ downloadProgressMonitor,
132 //                                /* urlEngineOptional= */ Optional.absent(),
133 //                                /* exceptionHandlerOptional= */ Optional.absent(),
134 //                                /* authTokenProviderOptional= */ Optional.absent(),
135 ////                /* cookieJarSupplierOptional= */ Optional.absent(),
136 //                                /* trafficTag= */ Optional.absent(),
137 //                                flags);
138 //                    };
139 //            }
140 //            throw new AssertionError("Invalid DownloaderConfigurationType");
141 //        }
142 //    }
143 
144     /**
145      * Differentiates between LoggingStateStore implementations.
146      *
147      * <p>Used for parameterizing tests, as well as for making configuration-specific test
148      * assertions.
149      */
150     public enum LoggingStateStoreImpl {
151         SHARED_PREFERENCES;
152 
loggingStateStore( Context context, Optional<String> instanceIdOptional, TimeSource timeSource, Executor backgroundExecutor, Random random)153         public LoggingStateStore loggingStateStore(
154                 Context context,
155                 Optional<String> instanceIdOptional,
156                 TimeSource timeSource,
157                 Executor backgroundExecutor,
158                 Random random) {
159 
160             // Set up file downloader supplier based on the configuration given
161             switch (this) {
162                 case SHARED_PREFERENCES:
163                     return SharedPreferencesLoggingState.createFromContext(
164                             context, instanceIdOptional, timeSource, backgroundExecutor, random);
165             }
166             throw new AssertionError("Invalid LoggingStateStoreImpl");
167         }
168     }
169 }
170