18

This is NOT a duplicate of Superiority of unnamed namespace over static? Please read the question carefully before marking it as duplicate. I am not asking why use an unnamed namespace versus static!
I am asking, why are google tests placed inside an unnamed namespace? Is this some convention that google tests follow, and if so, why? The tests work fine whether they are in an unnamed namespace or not, so obviously it is not required.**

I cloned google test from github and built it for my mac. It works fine, but I noticed in the sample test code they give they place the tests in an unnamed namespace. Does anyone know why?

For example, see following file: googletest/googletest/samples/sample1_unittest.cc (https://github.com/google/googletest/blob/master/googletest/samples/sample1_unittest.cc#L41)

Part of the file looks like this:

// Step 1. Include necessary header files such that the stuff your
// test logic needs is declared.
//
// Don't forget gtest.h, which declares the testing framework.

#include <limits.h>
#include "sample1.h"
#include "gtest/gtest.h"
namespace {

// Step 2. Use the TEST macro to define your tests.
...
TEST(FactorialTest, Negative) {
// This test is named "Negative", and belongs to the "FactorialTest"
// test case.
EXPECT_EQ(1, Factorial(-5));
EXPECT_EQ(1, Factorial(-1));
EXPECT_GT(Factorial(-10), 0);
}
...
}  // namespace

Does anyone know why all the tests are in an unnamed namespace? I tried removing the unnamed namespace and the sample still worked fine, so clearly it is not necessary for this particular sample.

alecxe
  • 462,703
  • 120
  • 1,088
  • 1,195
Daniel Goldfarb
  • 6,937
  • 5
  • 29
  • 61
  • 1
    Please read the question more carefully before marking it as a duplicate! – Daniel Goldfarb Dec 18 '17 at 04:01
  • 1
    Class definition can't be static, right? Why would you want to risk your test code clashing with your application code at link time? – Josh Lee Dec 18 '17 at 16:41
  • 5
    An example of good coding practice might not actually be necessary in a particular application of the example. It is good practice not to give external linkage to symbols gratuitously. You don't need to ask a programmer why *haven't* put stuff into the global namespace. You need to ask why they *have*. – Mike Kinghan Dec 18 '17 at 20:03
  • @Mike, good point. I especially like the phrase "You don't need to ask a programmer why haven't put stuff into the global namespace. You need to ask why they have." – Daniel Goldfarb Dec 19 '17 at 03:42

1 Answers1

10

I think the comment by Mike Kinghan answers the question, especially the part

You don't need to ask a programmer why haven't put stuff into the global namespace. You need to ask why they have.

However, I think its a good idea, pedagogically, to give an example of the kind of horrors that can happen if one doesn't follow good coding practices and as a consequence, violate ODR by mistake.

First, to relate the program below with the question, one needs to know that some of the Google Test macros create new classes. Now, consider the following program

myClass1.h

#ifndef MYCLASS1_H
#define MYCLASS1_H

int f();    

#endif  /* MYCLASS1_H */

myClass2.h

#ifndef MYCLASS2_H
#define MYCLASS2_H

int g();    

#endif  /* MYCLASS2_H */

myClass1.cpp

#include "myClass1.h"

class MyClass {
public:
    void twice() { val *= 2; }
    char val;
};    

int f() {
    MyClass x;
    x.val = 2;
    x.twice();
    return x.val;
}

myClass2.cpp

#include "myClass2.h"

class MyClass {
public:
    void twice() { val *= 2; }
    double val;
};    

int g() {
    MyClass x;
    x.val = 3;
    x.twice();
    return x.val;
}

main.cpp

#include <iostream>
#include "myClass1.h"
#include "myClass2.h"

int main() {
    std::cerr << f() << std::endl << g() << std::endl;
    return 0;
}

Notice how the class MyClass has two different definitions. With g++ 5.4.0-6ubuntu1~16.04.10, compiling and running the program with

g++ -O3 myClass1.cpp myClass2.cpp main.cpp -o undefined && ./undefined

prints 4 and 6, the expected behavior. However, compiling and running with no optimizations, i.e. with

g++ -O0 myClass1.cpp myClass2.cpp main.cpp -o undefined && ./undefined

prints 4 and 3!

Now, put this bug in a non-trivial program and you might easily loose an afternoon of debugging, especially if the bug laid dormant for a while. On the other hand, wrapping the classes in anonymous namespaces up-front takes no time at all and it prevents the bug. I think this illustrates one of the rationale behind some of the good coding practices: basic risk management.

Kevin
  • 1,064
  • 12
  • 14
  • 1
    Can you elaborate on this a little? Is it that a cast from `3` prefer to choose `char` as a target before finding the `float` alternative, but `x.twice()` gets linked to latter anyway? – corsel May 09 '19 at 10:46