How to print to stream during sbt setting initialization - sbt

I am trying to print a warning message whilst configuring an sbt setting. My initial attempt looks something like this:
setting := {
val log = streams.value.log
val condition = //check something
if (condition) {
log.warn("Warning, condition! Specific functionality may not work.")
//some default
} else {
//something else
}
}
However, since streams is a TaskKey, its value can only be accessed from tasks. Furthermore, my setting is reused by other settings therefore I don't have the option of defining it as a task.
Hence my question: what is the best way to print warnings during setting initialization?

sLog.value.warn("danger!")
sLog is a SettingKey[Logger] for use from setting initialization.

Related

Why doesnt my CoroutineScope stop the code until it has the Firebase data and is finished?

I created a CoroutineScope to get the data from Firebase before expanding a Card and showing that data in a listView. But the card expands while the CoroutineScope is still getting the data from Firebase and tries to display the listView with an empty list.
Here is my Expand Function inside the OnClickListener (StartPageActivity.customClassList is a List in a Object that is defined earlier):
var list : List<CustomClass> = ArrayList()
CoroutineScope(Dispatchers.IO).launch {
var customList: List<CustomClass> = ArrayList()
StartPageActivity.customClassExpandList.forEach {
if (it.title.contains(CustomClass.title)) {
customList += getFirebaseData(it.date)
if (customList.size == 12) {
list = customList
}
}
}
}
val listAdapter = MyListAdapter(context, list)
listView.adapter = listAdapter
listView.visibility = View.VISIBLE
listView.dividerHeight = 0
listView.layoutParams.height = calculateHeight(listView, 12)
Here is my getFirebaseData function:
suspend fun getFirebaseDate(date : LocalDate) : CustomClass = withContext(Dispatchers.IO){
val customClass = CustomClass("$date", date, "Empty", false)
FirebaseFirestore.getInstance().collection("users").document(FirebaseAuth.getInstance().currentUser!!.uid).collection("customClass")
.document(date.toString()).get().addOnCompleteListener { task ->
if (task.isSuccessful) {
val document = task.result
if (document.exists()) {
goal.description = document["description"].toString()
goal.title = document["tile"].toString()
}
}
}.await()
return#withContext customClass
}
The getFirebaseData function works and it returns the customClass; this is also added to my customList. But this happens while the code tries to build the expanded listView with the list, that is initiated before the CoroutineScope.
I tried to run the Code after the CoroutineScope inside that scope, but it doesn't allow that and returns an error.
I also tried adding multiple suspend functions, but that also has not fixed my problem.
I also tried putting the forEach function in a separate suspend function, but my problem still occurred.
Launching a coroutine queues it up to run in parallel or in the background, and the current function continues running without waiting for it. See here for more explanation.
To get the behavior you're expecting, you would need to use runBlocking instead of CoroutineScope(Dispatchers.IO).launch. However, this is not a viable solution for a network operation. The entire device will be completely frozen to user input and screen refreshes/animation until the coroutine is finished. If the network operation takes more than a few milliseconds, this will be unacceptable to the user, because they can't even back out of your app if they change their mind, among many other potential problems.
You must design your app to gracefully handle the fact that a network operation might take a while. This is typically done by showing some kind of loading indicator in the UI, and then you can start your coroutine, and then inside the coroutine you can update the list view when the results are ready.
Two other issues with your use of coroutines:
You should not create a new CoroutineScope like that. It will leak your fragment. Use viewLifecycleOwner.lifecycleScope.launch. And don't use Dispatchers.IO, because that will cause glitches and crashes if you start working with UI in your coroutine. You don't need Dispatchers.IO unless you're directly calling blocking code inside your coroutine, and if you do, you should wrap only those parts of the coroutine with withContext(Dispatchers.IO) { }.
In your suspend function, you should not mix using listeners and await(). That is convoluted and error prone. You're also neglecting the failure condition. If you don't use try/catch when using await(), you risk a crash or unhandled error (depending on how your coroutine scope is set up). Incidentally, you don't need to specify Dispatchers.IO here (like I mentioned above) because await() is not a blocking function. It's a suspending function. Your function should look something like this instead. I'm guessing that you are using CustomClass to communicate whether the retrieval was successful.
suspend fun getFirebaseDate(date : LocalDate) : CustomClass = try {
val document = FirebaseFirestore.getInstance()
.collection("users")
.document(FirebaseAuth.getInstance().currentUser!!.uid)
.collection("customClass")
.document(date.toString())
.await()
require(document.exists()) // Throw exception if it doesn't. Catch block will handle it.
goal.description = document["description"].toString()
goal.title = document["tile"].toString()
CustomClass("$date", date, "Empty", false)
} catch (e: Exception) {
CustomClass("$date", date, "Empty", true)
}

Use QTest macros (QVERIFY, QCOMPARE, etc.) in function other than the test function

In general, the macros QVERIFY, QCOMPARE, etc. shall not be used outside a test function. The reason is, that in case of a failure, they interrupt the test with a return.
If I want to do tests in a function, I should do them by hand and return false if one of them fails. Then call the function with QVERIFY. But when I do this, I miss out the detailed output of the macros like the line where the error occurred.
So I'm looking for a way to use the macros outside of a test function. One solution is to create my own macro that interrupts the test when a macro call in the underlying function fails. The main problem here is to detect when a test has failed. Looking into Qt's code, in case of a fail the variable QTest::failed is set to true. But I don't have access to this variable.
Is there a way to find out if a QtTest macro has failed?
Yeah, Qt does not really offer anything here because the test will not really get interrupted within your own function. The control flow cannot be as easily disturbed. You would need to throw an exception and make sure it's correctly caught.
What I'm doing now is just returning a const char* (works when using a string literal). If the function actually returns something, std::variant can be used, e.g.:
std::variant<MyObject, const char*> createObject() {
// do some preparations
if(preparationsFail) {
return "Error occurred";
// all worked
// ...: create some myObject
return myObject;
}
void MyTest::testFunction() {
auto result = createObject();
if(const char** error = std::get_if<const char*>(&result)) {
QVERIFY2(false, *error); // we get pointer to value, so type is **
}
// else, work with myObject by std::get<MyObject>(result);
}
Not as concise as would be desired, but it works.
It can be made more beautiful by wrapping const char* and, depending on your style, by using std::visit etc. but that's up to you and your style.

PNaCl: Handle another message while already in 'HandleMessage' function?

I'm using PNaCl and I'm in a situation where first I receive a message that is handled in the 'HandleMessage' function as the normal way, but then in the current HandleMessage execution, I need to wait for a user input that would come from an other message in order to complete the execution.
I'm wondering if this is possible to do that (handling a message while already waiting in the 'HandleMessage' function) ? And if so, can someone give me a trick ?
Thanks !
HandleMessage is currently called on one thread, the main thread. So you cannot receive a message while you are handling another message.
We typically suggest you spawn a new thread to do your work, and leave the main thread to handle messages, and queue them for the new thread to handle. Take a look at the nacl_io_demo example in the SDK for an example of this technique (found in examples/demo/nacl_io).
Another solution is to use a state machine; i.e. keep track of your current state in a variable instead of on the stack.
For example:
enum State {
STATE_INIT,
STATE_WAITING_FOR_INPUT,
STATE_DO_OTHER_STUFF,
};
State state_;
virtual void HandleMessage(const pp::Var& var_message) {
switch (state_) {
case STATE_INIT:
if (var_message.AsString() == "first_message") {
state_ = STATE_WAITING_FOR_INPUT;
// Do some work before you need the user input ...
}
break;
case STATE_WAITING_FOR_INPUT:
if (var_message.AsString() == "user_input") {
// Do more work, now that we've received input from the user...
state_ = STATE_DO_OTHER_STUFF;
}
break;
}
}

Rational Functional Tester - How can I get scripts called from a parent script to use the parent's data pool?

I'm fairly new to Rational Functional Tester (Java) but I have one large blank. I have an application that is in an agile development environment so some of the screens can flux as new interfaces are brought online.
For this reason I'm trying to modularize my test scripts. For example: I would like to have a login script, a search script, and a logout script.
I would then stitch these together (pseudo code)
Call Script components.security.Login;
Call Script components.search.Search;
//verification point
Call Script components.security.Logout;
By breaking the testing script into discrete chunks (functional units) I believe that I would be better able to adapt to change. If the login script changed, I would fix or re-record it once for every script in the application.
Then I would call that script, say, "TestSituation_001". It would have need to refer to several different data pools. In this instance a User datapool (instead of a superUser datapool) and a TestSituation_001 datapool, or possibly some other datapools as well. The verfication point would use the situational datapool for its check.
Now, this is how I would do it in an ideal world. What is bothering me at the moment is that it appears that I would need to do something entirely different in order to get the child scripts to inherit the parents.
So my questions are these:
Why don't child scripts just inherit the calling script's data pool?
How can I make them do it?
Am I making poor assumptions about the way this should work?
If #3 is true, then how can I do better?
As a side note, I don't mind hacking the heck out of some Java to make it work.
Thanks!
I solved my own problem. For those of you who are curious, check this out:
public abstract class MyTestHelper extends RationalTestScript
{
protected void useParentDataPool() {
if(this.getScriptCaller() != null) {
IDatapool dp = this.getScriptCaller().getDatapool();
IDatapoolIterator iterator = DatapoolFactory.get().open(dp, "");
if(dp != null && iterator != null) {
//if the datapool is not null, substitute it for the current data pool
this.dpInitialization(dp, iterator);
}
}
}
}
This will use the same iterator too. Happy hunting...
Actually, after some reflection, I made a method that would make any given script use the Root calling script's DataPool. Again, happy hunting to those who need it...
/*
* preconditions: there is a parent caller
* postconditions: the current script is now using the same datapool / datapool iterator as the root script
*/
protected void useRootDataPool() {
//if there is no parent, then this wouldn't work so return with no result;
if(this.getScriptCaller() == null) return;
//assume that we're at the root node to start
RationalTestScript root = this;
while(root.getScriptCaller() != null) {
root = root.getScriptCaller();
}
//if this node is the root node, no need to continue. the default attached datapool will suffice.
if(this.equals(root)) return;
//get the root's data pool (which would be the parent's parent and so on to the topmost)
IDatapool dp = root.getDatapool();
if(dp != null) {
//check to make sure that we're not trying to re-initialize with the same datapool (by name)
//if we are, then leave
if(dp.getName().equals(this.getDatapool().getName())) return;
//this basically says "give me the iterator already associated to this pool"
IDatapoolIterator iterator = DatapoolFactory.get().open(dp, "");
//if we have an iterator AND a data pool (from above), then we can initialize
if(iterator != null) {
//this method is never supposed to be run, but this works just fine.
this.dpInitialization(dp, iterator);
//log information
logInfo("Using data pool from root script: " + root.getScriptName());
}
}
}

In ActionScript, is there a way to test for existence of variable with datatype "Function"

So I have a class where I instantiate a variable callback like so:
public var callback:Function;
So far so good. Now, I want to add an event listener to this class and test for existence of the callback. I'm doing like so:
this.addEventListener(MouseEvent.MOUSE_OVER, function(event:MouseEvent) : void {
if (callback) {
// do some things
}
});
This works great, doesn't throw any errors, but everywhere I test for callback I get the following warning:
3553: Function value used where type Boolean was expected.
Possibly the parentheses () are missing after this function reference.
That bugged me, so I tried to get rid of the warning by testing for null and undefined. Those caused errors. I can't instantiate a Function as null, either.
I know, I know, real programmers only care about errors, not warnings. I will survive if this situation is not resolved. But it bothers me! :) Am I just being neurotic, or is there actually some way to test whether a real Function has been created without the IDE bitching about it?
Similar to using typeof:
if(callback is Function){
}
I believe should evaluate to true if the function exists and is a function and false if it is null or is not a function. (although if that doesn't work try if(callback && callback is function){}
if( !(callback == null)){
// do something
}
There's already an answer that works, but I thought I'd mention that you can also stop the warning from occurring by explicitly casting the result to a Boolean.
if (Boolean(callback)) {
// do something
}
Have you tried:
if (typeof callback == "function") {
// do some things
}
?
http://www.adobe.com/livedocs/flash/9.0/ActionScriptLangRefV3/operators.html#typeof

Resources