Test.debug is not working in delegates and it's not advertised in documentation

Former Member
Former Member
Hello, it turns out it's pretty useless to call Test.assert() in delegate callbacks, e.g. I'm trying to call Test.debug in Menu2InputDelegate.onSelect, and it seems that it results in callback (onSelect) being terminated (if assert fails), but no message is being written anywhere. Took some time to figure this out. I'm not sure I've seen any mentions of such behavior in SDK documentation.
  • There are actually two issues here...

    Not getting error output in the eclipse console for all errors is a known issue. We have an bug filed to review the simulator code for these problems, but we have not yet started working on it.

    The second issue is that you probably shouldn't use the Test module outside of test functions (those annotated with (:test)). The reason is that the Test module doesn't exist in release builds, and attempts to call into it will result in Symbol Not Found errors.

    Travis
  • Former Member
    Former Member over 6 years ago
    The second issue is that you probably shouldn't use the Test module outside of test functions (those annotated with (:test)). The reason is that the Testmodule doesn't exist in release builds, and attempts to call into it will result in Symbol Not Found errors.

    Travis.ConnectIQ well, the Garmin SDK documentation does not support this statement. Please see these 2 quotes from the SDK (they are from "Run no evil" section):

    Asserts are a useful way to check for conditions at critical points in your code.

    Assert code requires no special compiler commands to execute within the simulator, and are removed by the compiler when building release code.


    Effectively, this means devs are encouraged to use asserts in their code to do additional checks on simulator, and, and it seems the assertXXX functions are marked with (:test) themselves, thus they will be stripped off from the release builds, causing no troubles on a real devices. This is the common practice, btw. And using asserts in unit tests seems weird, because in ConnectIQ tests were designed to return true/false to indicate success/failure, not assert.XXX (unlike, say, NUnit framework for .NET).
  • The API documentation says something similar:

    https://developer.garmin.com/downloa...ybox/Test.html
    The test module provides the tools to implement your own unit test and asserts in your source code. Unit tests take a Logger object and allow for different levels of output. Unit tests are annotated with :test and ignored if testing is not run. Asserts do not require the :test annotation and will be compiled out in release versions or you Connect IQ Content. A test RESULTS section is printed to the console with the tests run, test status, and failure rates.

    And gives an example:
    // Asserts can be called outside of test calls
    function assertWithoutLogger(x, y) {
    Test.assertEqual(x, y);
    }


    Sorry to be "that guy" and ask the obvious question, but isn't line-by-line exclusion of code impossible in Monkey C? Is this a special exception or is the documentation wrong? (Maybe I'm taking the phrase "will be compiled out" too literally.)

    Or is it actually the case that Test.assertEqual() and other assert functions are simply replaced by no-ops in release code?

    Because of course it makes a difference if you want to save memory....
  • So in attempting to answer my own question, I compiled the following code as a simple data field:
    function compute(info) {
    Test.assert(true);
    return 5;
    }


    It ran in the simulator, naturally.

    I compiled it in release mode and sideloaded it to my 935. It crashed at the Test.assert() line (*) with:
    Error: Symbol Not Found Error
    Details: 'Failed invoking <symbol>'

    (*) Based on the PC

    Just as was predicted.

    So I guess the documentation is an example of wishful thinking. (We've all been there, I get it.)

    On a completely unrelated note, now is anyone interested in my line-by-line conditional compilation script? (jk it's legit awful and should only be used as a last resort if you want to cram a million and one features into one data field, for some reason.)
  • Former Member
    Former Member over 6 years ago
    So, it's either a bug in the compiler, or in the documentation. It would be better if it's a compiler bug, which can be fixed then, giving us a nice possibility to use asserts during development.
  • I think it would be very interesting if the compiler was meant to be hardcoded to literally "compile-out" (remove) references to certain functions like Test.assert*(), since "compiling-out code" (on a line-by-line basis) is not an existing feature (available to developers, at least). Since there are no Monkey C language features to facilitate this, such as macros or inline functions, I have to wonder how this would be accomplished without using an unwieldy hack.

    Based on everything I know about Monkey C (not much), it seems more likely that the intent was to provide a "stub" Test class with no-ops for the assert*() functions. Which would still be fine, but you'd have the overhead of function calls in release mode. And the release build would also retain any side effects of whatever parameters you passed into asserts. (Depending on your POV, this might be a good thing).

    It's all just baseless speculation on my part tho.

    On a related note, is there a supported way to build and run a release binary in the simulator? Would've been nice to able to easily test this in the sim. (I'm hoping I didn't once again miss something basic....) I'm sure I could've done it manually by copying PRGs, etc.
  • Building a release version of a .prg is easily done with a checkbox in the the "Build for Device Wizard" (build to your hard drive), and I don't see why you can't manually launch the sim with that prg/device, but not tried it myself and not sure of the steps/arguments.
  • jim_m_58 yes as I said, I realize I could've done it manually. I only meant I wish there was a supported way to do this automatically, but on second thought, nvm. I realize that it must be such a rare use case that it's pointless even mentioning it....
  • I only point out this limitation because I discovered it myself last year and pointed to the same documentation. The asserts should end up being no-ops, but the call itself is not likely to go away because that would require some compiler hackery.

    The issue has been filed and scheduled, but work has not yet been started.
  • Travis.ConnectIQ Thanks for the clarification and the inside info. Your previous comment in the thread seemed to imply that we were never supposed to call Test.assert*() in the first place. But maybe I read too much into it.

    This is where I will once again say that I wish there was greater transparency (or any at all) for known issues like this. Obviously Garmin knows about it, yet the incorrect advice to use Test.assert() remains in the API documentation and the programmer's guide. There's no note that says "this isn't working at the moment, please don't use!". (I can def understand why not.) But there's also no developer-facing issue tracker that can be referenced, so we know what to expect. I get it, as very few companies (or individual devs) are willing to provide this level of detail, and it's understandable why.

    But personally, I have wasted time and/or released partially broken apps to the store because of other bugs that were known to Garmin (but not me). And I gather that some devs literally have a dozen Garmin devices to test with, but I'm sure most don't. (Here I'm speaking of known device-specific bugs.) Then again, you are very generous with your time in helping people on these boards, so it's definitely appreciated.

    Sorry to beat a dead horse, I know it's beyond your control. Thanks again!