<div dir="ltr"><div dir="ltr">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 <a href="https://fuchsia.googlesource.com/fuchsia/+/refs/heads/master/zircon/system/ulib/zxtest/">zxtest</a>, a googletest-like framework that's much simpler and thus usable for testing kernel constructs. In GN, we're also using a <a href="https://gn.googlesource.com/gn/+/refs/heads/master/src/util/test/">custom</a> 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.<div><a href="https://gn.googlesource.com/gn/+/refs/heads/master/src/util/test/test.h"></a></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Sat, Jan 11, 2020 at 10:54 AM Siva Chandra via libc-dev <<a href="mailto:libc-dev@lists.llvm.org">libc-dev@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">tl;dr - gtest is unittesting framework which uses the standard<br>
library. A circular dependency occurs when using gtest to test the<br>
standard library itself. [1] [2]<br>
<br>
To begin the long story, let me say a little about header files and<br>
include paths in llvm-libc. One of the implementation rules we want to<br>
follow is that header files should only be included using their local<br>
path in the implementation and test `.cpp` files. The same rule also<br>
is imposed on the internal header files like `src/sys/mman/mmap.h`.<br>
That is, the internal implementation header files like `mmap.h` should<br>
include `mman.h` using the full internal path `include/mmap.h` and not<br>
`<sys/mman.h>` or `"sys/mman.h"`. Likewise, the mmap unittest should<br>
include `sys/mman.h` using the full internal path `include/sys/mman.h`<br>
and not `<sys/mman.h>` or `"sys/mman.h"`. We need an implementation<br>
rule like this because we want to ensure that our implementations and<br>
tests only pick pieces from llvm-libc and not from the system-libc.<br>
<br>
I confess that I have accidentally, and also due to oversight in some<br>
cases, broken this rule in a few places. So, once I realized I had<br>
broken this rule, I tried fixing them. This attempt to fix is what<br>
brings us to the topic of this email.<br>
<br>
As far as the implementations in the `src` directory go, I did not<br>
face any problem fixing the places at which the rule was broken.<br>
However, as I started touching the tests, I ran into problems. The<br>
problem specifically was because of gtest. We use gtest for our<br>
unittests, but `gtest.h` includes string.h, time.h etc directly [3].<br>
As parts of a few standards require that some of the header files<br>
include other header files, llvm-libc's include paths are setup to<br>
lookup standard library headers from llvm-libc first. Because of this,<br>
gtest ends up getting llvm-libc's headers. We do not want gtest to be<br>
using llvm-libc's headers as it is not compiled against them. We<br>
cannot also change the include path order to enable gtest to get the<br>
system libc's headers because then, llvm-libc's public headers which<br>
include other public headers, will end up picking up systems libc<br>
headers.<br>
<br>
I could not come up with a clean solution to this problem other than<br>
disallowing gtest for unittests. Which means, we need a replacement<br>
which does not cause the problems I described above. For consistency,<br>
we want the interface of this replacement to be exactly like that of<br>
gtest. We do not however need this replacement to be as featureful as<br>
gtest (to begin with at least). As a demonstration, I have implemented<br>
a simple and lightweight framework and put it on my github account:<br>
<a href="https://github.com/sivachandra/unittest" rel="noreferrer" target="_blank">https://github.com/sivachandra/unittest</a>. I have also tested it with<br>
llvm-libc and verified that it solves the above header file problem<br>
and can be used as a drop-in replacement for gtest. Hence, I propose<br>
that we put this unittest framework in the llvm-libc tree (of course<br>
after a code review) and use it for setting up llvm-libc unittests. At<br>
the interface level, the experience will not be any different from<br>
using gtest (except that of including something different from<br>
`gtest/gtest.h`.)<br>
<br>
[1] At a fundamental level, gtest is not designed to test standard libraries.<br>
[2] Circular dependency can be of two kinds: header files and symbols.<br>
By ensuring that the tests call in to llvm-libc using internal names,<br>
we have avoided the circular dependeny wrt the symbols. So, when you<br>
link gtest with a test, we can be confident that gtest's library code<br>
does not call into llvm-libc.<br>
[3] To make our problem worse, LLVM's gtest pulls in headers from the<br>
LLVM Support library, which in turn pull in a large number of standard<br>
headers.<br>
<br>
Thanks,<br>
Siva Chandra<br>
_______________________________________________<br>
libc-dev mailing list<br>
<a href="mailto:libc-dev@lists.llvm.org" target="_blank">libc-dev@lists.llvm.org</a><br>
<a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/libc-dev" rel="noreferrer" target="_blank">https://lists.llvm.org/cgi-bin/mailman/listinfo/libc-dev</a><br>
</blockquote></div></div>