Commits

Matt Oswald  committed f5a94cc

updates for building in Ubuntu
(kind of wishing I had noticed <filesystem> was an experimental future TR2 thing, I feel like an idiot :) )

  • Participants
  • Parent commits 55c1141

Comments (0)

Files changed (14)

File .build/build.props

       <WarningLevel>Level4</WarningLevel>
       <MultiProcessorCompilation>true</MultiProcessorCompilation>
       <MinimalRebuild>false</MinimalRebuild>
+      <PreprocessorDefinitions>WIN32</PreprocessorDefinitions>
     </ClCompile>
     <Link>
       <GenerateDebugInformation>true</GenerateDebugInformation>
     </Link>
   </ItemDefinitionGroup>
   <ItemGroup />
-</Project>
+</Project>

File .build/build.sconscript

 
 if env['windows'] == True:
     SConscript('msvc.sconscript', exports = 'env')
-
-env.Append(CCFLAGS = [ '/W4', '/WX-' ])
+else:
+    env['CXX'] = 'g++-4.7'
+    #env.Append(CCFLAGS = [ '-Wall', '-Wextra', '-pedantic', '-fpermissive', '-std=c++11' ])
+    env.Append(CCFLAGS = [ '-fpermissive', '-w', '-std=c++11' ])

File .build/msvc.sconscript

 Import('env')
 
+copy.Append(CPPDEFINES = ['WIN32'])
 env.Append(CCFLAGS = [ '/EHsc' ])
 
 if env['debug'] == True:

File xUnit++.console/CommandLine.cpp

 #include "CommandLine.h"
-#include <filesystem>
 #include <functional>
 #include <queue>
 #include <sstream>
     bool GetInt(std::queue<std::string> &queue, int &value)
     {
         std::istringstream stream(TakeFront(queue));
-        
+
         stream >> value;
 
         return stream.failbit;
     {
         auto exe = [=]()
         {
-            return std::tr2::sys::path(argv[0]).leaf();
+            std::string path = argv[0];
+            std::replace(path.begin(), path.end(), '\\', '/');
+
+            auto idx = path.find_last_of('/');
+
+            if (idx != std::string::npos)
+            {
+                return path.substr(idx + 1);
+            }
+
+            return path;
         };
 
         std::queue<std::string> arguments;

File xUnit++.console/TestAssembly.cpp

+#include "TestAssembly.h"
+
+#if !defined(WIN32)
+#include <cstdio>
+#include <dlfcn.h>
+#include <fcntl.h>
+#include <unistd.h>
+#endif
+
+namespace
+{
+#if defined(WIN32)
+    std::string CopyFile(const std::string &file)
+    {
+        char tempPath[MAX_PATH] = {0};
+        if (GetTempPath(MAX_PATH, tempPath) > 0)
+        {
+            if (GetTempFileName(tempPath, "xU+", 0, tempPath) != 0)
+            {
+                if (::CopyFile(file.c_str(), tempPath, FALSE))
+                {
+                    return tempPath;
+                }
+            }
+        }
+
+        return "";
+    }
+#else
+    std::string CopyFile(const std::string &file)
+    {
+        std::string result;
+
+        char buf[BUFSIZ];
+        size_t size;
+
+        char tempFile[] = "/tmp/xU+XXXXXX";
+
+        int source = open(file.c_str(), O_RDONLY, 0);
+        int dest = mkstemp(tempFile);
+
+        if (source > 0)
+        {
+            if (dest > 0)
+            {
+                while ((size = read(source, buf, BUFSIZ)) > 0)
+                {
+                    write(dest, buf, size);
+                }
+
+                result = tempFile;
+
+                close(dest);
+            }
+
+            close(source);
+        }
+
+        return result;
+    }
+#endif
+}
+
+namespace xUnitpp
+{
+
+TestAssembly::TestAssembly(const std::string &file)
+    : EnumerateTestDetails(nullptr)
+    , FilteredTestsRunner(nullptr)
+    , tempFile(CopyFile(file))
+    , module(nullptr)
+{
+    if (!tempFile.empty())
+    {
+#if defined(WIN32)
+        if ((module = LoadLibrary(tempFile.c_str())) != nullptr)
+        {
+            EnumerateTestDetails = (xUnitpp::EnumerateTestDetails)GetProcAddress(module, "EnumerateTestDetails");
+            FilteredTestsRunner = (xUnitpp::FilteredTestsRunner)GetProcAddress(module, "FilteredTestsRunner");
+        }
+#else
+        if ((module = dlopen(tempFile.c_str(), RTLD_LAZY)) != nullptr)
+        {
+            EnumerateTestDetails = (xUnitpp::EnumerateTestDetails)dlsym(module, "EnumerateTestDetails");
+            FilteredTestsRunner = (xUnitpp::FilteredTestsRunner)dlsym(module, "FilteredTestsRunner");
+        }
+#endif
+    }
+}
+
+TestAssembly::~TestAssembly()
+{
+    if (module)
+    {
+#if defined(WIN32)
+        FreeLibrary(module);
+#else
+        dlclose(module);
+#endif
+    }
+
+    if (!tempFile.empty())
+    {
+#if defined(WIN32)
+        DeleteFile(tempFile.c_str());
+#else
+        std::remove(tempFile.c_str());
+#endif
+    }
+}
+
+bool TestAssembly::is_valid() const
+{
+    return EnumerateTestDetails != nullptr && FilteredTestsRunner != nullptr;
+}
+
+TestAssembly::operator bool_type() const
+{
+    return is_valid() ? &TestAssembly::is_valid : nullptr;
+}
+
+}

File xUnit++.console/TestAssembly.h

+#ifndef TESTASSEMBLY_H_
+#define TESTASSEMBLY_H_
+
+#if defined(WIN32)
+#include <Windows.h>
+#endif
+
+#include <string>
+#include "xUnit++/ExportApi.h"
+
+namespace xUnitpp
+{
+
+class TestAssembly
+{
+private:
+    typedef bool (TestAssembly::*bool_type)() const;
+    bool is_valid() const;
+
+#if !defined(WIN32)
+    typedef void * HMODULE;
+#endif
+
+public:
+    TestAssembly(const std::string &file);
+    ~TestAssembly();
+
+    // !!!VS enable this when Visual Studio supports it
+    //explicit operator bool() const
+    //{
+    //    return module != nullptr;
+    //}
+
+    operator bool_type() const;
+
+    xUnitpp::EnumerateTestDetails EnumerateTestDetails;
+    xUnitpp::FilteredTestsRunner FilteredTestsRunner;
+
+private:
+    std::string tempFile;
+    HMODULE module;
+};
+
+}
+
+#endif

File xUnit++.console/main.cpp

 #include <string>
 #include <tuple>
 #include <vector>
-#include <Windows.h>
 #include "xUnit++/ExportApi.h"
 #include "xUnit++/TestDetails.h"
 #include "CommandLine.h"
 #include "StdOutReporter.h"
+#include "TestAssembly.h"
 #include "XmlReporter.h"
 
+
 int main(int argc, char **argv)
 {
     xUnitpp::Utilities::CommandLine::Options options;
 
     for (const auto &lib : options.libraries)
     {
-        auto testlib = LoadLibrary(lib.c_str());
+        auto testAssembly = xUnitpp::TestAssembly(lib.c_str());
 
-        if (testlib == nullptr)
+        if (!testAssembly)
         {
-            std::cerr << "unable to load " << lib << std::endl;
-            forcedFailure = true;
-            continue;
-        }
-
-        xUnitpp::EnumerateTestDetails enumerateTests = (xUnitpp::EnumerateTestDetails)GetProcAddress(testlib, "EnumerateTestDetails");
-
-        if (!enumerateTests)
-        {
-            std::cerr << "unable to load EnumerateTestDetails" << std::endl;
+            std::cerr << "Unable to load " << lib << std::endl;
             forcedFailure = true;
             continue;
         }
                 }
             };
 
-        enumerateTests([&](const xUnitpp::TestDetails &td)
+        testAssembly.EnumerateTestDetails([&](const xUnitpp::TestDetails &td)
             {
                 // check suites:
                 // if any suites are specified, a test has to belong to one of them to be run
         {
             std::sort(activeTestIds.begin(), activeTestIds.end());
 
-            xUnitpp::FilteredTestsRunner filteredTestRunner = (xUnitpp::FilteredTestsRunner)GetProcAddress(testlib, "FilteredTestsRunner");
-
-            if (!filteredTestRunner)
-            {
-                std::cerr << "unable to get FilteredTestsRunner" << std::endl;
-                forcedFailure = true;
-                continue;
-            }
-
             std::unique_ptr<xUnitpp::IOutput> reporter(options.xmlOutput.empty() ?
                 (xUnitpp::IOutput *)new xUnitpp::StdOutReporter(options.verbose, options.veryVerbose) :
                 (xUnitpp::IOutput *)new xUnitpp::XmlReporter(options.xmlOutput));
-            totalFailures += filteredTestRunner(options.timeLimit, options.threadLimit, *reporter,
+            totalFailures += testAssembly.FilteredTestsRunner(options.timeLimit, options.threadLimit, *reporter,
                 [&](const xUnitpp::TestDetails &testDetails)
                 {
                     return std::binary_search(activeTestIds.begin(), activeTestIds.end(), testDetails.Id);

File xUnit++.console/sconscript

 local.VariantDir(intDir, './', duplicate = 0)
 local.Append(CPPPATH = ['../xUnit++'])
 
-target = local.Program(targetFile + '.exe', Glob(intDir + '*.cpp'), LIBS = env['xUnit'])
+target = local.Program(targetFile + '.exe', Glob(intDir + '*.cpp'), LIBS = [env['xUnit'], 'dl' ])
 
 Return('target')

File xUnit++.console/xUnit++.console.vcxproj

     <ClCompile Include="CommandLine.cpp" />
     <ClCompile Include="main.cpp" />
     <ClCompile Include="StdOutReporter.cpp" />
+    <ClCompile Include="TestAssembly.cpp" />
     <ClCompile Include="XmlReporter.cpp" />
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <ClInclude Include="CommandLine.h" />
     <ClInclude Include="StdOutReporter.h" />
+    <ClInclude Include="TestAssembly.h" />
     <ClInclude Include="XmlReporter.h" />
   </ItemGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

File xUnit++.console/xUnit++.console.vcxproj.filters

     <ClCompile Include="CommandLine.cpp" />
     <ClCompile Include="StdOutReporter.cpp" />
     <ClCompile Include="XmlReporter.cpp" />
+    <ClCompile Include="TestAssembly.cpp" />
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="CommandLine.h" />
     <ClInclude Include="StdOutReporter.h" />
     <ClInclude Include="XmlReporter.h" />
+    <ClInclude Include="TestAssembly.h" />
   </ItemGroup>
 </Project>

File xUnit++/src/xUnitAssert.cpp

         if (!userMsg.empty())
         {
             msg += ": ";
-            
+
             for (const auto &s : userMsg)
             {
                 msg += s;
     return lineInfo;
 }
 
-const char *xUnitAssert::what() const
+const char *xUnitAssert::what() const noexcept(true)
 {
     if (whatMessage.empty())
     {
         // http://akrzemi1.wordpress.com/2011/09/21/destructors-that-throw/
         // throwing destructors aren't Evil, just misunderstood
         OnFailureComplete(assert);
-    } 
+    }
 }
 
 xUnitFailure xUnitFailure::None()

File xUnit++/src/xUnitTestRunner.cpp

         std::condition_variable condition;
     } threadCounter(maxConcurrent);
 
-    std::atomic<int> failedTests = 0;
+    std::atomic<int> failedTests(0);
     int skippedTests = 0;
 
     SharedOutput sharedOutput(output);
                                 }
                             }
                         };
-                        
+
                         try
                         {
                             output->ReportStart(runningTest.TestDetails());
     {
         test.get();
     }
-    
+
     sharedOutput.ReportAllTestsComplete((int)futures.size(), skippedTests, failedTests, Time::ToDuration(Time::Clock::now() - timeStart));
 
     return failedTests;
 }
 
-}
+}

File xUnit++/xUnit++/ExportApi.h

 #include <memory>
 #include <vector>
 
+#if !defined(WIN32)
+# define __declspec(x)
+#endif
+
 namespace xUnitpp
 {
     struct IOutput;

File xUnit++/xUnit++/xUnitAssert.h

 #include <exception>
 #include <functional>
 #include <sstream>
+#include <stdexcept>
 #include <string>
 #include <type_traits>
 #include <vector>
 
     static const xUnitAssert &None();
 
-    virtual const char *what() const override;
+    virtual const char *what() const noexcept(true) override;
 
 private:
     xUnitpp::LineInfo lineInfo;
     typename std::enable_if<!has_empty<TSequence>::value, xUnitFailure>::type Empty(const TSequence &sequence, const LineInfo &lineInfo = LineInfo::empty()) const
     {
         using namespace std;
-    
+
         if (begin(sequence) != end(sequence))
         {
             return OnFailure(xUnitAssert(callPrefix + "Empty", lineInfo));
     template<typename TSequence, typename T>
     xUnitFailure Contains(const TSequence &sequence, T value, const LineInfo &lineInfo = LineInfo::empty()) const
     {
-        return ContainsPred(sequence, [&value](const T &actual) { return actual == value; }, lineInfo); 
+        return ContainsPred(sequence, [&value](const T &actual) { return actual == value; }, lineInfo);
     }
 
     xUnitFailure Contains(const char *actualString, const char *value, const LineInfo &lineInfo = LineInfo::empty()) const;