Risky question about: #ifndef UNIT_TEST #include <Arduino.h> #endif

I fear this may an annoying question because of what I read in another post,

Is there another reference area that I am missing?

Google, perhaps ? The terms are not Arduino specific but relate to C and C++

Preprocessor directives - C++ Tutorials

I have googled. Problems: too vast, too specific (not applicable to my case), too advanced, poorly written English (or poorly understood)… When I did find something promising, a few lines in then I’m confused. So out of frustration, I risk being a nuisance by asking here.

I’ve been trying to use the IRremote and IRremoteESP8266 libraries, and have cut&pasted bits from examples, and now I can’t find the place I got this from:

#ifndef UNIT_TEST
#include <Arduino.h>
#endif

I read as much as I could from the link given in the above quote, which was really good because I had never heard of preprocessor directives before. So I’m glad that I know basically what they do, but that’s about it. I don’t want to go line by line with my deficiencies reading the documentation (assuming nobody wants me to, either), but if I could just ask for a brief For Dummies (or even For Abject Morons) explanation of what this code does I would be forever grateful. In particular, why is the #include<Arduino.h> needed? Most of the examples have that line, such as IRrecvDemo, IRsendDemo, and DumbIRRepeater (but those don’t have #ifndef #endif).

Thanks (or sorry)

Without the context of where it is used, the only thing that can be said is: The preprocessor checks to see if the macro UNIT_TEST is defined. If it is not, the preprocessor includes the Arduino.h file.

If you want more detail, you'll need to supply more context.

Beavis4ever:
if I could just ask for a brief For Dummies (or even For Abject Morons) explanation of what this code does I would be forever grateful.

If the UNIT_TEST macro is not defined, include the file Arduino.h.

Beavis4ever:
In particular, why is the #include<Arduino.h> needed?

Arduino.h contains the declarations of the standard Arduino API functions (e.g., pinMode, digitalWrite, digitalRead). An #include directive for Arduino.h is automatically added to the .ino file in your sketch so you are used to being able to use the Arduino API functions without this #include directive, but that is not done in any other file type so libraries need to have this #include directive if they use the Arduino API. Some programmers add the #include directive to their sketches as well, even though it is unnecessary (at least not when using the Arduino IDE, it’s possible some other IDE’s don’t fully emulate the behavior of the Arduino IDE and do require this code).

So now you know why it’s needed, this begs the question: why is it not needed when UNIT_TEST is defined? This question is a bit difficult to answer because you didn’t provide a link to where you found this code. I checked the IRrecvDemo example sketch of both standard versions of the IRremote and IRremoteESP8266 libraries and they don’t contain this code so you must have dug up some random modified version of those libraries somewhere. I’ll try my best going on some guesswork though: The reason is that the core library that defines the standard Arduino API uses hardware-specific code for the target microcontroller architecture, but the unit tests are run on a PC for which this code doesn’t compile. So the unit test framework must provide its own version of the core library, with mocks or stubs of these functions.

@gfvalvo Thanks for the reply. Sorry I didn't have more specifics posted, but I was unable to find the source of that code. It wasn't from the examples I've been using (I double checked), and combing through my browser history rarely pays off if I can't narrow down the time frame.
I'm getting more comfortable with things that happen outside of "the program" (that which I LOAD and can then LIST - re: TRS-80) so I think I get what the # is doing before the "if". Now that that's been tamed, I'm wondering about the "macro" it's checking for. Some remote controls have a "macro" feature which happens when the ON/OFF gets a long press. It then sends out multiple signals to the boxes you want to power up (after specifying them during setup). In this environment, I'm guessing, macros are like scripts which automate a number of tasks instead of typing them in one by one. I can't think of any examples, but am I close?
Thanks again for your infinite patience, it is greatly appreciated!

No need to guess, see these links:
https://en.cppreference.com/w/cpp/preprocessor
https://en.cppreference.com/w/cpp/preprocessor/conditional
https://en.cppreference.com/w/cpp/preprocessor/replace

Pieter

The "UNIT_TEST" identifier is used by PlatformIO (see: http://platformio.org) when it is testing code separate from the rest of a project. If it allowed Arduino functions it would not be able to test code on a PC because there is no Arduino runtime for the PC.

Since the IRremoteESP8266 library is no longer unit tested with PlatformIO, that test is unnecessary and can be removed.

@pert Again, you have been so very helpful. It's such a relief when I read something and it actually makes sense!

...you didn't provide a link to where you found this code... you must have dug up some random modified version of those libraries somewhere.

Yeah, I don't know where it came from (I certainly didn't write it myself!), I sat in a quiet spot trying hard to remember (results rare), I checked the examples I've been using (again), and skimmed some of my browser history (grouped by location) but soon gave up because I've typically had diminishing returns the further back I go. I didn't want to make extra work for you by leaving loose ends like that. I'm not too worried by the specifics of what UNIT_TEST does, maybe down the road if I'm using the library again I'll want to investigate further. But for my current project I was just trying to get a "big picture"; something named"Arduino.h" felt rather fundamental and worthy of investigation. Thanks so much for your finely tuned explanation, it's exactly what I was hoping for!

@PieterP and @johnwasser Thanks for the links, it's really helpful when getting a targeted referral based on my situation. I have some new info to process, like "identifier" and apparently a whole other world (or at least another entity) that is PlatformIO. Whereas those things would have just blended into the rest of the infinite backgorund sea of confusion, I now have a context in which to place those "things" (a word I blatantly overuse out of desperation) so that I have a good "vector" for investigation.
Thanks again!

Beavis4ever:
I’m wondering about the “macro” it’s checking for. Some remote controls have a “macro” feature which happens when the ON/OFF gets a long press. It then sends out multiple signals to the boxes you want to power up (after specifying them during setup). In this environment, I’m guessing, macros are like scripts which automate a number of tasks instead of typing them in one by one.

You probably already understand from looking at the links provided by PieterP, but just in case, I’ll give a quick overview. Preprocessor macros are created using #define. The preprocessor will do a text replace everywhere the macro occurs in your code. So if you have code like this:

#define FOOBAR 42
void setup() {
  Serial.begin(9600);
  while(!Serial){}
  Serial.println(FOOBAR);
}

void loop() {}

So after preprocessing, the code looks like this:

#define FOOBAR 42
void setup() {
  Serial.begin(9600);
  while(!Serial){}
  Serial.println(42);
}

void loop() {}

The most simple macro looks like this:

#define UNIT_TEST

That doesn’t actually give the UNIT_TEST macro any value, but it’s useful as a configuration flag for preprocessor conditional statements:

#ifdef UNIT_TEST
#include <Arduino.h>
#endif

This just checks if the UNIT_TEST macro was defined or not so the value of UNIT_TEST is irrelevant.

You can also make macro functions. For example, here is Arduino’s definition of abs():

#define abs(x) ((x)>0?(x):-(x))

Compared to a standard function, this has the advantage of being able to work with any argument type, since it just does a text substitution. So if you have this code:

abs(42);

it looks like this after preprocessing:

((42)>0?(42):-(42))

Preprocessor directives can allow you to do things that are not possible to do any other way and can be extremely useful. However, they can also make your code very difficult to understand and debug. For this reason, I recommend only using the preprocessor when there is no other option. The UNIT_TEST case is a perfect example. This sort of code won’t work:

bool unitTest = true;
if (unitTest == true) {
  #include <Arduino.h>
}

So it was absolutely necessary to use the preprocessor.

Beavis4ever:
@pert Again, you have been so very helpful.

I’m glad if I was able to be of assistance.