Open Bug 529330 Opened 10 years ago Updated 2 years ago

can't compile a compiled-code unit test for internal-only static function in netwerk

Categories

(Testing :: General, defect, minor)

defect
Not set
minor

Tracking

(Not tracked)

People

(Reporter: geekboy, Unassigned)

Details

I'm working on writing a static function in nsHttpChannel.cpp that is only used from within nsHttpChannel, but I want to be able to test that it is behaving properly (it is a parser).  

I created a binary unit test $(SRC)/netwerk/test/MyTest.cpp and modified $(SRC)/netwerk/test/Makefile.in so that it contained:
CPP_UNIT_TESTS = MyTest.cpp

My test wouldn't compile becuase it needed access to $(SRC)/netwerk/protocol/http/src/nsHttpChannel.h, which is not an exported header.  Additionally, the .h file uses the internal string API, so even if I attempted to add the include to the make target, a bunch of errors popped up saying I couldn't use internal string headers for external-linkage code. 

I also tried the same thing (with different #includes in the compiled code test) but putting the test file in CPPSRCS... but ended up with the same issues.

For some reason, if I were able to get it to compile, I imagine linking might be an issue since the .o file is not in the same directory as the unit tests, but I didn't get this far so I'm not sure.  Ted suggested adding a target-specific variable to take care of this, but I didn't get that far.

It would be nice to be able to quickly create a compiled code test that tests a static function in nsHttpChannel.cpp to make an easier unit test than one where I have to simulate an entire request/response process, then check how some database changed.
At one point we talked about building a static copy of libxul, and allowing unit tests to link to that directly, so you could use every internal API.

bsmedberg: could he work around this for one particular test by #defining MOZILLA_INTERNAL_API or something?
Oh, one other thing I didn't think to suggest is that you could #include the .cpp containing the function you wanted to test. Kind of ugly, but it's just a test.
That depends on what the code links against... you could only build the test in non-libxul configurations (which are getting rarer, though)... but #defining MOZILLA_INTERNAL_API won't actually get you through linkage, only compilation.
#define MOZILLA_INTERNAL_API helped immensely with the compilation, but I'm stuck at trying to link to necko to get the gHttpLog defined in there.  It links and runs fine if I define gHttpLog in the MyTest.cpp file, since necko isn't needed, but ideally I would like to link to necko (but for some reason everything I try is not working).  Here's a summary of what I did:

1.  moved the function into nsHttpChannel.h, and made it static
2.  #include "nsHttpChannel.h" in MyTest.cpp
3.  #define MOZILLA_INTERNAL_API in MyTest.cpp
4.  added some local includes to the /netwerk/test/Makefile.in:
 LOCAL_INCLUDES+= -I$(topsrcdir)/netwerk/protocol/http/src \
                  -I$(topsrcdir)/netwerk/base/src
So while that worked on my local machine (with both a libxul build and shared libs build) it doesn't seem to work on most of the try server nodes.  

I moved the parser function out of nsHttpChannel.h, and into its own file so that it's not included more than where it's needed.  

Now, when building on try server nodes (except WinCE) I get a linking error, specifying that there are tons of undefined symbols (all are internal string API stuff).

For example:
Undefined symbols:
  "nsACString_internal::nsACString_internal(char*, unsigned int, unsigned int)", referenced from:
      ParseStrictTransportHeader(nsACString_internal&, long long&, int&)in MyTest.o
      ParseStrictTransportHeader(nsACString_internal&, long long&, int&)in MyTest.o
      ParseStrictTransportHeader(nsACString_internal&, long long&, int&)in MyTest.o
      TestFailure(char const*)in TestSTS.o
      TestSuccess(char const*, long long, int)in TestSTS.o
  "nsACString_internal::~nsACString_internal()", referenced from:
      ParseStrictTransportHeader(nsACString_internal&, long long&, int&)in MyTest.o
      ParseStrictTransportHeader(nsACString_internal&, long long&, int&)in MyTest.o
      ParseStrictTransportHeader(nsACString_internal&, long long&, int&)in MyTest.o
      ParseStrictTransportHeader(nsACString_internal&, long long&, int&)in MyTest.o
      ParseStrictTransportHeader(nsACString_internal&, long long&, int&)in MyTest.o
      TestFailure(char const*)in TestSTS.o
      TestSuccess(char const*, long long, int)in TestSTS.o
  "nsAString_internal::nsAString_internal(unsigned short*, unsigned int, unsigned int)", referenced from:
      ScopedXPCOM::GetFile(char const*, int*, nsIFile**)in TestSTS.o
  "nsFixedCString::nsFixedCString(char*, unsigned int, unsigned int)", referenced from:
      ParseStrictTransportHeader(nsACString_internal&, long long&, int&)in MyTest.o
  "nsAString_internal::~nsAString_internal()", referenced from:
      ScopedXPCOM::GetFile(char const*, int*, nsIFile**)in TestSTS.o
  "nsACString_internal::nsACString_internal()", referenced from:
      ParseStrictTransportHeader(nsACString_internal&, long long&, int&)in MyTest.o
  "nsACString_internal::Assign(nsACString_internal const&)", referenced from:
      ParseStrictTransportHeader(nsACString_internal&, long long&, int&)in MyTest.o
  "CaseInsensitiveFindInReadable(nsACString_internal const&, nsReadingIterator<char>&, nsReadingIterator<char>&)", referenced from:
      ParseStrictTransportHeader(nsACString_internal&, long long&, int&)in MyTest.o
      ParseStrictTransportHeader(nsACString_internal&, long long&, int&)in MyTest.o
  "nsPromiseFlatCString::Init(nsACString_internal const&)", referenced from:
      ParseStrictTransportHeader(nsACString_internal&, long long&, int&)in MyTest.o
ld: symbol(s) not found
collect2: ld returned 1 exit status
The solution turned out to be simple (thanks to :bent).  In my .h file:
 #import "nsStringGlue.h"
Instead of nsString.h or nsStringAPI.h. That seemed to do the trick.

Recently, I ended up moving all my parser stuff out into an XPCOM service anyway, so testing became much simpler. 

It would still be nice if we could have netwerk unit tests that test individual internally-used-only static functions buried deep in netwerk, especially for things like parsers.  So I'm not going to close the bug just yet, although I'm no longer waiting on a fix.
You need to log in before you can comment on or make changes to this bug.