[libc-dev] Header files, include paths and gtest

Petr Hosek via libc-dev libc-dev at lists.llvm.org
Sat Jan 11 13:23:40 PST 2020


I think that's fine given that libc testing is a special case where you
want to have strict control over your header dependencies. In Zircon, we've
similarly ended up creating zxtest
<https://fuchsia.googlesource.com/fuchsia/+/refs/heads/master/zircon/system/ulib/zxtest/>,
a googletest-like framework that's much simpler and thus usable for testing
kernel constructs. In GN, we're also using a custom
<https://gn.googlesource.com/gn/+/refs/heads/master/src/util/test/>
googletest-like framework that's much simpler and faster (and it was in
turn derived from Ninja's which is even simpler). These might be useful as
an inspiration.
<https://gn.googlesource.com/gn/+/refs/heads/master/src/util/test/test.h>

On Sat, Jan 11, 2020 at 10:54 AM Siva Chandra via libc-dev <
libc-dev at lists.llvm.org> wrote:

> tl;dr - gtest is unittesting framework which uses the standard
> library. A circular dependency occurs when using gtest to test the
> standard library itself. [1] [2]
>
> To begin the long story, let me say a little about header files and
> include paths in llvm-libc. One of the implementation rules we want to
> follow is that header files should only be included using their local
> path in the implementation and test `.cpp` files. The same rule also
> is imposed on the internal header files like `src/sys/mman/mmap.h`.
> That is, the internal implementation header files like `mmap.h` should
> include `mman.h` using the full internal path `include/mmap.h` and not
> `<sys/mman.h>` or `"sys/mman.h"`. Likewise, the mmap unittest should
> include `sys/mman.h` using the full internal path `include/sys/mman.h`
> and not `<sys/mman.h>` or `"sys/mman.h"`. We need an implementation
> rule like this because we want to ensure that our implementations and
> tests only pick pieces from llvm-libc and not from the system-libc.
>
> I confess that I have accidentally, and also due to oversight in some
> cases, broken this rule in a few places. So, once I realized I had
> broken this rule, I tried fixing them. This attempt to fix is what
> brings us to the topic of this email.
>
> As far as the implementations in the `src` directory go, I did not
> face any problem fixing the places at which the rule was broken.
> However, as I started touching the tests, I ran into problems. The
> problem specifically was because of gtest. We use gtest for our
> unittests, but `gtest.h` includes string.h, time.h etc directly [3].
> As parts of a few standards require that some of the header files
> include other header files, llvm-libc's include paths are setup to
> lookup standard library headers from llvm-libc first. Because of this,
> gtest ends up getting llvm-libc's headers. We do not want gtest to be
> using llvm-libc's headers as it is not compiled against them. We
> cannot also change the include path order to enable gtest to get the
> system libc's headers because then, llvm-libc's public headers which
> include other public headers, will end up picking up systems libc
> headers.
>
> I could not come up with a clean solution to this problem other than
> disallowing gtest for unittests. Which means, we need a replacement
> which does not cause the problems I described above. For consistency,
> we want the interface of this replacement to be exactly like that of
> gtest. We do not however need this replacement to be as featureful as
> gtest (to begin with at least). As a demonstration, I have implemented
> a simple and lightweight framework and put it on my github account:
> https://github.com/sivachandra/unittest. I have also tested it with
> llvm-libc and verified that it solves the above header file problem
> and can be used as a drop-in replacement for gtest. Hence, I propose
> that we put this unittest framework in the llvm-libc tree (of course
> after a code review) and use it for setting up llvm-libc unittests. At
> the interface level, the experience will not be any different from
> using gtest (except that of including something different from
> `gtest/gtest.h`.)
>
> [1] At a fundamental level, gtest is not designed to test standard
> libraries.
> [2] Circular dependency can be of two kinds: header files and symbols.
> By ensuring that the tests call in to llvm-libc using internal names,
> we have avoided the circular dependeny wrt the symbols. So, when you
> link gtest with a test, we can be confident that gtest's library code
> does not call into llvm-libc.
> [3] To make our problem worse, LLVM's gtest pulls in headers from the
> LLVM Support library, which in turn pull in a large number of standard
> headers.
>
> Thanks,
> Siva Chandra
> _______________________________________________
> libc-dev mailing list
> libc-dev at lists.llvm.org
> https://lists.llvm.org/cgi-bin/mailman/listinfo/libc-dev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/libc-dev/attachments/20200111/21dc9248/attachment.html>


More information about the libc-dev mailing list