UiDevice.getUiAutomation(instrumentation) returns null causing NPE, in Robolectric test - robolectric

In my Roblectric test, I try to confirm permission dialog with UiDevice
#RunWith(RobolectricTestRunner::class)
#Config(sdk = [Build.VERSION_CODES.P])
open class FooTest {
#Before
private fun before() {
var device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
// Confirm permissions dialog with device object
// ...
}
but this line throws an NPE exception
var device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
with stack trace
java.lang.NullPointerException
at androidx.test.uiautomator.QueryController.<init>(QueryController.java:95)
at androidx.test.uiautomator.UiDevice.<init>(UiDevice.java:109)
at androidx.test.uiautomator.UiDevice.getInstance(UiDevice.java:261)
because UiDevice.getUiAutomation(instrumentation) is returning null
public QueryController(Instrumentation instrumentation) {
mInstrumentation = instrumentation;
UiDevice.getUiAutomation(instrumentation).setOnAccessibilityEventListener(mEventListener);
}

Related

Unable to open SQLite database from singleton object

I am able to open the database from within the main app activity using the following code, but once it's wrapped into a singleton object, it keeps throwing a null-object error:
object CommonClass {
fun openSQLDatabase(): SQLiteDatabase? {
var dbase: SQLiteDatabase? = null
try {
dbase = openOrCreateDatabase(
"dbfile.sqlite",
Context.MODE_PRIVATE, null
)
} catch (e: SQLException) {
println(e.message)
}
return dbase
}
}
I'm assuming that the main AppCompatActivity should be passing its context to the object in some way, but I've not been able to find a working model.
to Swayangjit
Android Studio highlights the Context.MODE_PRIVATE parameter and flags it as:
Type mismatch.
Required: SQLiteDatabase.CursorFactory?
Found: Int
But when I implement the AppCompatActivity to the singleton object and pass the Context.MODE_PRIVATE from the main activity, it runs but throws this error:
java.lang.NullPointerException: Attempt to invoke virtual method 'android.database.sqlite.SQLiteDatabase android.content.Context.openOrCreateDatabase(java.lang.String, int, android.database.sqlite.SQLiteDatabase$CursorFactory)' on a null object reference
I believe the following will work :
object CommonClass {
fun openSQLDatabase(context: Context): SQLiteDatabase? {
var dbase: SQLiteDatabase? = null
if (dbase == null) {
try {
dbase = openOrCreateDatabase(context.getDatabasePath("dbfile.sqlite"), null)
} catch (e: SQLException) {
println(e.message)
}
}
return dbase
}
}
Note this assumes that you want the database in the default location i.e. data/data/the_package_name/databases/dbfile.sqlite
You could invoke/call it using something like :-
val mydb = CommonClass.openSQLDatabase(this)

why the coroutine exception handler double the original exception?

I implements my own async, I can't process the exception in a right way. why?
val expected = IllegalStateException();
val it = async<Any> {
throw expected;
};
assert.that({ it.get() }, throws(equalTo(expected)));
// ^--- but it throws a IllegalStateException(cause = expected)
Source Code
interface Response<in T> {
suspend fun yield(value: T);
}
interface Request<out T> {
fun get(): T;
fun <R> then(mapping: (T) -> R): Request<R>;
}
private val executor: ExecutorService = ForkJoinPool(20);
fun <T> async(block: suspend Response<T>.() -> Unit): Request<T> {
return object : Request<T>, Response<T> {
#Volatile var value: T? = null;
var request: Continuation<Unit>? = block.createCoroutine(this, delegate {}).let {
var task: Future<*>? = executor.submit { it.resume(Unit); };
return#let delegate {
try {
val current = task!!;
task = null;
current.get();
} catch(e: ExecutionException) {
throw e.cause ?: e;
}
};
};
override fun <R> then(mapping: (T) -> R): Request<R> = async<R> {
yield(mapping(get()));
};
override fun get(): T {
return value ?: wait();
}
private fun wait(): T {
val it = request!!;
request = null;
it.resume(Unit);
return value!!;
}
suspend override fun yield(value: T) {
this.value = value;
}
};
}
inline fun <T> delegate(noinline exceptional: (Throwable) -> Unit = { throw it; }, crossinline resume: (T) -> Unit): Continuation<T> {
return object : Continuation<T> {
override val context: CoroutineContext = EmptyCoroutineContext;
override fun resumeWithException(exception: Throwable) {
exceptional(exception);
}
override fun resume(value: T) {
resume(value);
}
}
}
the strange behavior is comes from java. the ForkJoinTask#getThrowableException will rethrow exception for the given task:
Returns a rethrowable exception for the given task, if
available. To provide accurate stack traces, if the exception
was not thrown by the current thread, we try to create a new
exception of the same type as the one thrown, but with the
recorded exception as its cause. If there is no such
constructor, we instead try to use a no-arg constructor,
followed by initCause, to the same effect. If none of these
apply, or any fail due to other exceptions, we return the
recorded exception, which is still correct, although it may
contain a misleading stack trace.
which implies that if you don't want to rethrow exception for the give task you can make the exception constructor non-publicly, for example:
val exception = object: IllegalStateException(){/**/};
// ^--- its constructor only available in its scope

Visual Studio SDK - IViewTagAggregatorFactoryService.CreateTagAggregator causes an exception

I need to obtain classifications tags for ITextSnapshotLine lines in a current text view.
First, I get the active text view:
public static IWpfTextView GetTextView()
{
var textManager = (IVsTextManager)ServiceProvider.GlobalProvider.GetService(typeof(SVsTextManager));
IVsTextView vTextView = null;
var mustHaveFocus = 1;
textManager.GetActiveView(mustHaveFocus, null, out vTextView);
var userData = vTextView as IVsUserData;
if (userData != null)
{
IWpfTextViewHost viewHost;
object holder;
var guidViewHost = DefGuidList.guidIWpfTextViewHost;
userData.GetData(ref guidViewHost, out holder);
viewHost = (IWpfTextViewHost)holder;
var textView = viewHost.TextView;
return textView;
}
return null;
}
Then, I get the collection of ITextViewLine lines from the view and call GetClassificationTags method on each:
GetClassificationTags(new SnapshotSpan(line.Start, line.Length), textView)
The method looks like this:
public IEnumerable<IMappingTagSpan<IClassificationTag>> GetClassificationTags(SnapshotSpan span, ITextView textView)
{
var snapshot = textView.TextSnapshot;
var componentModel = (IComponentModel)ServiceProvider.GlobalProvider.GetService(typeof(SComponentModel));
var exportProvider = componentModel.DefaultExportProvider;
var viewTagAggregatorFactoryService = exportProvider.GetExportedValue<IViewTagAggregatorFactoryService>();
var tagAggregator = viewTagAggregatorFactoryService.CreateTagAggregator<IClassificationTag>(textView);
return tagAggregator.GetTags(span);
}
As a result I have everything classified correctly. However, Visual Studio throws an exception and logs it to the ActivityLog.xml file. This happens only after classifying all the lines for the first time. The information in log file says:
System.InvalidOperationException:
Unexpected false
at Roslyn.Utilities.Contract.ThrowIfFalse(Boolean condition, String message)
at Microsoft.CodeAnalysis.Editor.Implementation.Diagnostics.AbstractDiagnosticsTaggerProvider`1.CreateTagger[T](ITextBuffer buffer)
at Microsoft.CodeAnalysis.Editor.Implementation.Diagnostics.AbstractDiagnosticsTaggerProvider`1.Microsoft.VisualStudio.Text.Tagging.ITaggerProvider.CreateTagger[T](ITextBuffer buffer)
at Microsoft.VisualStudio.Text.Tagging.Implementation.TagAggregator`1.GatherTaggers(ITextBuffer textBuffer)
I noticed that the exception is not thrown after commenting out the line below:
var tagAggregator = viewTagAggregatorFactoryService.CreateTagAggregator<IClassificationTag>(textView);
Sometimes, there is also this exception in the log file:
System.InvalidOperationException: Unexpected false
at Roslyn.Utilities.Contract.ThrowIfFalse(Boolean condition, String message)
at Microsoft.CodeAnalysis.Editor.Tagging.AbstractAsynchronousTaggerProvider`1.TagSource.GetTagIntervalTreeForBuffer(ITextBuffer buffer)
at Microsoft.CodeAnalysis.Editor.Tagging.AbstractAsynchronousTaggerProvider`1.Tagger.GetTagsWorker(NormalizedSnapshotSpanCollection requestedSpans, Boolean accurate, CancellationToken cancellationToken)
at Microsoft.CodeAnalysis.Editor.Tagging.AbstractAsynchronousTaggerProvider`1.Tagger.GetTags(NormalizedSnapshotSpanCollection requestedSpans)
at Microsoft.VisualStudio.Text.Tagging.Implementation.TagAggregator`1.<GetTagsForBuffer>d__38.MoveNext()
My question is: what causes this exception and how can I get rid of it?
The code is open source, you can just take a look. My guess is you're trying that on a background thread.

Android Roboelectric 3.0 testing next activity –choosing from multiple activities

I have scenario like this:--
I have three activities ActivityA(launcher activity), ActivityB, ActivityC
Now in Activity A I read the Application context to decide whether to start ActivityB or ActivityC.
But even after setting the context value manual, the ActivityA is not updated and second test case fails. Any helps?
private ActivityA activityA;
private ShadowActivity shadowActivity;
#Before
public void setUp() {
activityA = Robolectric.setupActivity(ActivityA.class);
assertNotNull("ActivityA not intsantiated", activityA);
shadowActivity = Shadows.shadowOf(activityA);
}
#Test
public void shouldStartActivityB() throws Exception
{
Intent intent = shadowActivity.peekNextStartedActivity();;
assertEquals(ActivityB.class.getCanonicalName(), intent.getComponent().getClassName());
}
#Test
public void shouldStartMainActivity() throws Exception
{
ApplicationSettings.setWizardState(RuntimeEnvironment.application, 22);
ShadowLog.d("Wizard state value", "" +ApplicationSettings.getWizardState(RuntimeEnvironment.application));// it prints 22
activityA= Robolectric.setupActivity(ActivityA.class);
shadowActivity = Shadows.shadowOf(activityA);
Intent intent = shadowActivity.peekNextStartedActivity();
ShadowLog.d("target activity is", intent.getComponent().getClassName());// This prints ActivityB instead of ActivityC
assertEquals(ActivityC.class.getCanonicalName(), intent.getComponent().getClassName()); // this test case fails
}

rxjava - Combine onerror and timout handling

I will start with what I want to achieve.
I want to call a method that returns an Observabe.
I do not know if the called method handles exceptions and timeouts
I want to combine observables in my call (merge/zip etc)
if one method fails, I want the answers from the methods that succeeded -
I don't want to break the flow.
In case of exception, I am capable of handling it and continuing with the flow,
but when I try to add timeoutmanagement I fail.
Here is my code
public static void main(String[] args) {
createObservables(false, true); // stalls for timeout
zip();
}
private static void createObservables(final boolean throwException,
final boolean stall) {
obs1 = Observable.just(1);
obs1 = obs1.map(new Func1<Integer, Integer>() {
#Override public Integer call(Integer integer) {
int i = 0;
if (throwException)
getObj().equals("");
if (stall)
zzz(10);
return ++integer;
}
});
obs2 = Observable.just(111);
}
private static void zip() {
System.out.println("**Zip**");
obs1 = obs1.onErrorReturn(new Func1<Throwable, Integer>() {
#Override public Integer call(Throwable throwable) {
return 999;
}
});
obs1 = obs1.timeout(5, TimeUnit.SECONDS);
Observable.zip(obs1, obs2, new Func2<Integer, Integer, ArrayList<Integer>>() {
#Override
public ArrayList<Integer> call(Integer integer1, Integer integer2) {
ArrayList<Integer> integers = new ArrayList<Integer>();
integers.add(integer1);
integers.add(integer2);
return integers;
}
}).subscribe(new Observer<Object>() {....}
);
}
Now, when I call
createObservables(false , false); // no exceptions and timeouts
I get onNext - [2, 111].
then I call
createObservables(true, false); // throw exception in one method only
I get onNext - [999, 111] - which is what I want. Exception and the result from the second method.
But when I call
createObservables(false, true); // stall on timeout
I get only onError.
But I want to get the other method answer.
Thanks.
Try creating an observable for your timeout value, in this case you want the same value as your error case:
Observable obs1Timeout = Observable.just(999);
Then in your timeout policy give it this observable as the fallback to use in the case of a timeout:
obs1 = obs1.timeout(5, TimeUnit.SECONDS, obs1Timeout);

Resources