• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 The Android Open Source Project
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 
17 package com.android.textclassifier.testing;
18 
19 import static org.mockito.ArgumentMatchers.any;
20 import static org.mockito.ArgumentMatchers.anyInt;
21 import static org.mockito.Mockito.mock;
22 import static org.mockito.Mockito.when;
23 
24 import android.content.ComponentName;
25 import android.content.Context;
26 import android.content.ContextWrapper;
27 import android.content.Intent;
28 import android.content.pm.ActivityInfo;
29 import android.content.pm.ApplicationInfo;
30 import android.content.pm.PackageManager;
31 import android.content.pm.ResolveInfo;
32 import androidx.test.core.app.ApplicationProvider;
33 import com.google.common.base.Preconditions;
34 import java.util.HashMap;
35 import java.util.Map;
36 import java.util.UUID;
37 import javax.annotation.Nullable;
38 import org.mockito.stubbing.Answer;
39 
40 /** A builder used to build a fake context for testing. */
41 public final class FakeContextBuilder {
42 
43   /** A component name that can be used for tests. */
44   public static final ComponentName DEFAULT_COMPONENT = new ComponentName("pkg", "cls");
45 
46   private final PackageManager packageManager;
47   private final ContextWrapper context;
48   private final Map<String, ComponentName> components = new HashMap<>();
49   private final Map<String, CharSequence> appLabels = new HashMap<>();
50   @Nullable private ComponentName allIntentComponent;
51 
FakeContextBuilder()52   public FakeContextBuilder() {
53     packageManager = mock(PackageManager.class);
54     when(packageManager.resolveActivity(any(Intent.class), anyInt())).thenReturn(null);
55     context =
56         new ContextWrapper(ApplicationProvider.getApplicationContext()) {
57           @Override
58           public PackageManager getPackageManager() {
59             return packageManager;
60           }
61         };
62   }
63 
64   /**
65    * Sets the component name of an activity to handle the specified intent action.
66    *
67    * <p><strong>NOTE: </strong>By default, no component is set to handle any intent.
68    */
setIntentComponent( String intentAction, @Nullable ComponentName component)69   public FakeContextBuilder setIntentComponent(
70       String intentAction, @Nullable ComponentName component) {
71     Preconditions.checkNotNull(intentAction);
72     components.put(intentAction, component);
73     return this;
74   }
75 
76   /** Sets the app label res for a specified package. */
setAppLabel(String packageName, @Nullable CharSequence appLabel)77   public FakeContextBuilder setAppLabel(String packageName, @Nullable CharSequence appLabel) {
78     Preconditions.checkNotNull(packageName);
79     appLabels.put(packageName, appLabel);
80     return this;
81   }
82 
83   /**
84    * Sets the component name of an activity to handle all intents.
85    *
86    * <p><strong>NOTE: </strong>By default, no component is set to handle any intent.
87    */
setAllIntentComponent(@ullable ComponentName component)88   public FakeContextBuilder setAllIntentComponent(@Nullable ComponentName component) {
89     allIntentComponent = component;
90     return this;
91   }
92 
93   /** Builds and returns a fake context. */
build()94   public Context build() {
95     when(packageManager.resolveActivity(any(Intent.class), anyInt()))
96         .thenAnswer(
97             (Answer<ResolveInfo>)
98                 invocation -> {
99                   final String action = ((Intent) invocation.getArgument(0)).getAction();
100                   final ComponentName component =
101                       components.containsKey(action) ? components.get(action) : allIntentComponent;
102                   return getResolveInfo(component);
103                 });
104     when(packageManager.getApplicationLabel(any(ApplicationInfo.class)))
105         .thenAnswer(
106             (Answer<CharSequence>)
107                 invocation -> {
108                   ApplicationInfo applicationInfo = invocation.getArgument(0);
109                   return appLabels.get(applicationInfo.packageName);
110                 });
111     return context;
112   }
113 
114   /** Returns a component name with random package and class names. */
newComponent()115   public static ComponentName newComponent() {
116     return new ComponentName(UUID.randomUUID().toString(), UUID.randomUUID().toString());
117   }
118 
getResolveInfo(ComponentName component)119   private static ResolveInfo getResolveInfo(ComponentName component) {
120     final ResolveInfo info;
121     if (component == null) {
122       info = null;
123     } else {
124       // NOTE: If something breaks in TextClassifier because we expect more fields to be set
125       // in here, just add them.
126       info = new ResolveInfo();
127       info.activityInfo = new ActivityInfo();
128       info.activityInfo.packageName = component.getPackageName();
129       info.activityInfo.name = component.getClassName();
130       info.activityInfo.exported = true;
131       info.activityInfo.applicationInfo = new ApplicationInfo();
132       info.activityInfo.applicationInfo.packageName = component.getPackageName();
133       info.activityInfo.applicationInfo.icon = 0;
134     }
135     return info;
136   }
137 }
138