├── .gitignore ├── .gitmodules ├── test ├── example-output │ ├── gcc-missing-include-path.txt │ ├── gcc-missing-include-partial-path.txt │ ├── gcc-other-error.txt │ ├── gcc-warning.txt │ ├── gcc-undeclared-error.txt │ ├── gcc-link-error-legacy.txt │ ├── clang-link-errors.txt │ ├── gcc-link-errors.txt │ └── vs-link-errors.txt ├── all-tests.sh ├── golden │ ├── xfakes-gcc-sorted-undefines.txt │ ├── xfakes-clang-cpp-globals.cpp │ ├── xfakes-clang-sorted-undefines.txt │ ├── xfakes-vs-cpp-globals.cpp │ ├── xfakes-gcc-cpp-globals.cpp │ ├── xfakes-vs-sorted-undefines.txt │ ├── xfakes-clang-c.c │ ├── xfakes-vs-c.c │ ├── xfakes-gcc-c.c │ ├── xfakes-gcc-cpp.cpp │ ├── xfakes-vs-cpp.cpp │ └── xfakes-clang-cpp.cpp ├── test-gen-xfakes.sh └── test-legacy-suggest.sh ├── gen-xfakes.sublime-project ├── LICENSE ├── legacy-build.sh ├── README.md ├── gen-xfakes.sh └── legacy-suggest.sh /.gitignore: -------------------------------------------------------------------------------- 1 | tmp/ 2 | *.sublime-workspace 3 | *.out 4 | client*/ -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "shunit2"] 2 | path = shunit2 3 | url = https://github.com/kward/shunit2.git 4 | -------------------------------------------------------------------------------- /test/example-output/gcc-missing-include-path.txt: -------------------------------------------------------------------------------- 1 | In file included from tests/FooBarTest.cpp:6: 2 | ./somepath/somefile.h:10:10: fatal error: Filename.h: No such file or directory 3 | 10 | #include "Filename.h" 4 | | ^~~~~~~~~~~ 5 | compilation terminated. 6 | -------------------------------------------------------------------------------- /test/example-output/gcc-missing-include-partial-path.txt: -------------------------------------------------------------------------------- 1 | In file included from tests/FooBarTest.cpp:6: 2 | ./somepath/somefile.h:10:10: fatal error: foo/bar/Filename.h: No such file or directory 3 | 10 | #include "foo/bar/Filename.h" 4 | | ^~~~~~~~~~~ 5 | compilation terminated. 6 | -------------------------------------------------------------------------------- /test/example-output/gcc-other-error.txt: -------------------------------------------------------------------------------- 1 | src/app/LightScheduler.cpp:39:1: error: new types may not be defined in a return type 2 | 39 | class LightSchedulerWakeUpAction : public WakeUpAction 3 | | ^~~~~ 4 | compilation terminated due to -Wfatal-errors. 5 | make[1]: *** [/home/james/repos/github/cpputest/build/MakefileWorker.mk:511: objs/src/app/LightScheduler.o] Error 1 6 | -------------------------------------------------------------------------------- /test/example-output/gcc-warning.txt: -------------------------------------------------------------------------------- 1 | src/app/LightScheduler.cpp:27:12: error: ‘foo’ defined but not used [-Werror=unused-variable] 2 | 27 | static int foo; 3 | | ^~~ 4 | compilation terminated due to -Wfatal-errors. 5 | cc1plus: all warnings being treated as errors 6 | make[1]: *** [/home/james/repos/github/cpputest/build/MakefileWorker.mk:511: objs/src/app/LightScheduler.o] Error 1 7 | -------------------------------------------------------------------------------- /gen-xfakes.sublime-project: -------------------------------------------------------------------------------- 1 | { 2 | "folders": 3 | [ 4 | { 5 | "path": "." 6 | } 7 | ], 8 | "build_systems": 9 | [ 10 | { 11 | "name": "test gen-xfakes", 12 | "working_dir": "${project_path}/test", 13 | "cmd": ["./all-tests.sh"], 14 | "target": "ansi_color_build", 15 | "syntax": "Packages/ANSIescape/ANSI.sublime-syntax" 16 | } 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /test/example-output/gcc-undeclared-error.txt: -------------------------------------------------------------------------------- 1 | tests/LightSchedulerTest.cpp: In member function ‘virtual void TEST_LightScheduler_Create_Test::testBody()’: 2 | tests/LightSchedulerTest.cpp:21:2: error: ‘LightScheduler’ was not declared in this scope 3 | 21 | LightScheduler scheduler; 4 | | ^~~~~~~~~~~~~~ 5 | compilation terminated due to -Wfatal-errors. 6 | make[1]: *** [/home/james/repos/github/cpputest/build/MakefileWorker.mk:511: objs/tests/LightSchedulerTest.o] Error 1 7 | -------------------------------------------------------------------------------- /test/all-tests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | 4 | ORIGIN_DIR=$PWD 5 | cd $(dirname $0) 6 | 7 | test_files=$(ls test-*.sh) 8 | test_out=all-test.out 9 | rm -f $test_out 10 | 11 | for test_file in $test_files; do 12 | echo Running: $test_file 13 | bash ./$test_file | sed -e"s/OK/& -- ${test_file}/" -e"s/FAILED/& -- ${test_file}/" >>$test_out 14 | done 15 | 16 | if [ ! -z "$(grep "FAILED" $test_out)" ]; then 17 | cat $test_out 18 | fi 19 | 20 | grep -e OK -e Ran $test_out 21 | 22 | cd $ORIGIN_DIR 23 | 24 | -------------------------------------------------------------------------------- /test/golden/xfakes-gcc-sorted-undefines.txt: -------------------------------------------------------------------------------- 1 | AcmeCrypto_RemoveKeyFile(char const*) 2 | AcmeDatabase_GetCloudserver1Linked(bool*) 3 | AcmeDatabase_SetCloudserver1Linked(bool) 4 | AcmeRegistry::AcmeRegistry() 5 | AcmeRegistry::Write(char const*, char const*) 6 | AcmeRegistry::instance 7 | AcmeRegistry::~AcmeRegistry() 8 | AcmeUpdateTZEnv(char const*, char const*) 9 | AcmeWpa::clock 10 | AcmeWpa::clockGetSeconds() 11 | AcmeWpa::restartDhcp(double, std::__cxx11::basic_string, std::allocator >*) 12 | log_it 13 | myJSON_AddStringToObject 14 | myJSON_CreateObject 15 | myJSON_Delete 16 | myJSON_GetObjectItem 17 | myJSON_IsString 18 | pthread_setname_np 19 | -------------------------------------------------------------------------------- /test/golden/xfakes-clang-cpp-globals.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Fakes generated from: ./example-output/clang-link-errors.txt 3 | 4 | Generated file to help to quickly stub C++ undefined external globals. 5 | 6 | * One at a time 7 | * Add the file containing the global definition to your build or 8 | add the global data definition (and its declaratiob) to this file. 9 | Adding the global to this file is probably not sustainable, but a 10 | pragmatic choice until you decide how to better organioze your global 11 | data. 12 | * Add include files as neededd. 13 | * Work carefully. Use the compiler and link error output to test your changes. 14 | 15 | */ 16 | 17 | -------------------------------------------------------------------------------- /test/golden/xfakes-clang-sorted-undefines.txt: -------------------------------------------------------------------------------- 1 | LightSwitch::LightSwitch() 2 | LightSwitch::Off(int) 3 | LightSwitch::On(int) 4 | LightSwitch::~LightSwitch() 5 | RandomMinuteGenerator::Get() 6 | RandomMinuteGenerator::RandomMinuteGenerator(int, int) 7 | RandomMinuteGenerator::~RandomMinuteGenerator() 8 | Time::Time(Time const&) 9 | Time::getDay() const 10 | Time::getMinute() const 11 | Time::~Time() 12 | TimeService::TimeService() 13 | TimeService::getTime() 14 | TimeService::wakePeriodically(std::__1::unique_ptr >) 15 | TimeService::~TimeService() 16 | WakeUpAction::WakeUpAction(int) 17 | WakeUpAction::~WakeUpAction() 18 | eventList 19 | log_debug 20 | typeinfo for WakeUpAction 21 | -------------------------------------------------------------------------------- /test/golden/xfakes-vs-cpp-globals.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Fakes generated from: ./example-output/vs-link-errors.txt 3 | 4 | Generated file to help to quickly stub C++ undefined external globals. 5 | 6 | * One at a time 7 | * Add the file containing the global definition to your build or 8 | add the global data definition (and its declaratiob) to this file. 9 | Adding the global to this file is probably not sustainable, but a 10 | pragmatic choice until you decide how to better organioze your global 11 | data. 12 | * Add include files as neededd. 13 | * Work carefully. Use the compiler and link error output to test your changes. 14 | 15 | */ 16 | 17 | // cpp-global public: static class beta alpha::var; 18 | -------------------------------------------------------------------------------- /test/golden/xfakes-gcc-cpp-globals.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Fakes generated from: ./example-output/gcc-link-errors.txt 3 | 4 | Generated file to help to quickly stub C++ undefined external globals. 5 | 6 | * One at a time 7 | * Add the file containing the global definition to your build or 8 | add the global data definition (and its declaratiob) to this file. 9 | Adding the global to this file is probably not sustainable, but a 10 | pragmatic choice until you decide how to better organioze your global 11 | data. 12 | * Add include files as neededd. 13 | * Work carefully. Use the compiler and link error output to test your changes. 14 | 15 | */ 16 | 17 | // cpp-global AcmeRegistry::instance; 18 | // cpp-global AcmeWpa::clock; 19 | -------------------------------------------------------------------------------- /test/golden/xfakes-vs-sorted-undefines.txt: -------------------------------------------------------------------------------- 1 | Add_double 2 | Get_Digit_UINT32 3 | Set_Digit_UINT16 4 | __declspec(dllimport) const icu_62::ErrorCode::`vftable' 5 | __declspec(dllimport) public: enum UErrorCode __cdecl icu_62::ErrorCode::reset(void) 6 | __declspec(dllimport) public: signed char __cdecl icu_62::ErrorCode::isSuccess(void)const 7 | __declspec(dllimport) public: static double __cdecl vtkLine::DistanceToLine(double * const,double * const,double * const) 8 | __declspec(dllimport) public: static double __cdecl vtkLine::DistanceToLine(double * const,double * const,double * const,double &,double * const) 9 | __declspec(dllimport) public: virtual signed char __cdecl icu_62::UCharCharacterIterator::hasNext(void) 10 | _imp_icudt62_dat 11 | errorHalt 12 | public: static class beta alpha::var 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 James Grenning 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /test/golden/xfakes-clang-c.c: -------------------------------------------------------------------------------- 1 | /* 2 | Fakes generated from: ./example-output/clang-link-errors.txt 3 | 4 | Generated file to help to quickly stub C-linkage unresolved external references 5 | 6 | * When EXPLODING_FAKE_FOR is executed, a message is printed and the test run is existed 7 | * You could customize EXPLODING_FAKE_FOR to only fail the test 8 | * Add this file to your test build. 9 | * Do not include the header files for the referenced functions. The C-linker does not care. 10 | 11 | Note: a EXPLODING_FAKE_FOR() is generated for global variables too. 12 | * They will explode upon write :-) 13 | * You might want to resolve these a different way. 14 | 15 | */ 16 | 17 | #include 18 | #include 19 | 20 | #define BOOM_MESSAGE printf("BOOM! time to write a better fake for %s\n", __func__) 21 | #define EXPLODING_FAKE_FOR(f) void f(void); void f(void) { BOOM_MESSAGE; exit(1); } 22 | #define NULL_VOID_FAKE_FOR(f) void f(void); void f(void) {} 23 | #define NULL_VALUE_FAKE_FOR(value_type, f, result) value_type f(void); value_type f(void) { return result; } 24 | 25 | 26 | EXPLODING_FAKE_FOR(eventList) 27 | EXPLODING_FAKE_FOR(log_debug) 28 | -------------------------------------------------------------------------------- /test/example-output/gcc-link-error-legacy.txt: -------------------------------------------------------------------------------- 1 | /usr/bin/ld: lib/libHomeAutomation.a(LightScheduler.o): in function `LightScheduler::LightScheduler()': 2 | /home/james/repos/bitbucket/cyber-dojo-start-points/ref-cpp/Legacy_1_dev/src/app/LightScheduler.cpp:54: undefined reference to `TimeService::TimeService()' 3 | /usr/bin/ld: /home/james/repos/bitbucket/cyber-dojo-start-points/ref-cpp/Legacy_1_dev/src/app/LightScheduler.cpp:54: undefined reference to `LightSwitch::LightSwitch()' 4 | /usr/bin/ld: /home/james/repos/bitbucket/cyber-dojo-start-points/ref-cpp/Legacy_1_dev/src/app/LightScheduler.cpp:54: undefined reference to `TimeService::~TimeService()' 5 | /usr/bin/ld: lib/libHomeAutomation.a(LightScheduler.o): in function `LightScheduler::~LightScheduler()': 6 | /usr/bin/ld: /home/james/repos/bitbucket/cyber-dojo-start-points/ref-cpp/Legacy_1_dev/src/app/LightScheduler.cpp:65: undefined reference to `LightSwitch::~LightSwitch()' 7 | /usr/bin/ld: lib/libHomeAutomation.a(LightScheduler.o):(.data.rel.ro._ZTI26LightSchedulerWakeUpAction[_ZTI26LightSchedulerWakeUpAction]+0x10): undefined reference to `typeinfo for WakeUpAction' 8 | collect2: error: ld returned 1 exit status 9 | make[1]: *** [/home/james/repos/github/cpputest/build/MakefileWorker.mk:489: HomeAutomation_tests] Error 1 10 | -------------------------------------------------------------------------------- /test/golden/xfakes-vs-c.c: -------------------------------------------------------------------------------- 1 | /* 2 | Fakes generated from: ./example-output/vs-link-errors.txt 3 | 4 | Generated file to help to quickly stub C-linkage unresolved external references 5 | 6 | * When EXPLODING_FAKE_FOR is executed, a message is printed and the test run is existed 7 | * You could customize EXPLODING_FAKE_FOR to only fail the test 8 | * Add this file to your test build. 9 | * Do not include the header files for the referenced functions. The C-linker does not care. 10 | 11 | Note: a EXPLODING_FAKE_FOR() is generated for global variables too. 12 | * They will explode upon write :-) 13 | * You might want to resolve these a different way. 14 | 15 | */ 16 | 17 | #include 18 | #include 19 | 20 | #define BOOM_MESSAGE printf("BOOM! time to write a better fake for %s\n", __func__) 21 | #define EXPLODING_FAKE_FOR(f) void f(void); void f(void) { BOOM_MESSAGE; exit(1); } 22 | #define NULL_VOID_FAKE_FOR(f) void f(void); void f(void) {} 23 | #define NULL_VALUE_FAKE_FOR(value_type, f, result) value_type f(void); value_type f(void) { return result; } 24 | 25 | 26 | EXPLODING_FAKE_FOR(Add_double) 27 | EXPLODING_FAKE_FOR(Get_Digit_UINT32) 28 | EXPLODING_FAKE_FOR(Set_Digit_UINT16) 29 | EXPLODING_FAKE_FOR(_imp_icudt62_dat) 30 | EXPLODING_FAKE_FOR(errorHalt) 31 | -------------------------------------------------------------------------------- /test/golden/xfakes-gcc-c.c: -------------------------------------------------------------------------------- 1 | /* 2 | Fakes generated from: ./example-output/gcc-link-errors.txt 3 | 4 | Generated file to help to quickly stub C-linkage unresolved external references 5 | 6 | * When EXPLODING_FAKE_FOR is executed, a message is printed and the test run is existed 7 | * You could customize EXPLODING_FAKE_FOR to only fail the test 8 | * Add this file to your test build. 9 | * Do not include the header files for the referenced functions. The C-linker does not care. 10 | 11 | Note: a EXPLODING_FAKE_FOR() is generated for global variables too. 12 | * They will explode upon write :-) 13 | * You might want to resolve these a different way. 14 | 15 | */ 16 | 17 | #include 18 | #include 19 | 20 | #define BOOM_MESSAGE printf("BOOM! time to write a better fake for %s\n", __func__) 21 | #define EXPLODING_FAKE_FOR(f) void f(void); void f(void) { BOOM_MESSAGE; exit(1); } 22 | #define NULL_VOID_FAKE_FOR(f) void f(void); void f(void) {} 23 | #define NULL_VALUE_FAKE_FOR(value_type, f, result) value_type f(void); value_type f(void) { return result; } 24 | 25 | 26 | EXPLODING_FAKE_FOR(log_it) 27 | EXPLODING_FAKE_FOR(myJSON_AddStringToObject) 28 | EXPLODING_FAKE_FOR(myJSON_CreateObject) 29 | EXPLODING_FAKE_FOR(myJSON_Delete) 30 | EXPLODING_FAKE_FOR(myJSON_GetObjectItem) 31 | EXPLODING_FAKE_FOR(myJSON_IsString) 32 | EXPLODING_FAKE_FOR(pthread_setname_np) 33 | -------------------------------------------------------------------------------- /legacy-build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | LEGACY_SUGGEST=$(dirname $0)/legacy-suggest.sh 4 | if [[ ! -e "${LEGACY_SUGGEST}" ]]; then 5 | echo "error: missing ${LEGACY_SUGGEST}" 6 | exit 1 7 | fi 8 | 9 | source $LEGACY_SUGGEST 10 | 11 | GEN_XFAKES=$(dirname $0)/gen-xfakes.sh 12 | if [[ ! -e "${GEN_XFAKES}" ]]; then 13 | echo "error: missing ${GEN_XFAKES}" 14 | exit 1 15 | fi 16 | 17 | source $GEN_XFAKES 18 | 19 | legacy_build_main() 20 | { 21 | BUILD_COMMAND=$1 22 | BUILD_DIR=$2 23 | INCLUDE_ROOT=$3 24 | echo "legacy-build: BUILD_COMMAND=$BUILD_COMMAND, from BUILD_DIR=$BUILD_DIR, with INCLUDE_ROOT=${INCLUDE_ROOT}" 25 | start_dir=${PWD} 26 | cd $BUILD_DIR 27 | rm -f tmp-*.* 28 | $BUILD_COMMAND 2>$ERROR_FILE 29 | cat $ERROR_FILE 30 | legacy_build_suggestion $ERROR_FILE 31 | generate_fakes $SORTED_UNDEFINES 32 | rm -rf objs/ 33 | 34 | cd $start_dir 35 | } 36 | 37 | usage_exit() 38 | { 39 | echo "usage: legacy-build command dir1 dir2" 40 | echo " command: to run, e.g. 'make'" 41 | echo " dir1: cd to dir1 to run command" 42 | echo " dir2: search for missing include files in dir2" 43 | [[ $1 != "" ]] && echo " **** $1 ****" 44 | echo 45 | exit 1 46 | } 47 | 48 | verify_params() 49 | { 50 | [[ $1 == "" ]] && usage_exit "" 51 | [[ $2 == "" ]] && usage_exit "" 52 | [[ $3 == "" ]] && usage_exit "" 53 | [[ ! -d "$2" ]] && usage_exit "'$2' is not a directory" 54 | [[ ! -d "$3" ]] && usage_exit "'$3' is not a directory" 55 | } 56 | 57 | if [[ "$0" = "$BASH_SOURCE" ]]; then 58 | verify_params $1 $2 $3 59 | legacy_build_main $1 $2 $3 60 | fi 61 | -------------------------------------------------------------------------------- /test/golden/xfakes-gcc-cpp.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Fakes generated from: ./example-output/gcc-link-errors.txt 3 | 4 | Generated file to help to quickly stub C++ undefined external functions. 5 | 6 | * Add this file to your test build. 7 | * One at a time 8 | * Uncomment an exploing fake function definition. 9 | * Add needed the include file. 10 | * Modify non-void function return types and provide a return value. 11 | * Fix errors. 12 | * Work carefully. Use the compiler and link error output to test your changes. 13 | 14 | * You could customize the BOOM macros to only fail the test, rather than exit the 15 | test runner. 16 | 17 | */ 18 | 19 | #include 20 | #include 21 | 22 | #define BOOM_MESSAGE printf("BOOM! time to write a better fake for %s\n", __func__) 23 | #define BOOM_VOID_CPP BOOM_MESSAGE; exit(1); 24 | #define BOOM_VALUE_CPP(result) BOOM_MESSAGE; exit(1); return result; 25 | 26 | /* 27 | * Production code header files 28 | */ 29 | 30 | // #include "your.h" 31 | 32 | // void AcmeCrypto_RemoveKeyFile(char const*) { BOOM_VOID_CPP } 33 | // void AcmeDatabase_GetCloudserver1Linked(bool*) { BOOM_VOID_CPP } 34 | // void AcmeDatabase_SetCloudserver1Linked(bool) { BOOM_VOID_CPP } 35 | // void AcmeRegistry::AcmeRegistry() { BOOM_VOID_CPP } 36 | // void AcmeRegistry::Write(char const*, char const*) { BOOM_VOID_CPP } 37 | // void AcmeRegistry::~AcmeRegistry() { BOOM_VOID_CPP } 38 | // void AcmeUpdateTZEnv(char const*, char const*) { BOOM_VOID_CPP } 39 | // void AcmeWpa::clockGetSeconds() { BOOM_VOID_CPP } 40 | // void AcmeWpa::restartDhcp(double, std::__cxx11::basic_string, std::allocator >*) { BOOM_VOID_CPP } 41 | -------------------------------------------------------------------------------- /test/golden/xfakes-vs-cpp.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Fakes generated from: ./example-output/vs-link-errors.txt 3 | 4 | Generated file to help to quickly stub C++ undefined external functions. 5 | 6 | * Add this file to your test build. 7 | * One at a time 8 | * Uncomment an exploing fake function definition. 9 | * Add needed the include file. 10 | * Modify non-void function return types and provide a return value. 11 | * Fix errors. 12 | * Work carefully. Use the compiler and link error output to test your changes. 13 | 14 | * You could customize the BOOM macros to only fail the test, rather than exit the 15 | test runner. 16 | 17 | */ 18 | 19 | #include 20 | #include 21 | 22 | #define BOOM_MESSAGE printf("BOOM! time to write a better fake for %s\n", __func__) 23 | #define BOOM_VOID_CPP BOOM_MESSAGE; exit(1); 24 | #define BOOM_VALUE_CPP(result) BOOM_MESSAGE; exit(1); return result; 25 | 26 | /* 27 | * Production code header files 28 | */ 29 | 30 | // #include "your.h" 31 | 32 | // void __declspec(dllimport) const icu_62::ErrorCode::`vftable' { BOOM_VOID_CPP } 33 | // void __declspec(dllimport) public: enum UErrorCode __cdecl icu_62::ErrorCode::reset(void) { BOOM_VOID_CPP } 34 | // void __declspec(dllimport) public: signed char __cdecl icu_62::ErrorCode::isSuccess(void)const { BOOM_VOID_CPP } 35 | // void __declspec(dllimport) public: static double __cdecl vtkLine::DistanceToLine(double * const,double * const,double * const) { BOOM_VOID_CPP } 36 | // void __declspec(dllimport) public: static double __cdecl vtkLine::DistanceToLine(double * const,double * const,double * const,double &,double * const) { BOOM_VOID_CPP } 37 | // void __declspec(dllimport) public: virtual signed char __cdecl icu_62::UCharCharacterIterator::hasNext(void) { BOOM_VOID_CPP } 38 | -------------------------------------------------------------------------------- /test/golden/xfakes-clang-cpp.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Fakes generated from: ./example-output/clang-link-errors.txt 3 | 4 | Generated file to help to quickly stub C++ undefined external functions. 5 | 6 | * Add this file to your test build. 7 | * One at a time 8 | * Uncomment an exploing fake function definition. 9 | * Add needed the include file. 10 | * Modify non-void function return types and provide a return value. 11 | * Fix errors. 12 | * Work carefully. Use the compiler and link error output to test your changes. 13 | 14 | * You could customize the BOOM macros to only fail the test, rather than exit the 15 | test runner. 16 | 17 | */ 18 | 19 | #include 20 | #include 21 | 22 | #define BOOM_MESSAGE printf("BOOM! time to write a better fake for %s\n", __func__) 23 | #define BOOM_VOID_CPP BOOM_MESSAGE; exit(1); 24 | #define BOOM_VALUE_CPP(result) BOOM_MESSAGE; exit(1); return result; 25 | 26 | /* 27 | * Production code header files 28 | */ 29 | 30 | // #include "your.h" 31 | 32 | // void LightSwitch::LightSwitch() { BOOM_VOID_CPP } 33 | // void LightSwitch::Off(int) { BOOM_VOID_CPP } 34 | // void LightSwitch::On(int) { BOOM_VOID_CPP } 35 | // void LightSwitch::~LightSwitch() { BOOM_VOID_CPP } 36 | // void RandomMinuteGenerator::Get() { BOOM_VOID_CPP } 37 | // void RandomMinuteGenerator::RandomMinuteGenerator(int, int) { BOOM_VOID_CPP } 38 | // void RandomMinuteGenerator::~RandomMinuteGenerator() { BOOM_VOID_CPP } 39 | // void Time::Time(Time const&) { BOOM_VOID_CPP } 40 | // void Time::getDay() const { BOOM_VOID_CPP } 41 | // void Time::getMinute() const { BOOM_VOID_CPP } 42 | // void Time::~Time() { BOOM_VOID_CPP } 43 | // void TimeService::TimeService() { BOOM_VOID_CPP } 44 | // void TimeService::getTime() { BOOM_VOID_CPP } 45 | // void TimeService::wakePeriodically(std::__1::unique_ptr >) { BOOM_VOID_CPP } 46 | // void TimeService::~TimeService() { BOOM_VOID_CPP } 47 | // void WakeUpAction::WakeUpAction(int) { BOOM_VOID_CPP } 48 | // void WakeUpAction::~WakeUpAction() { BOOM_VOID_CPP } 49 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Crash to Pass Toolkit 2 | 3 | ## `legacy-build`, `legacy-suggest` and `gen-xfakes` 4 | 5 | This repo has scripts to help C and C++ programmers drag unwilling legacy C and C++ into a test harness. 6 | 7 | The recipe for getting legacy C/C++ is described in 8 | [TDD How-to: Get your Legacy C Into a Test Harness](https://wingman-sw.com/articles/tdd-legacy-c) 9 | 10 | ## Usage 11 | 12 | In your local build directory add a file like this 13 | 14 | ``` 15 | LEGACY_BUILD=~/repos/github/legacy-build/legacy-build.sh 16 | 17 | INCLUDE_ROOT=. 18 | BUILD_DIR=. 19 | BUILD_COMMAND=make 20 | 21 | bash $LEGACY_BUILD $BUILD_DIR $INCLUDE_ROOT $BUILD_COMMAND 22 | ``` 23 | 24 | ### legacy-build.sh -- main entry point 25 | 26 | Runs MY_BUILD_COMMAND in the working directory, captures the 27 | output, passes it to `legacy-suggest` which may make a suggestion about how 28 | to solve the current problem. If you use CppUTest, some suggestions can be cut and pasted into your makefile. 29 | 30 | Finally, when you get to linker errors, `legacy-build` will 31 | generate eploding fakes to get you past linker problems and on to running your code. 32 | 33 | Set your build so that it fails on the first error. 34 | For gcc and clang `-Wfatal-errors`. 35 | 36 | So far, this has been tested on 37 | * ubuntu gcc version 9.3.0. 38 | * mac osx gcc version 7.4.0 39 | 40 | ### legacy-suggest -- helper 41 | 42 | Takes a gcc compiler error output, and filters the error, and makes a suggestion. 43 | 44 | The suggestions handle a couple common legacy code test-build problems, like missing includes and linker errors. 45 | 46 | ### gen-xfakes -- helper 47 | 48 | Generate exploding fakes from c/c++ linker error output (used for unit testing). 49 | 50 | `gen-xfakes.sh` produces three files with the supplied basename `xfakes` 51 | 52 | | | | 53 | |--- |--- | 54 | | `tmp-xfakes-c.c` | C linkage fakes, ready to add to your build | 55 | | `tmp-xfakes-cpp.cpp` | C++ linkage fakes, edits needed | 56 | | `tmp-xfakes-cpp-globals.cpp` | C++ undefined globals, edits needed | 57 | 58 | For C linker errors, the resutling file can be added to the build and those link errors go away. They later turn into runtime errors as exit the test runner whenever your code executes and exploding fake. Usually when you hit an exploding fake, you want the fake to do nothing, or possible you will need a smarter fake. 59 | 60 | For C++ errors, you need to do some editing. `tmp-xfakes-cpp.cpp` will contain a fair guess at what the missing function is that you need. You'll need to add include files and adjust function signatures. 61 | 62 | ## Supported formats 63 | 64 | * g++ linker output 65 | * clang 66 | * Visual Studio -- best guess 67 | * Feel free to give me a contribution 68 | * All these compilers are moving target, so you may have to fiddle with it. 69 | 70 | # Examples 71 | 72 | See `test/example-output/gcc-link-errors.txt` for example input. The output files 73 | are found in `test/golden`. 74 | 75 | A full explanation of how to use `gen-xfakes` is on my blog [here](http://blog.wingman-sw.com/wrestle-legacy-c-cpp-into-tests-linker-errors). 76 | 77 | ## Run the tests on your machine 78 | 79 | Clone everying including the tests 80 | 81 | ``` 82 | $ git clone 83 | $ git submodule update --init 84 | ``` 85 | 86 | Run the tests 87 | ``` 88 | cd tests 89 | ./all-tests.sh 90 | ``` 91 | -------------------------------------------------------------------------------- /test/test-gen-xfakes.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | TEST_DIR=. 4 | TEMP_DIR=tmp 5 | FAKES_BASENAME=xfakes 6 | EXAMPLES_DIR=$TEST_DIR/example-output 7 | 8 | testMakeCFake() 9 | { 10 | c_undefined="someGlobal" 11 | assertEquals 'EXPLODING_FAKE_FOR(someGlobal)' "$(echo $c_undefined | makeCFakes)" 12 | } 13 | 14 | testMakeCFakeIgnoresCpp() 15 | { 16 | cpp_function1="SomeClass::someFunction(Foo&)" 17 | cpp_function2="someFunction(Foo*)" 18 | cpp_global="SomeClass::someGlobal" 19 | cpp_destructor="vtable" 20 | assertEquals '' "$(echo $cpp_function1 | makeCFakes)" 21 | assertEquals '' "$(echo $cpp_function2 | makeCFakes)" 22 | assertEquals '' "$(echo $cpp_global | makeCFakes)" 23 | assertEquals '' "$(echo $cpp_destructor | makeCFakes)" 24 | } 25 | 26 | testMakeCppFake() 27 | { 28 | cpp_function1="SomeClass::someFunction(Foo&)" 29 | cpp_function2="someFunction(Foo*)" 30 | cpp_global="SomeClass::someGlobal" 31 | c_undefined="someGlobal" 32 | cpp_destructor="vtable for FooBar" 33 | assertEquals '// void SomeClass::someFunction(Foo&) { BOOM_VOID_CPP }' "$(echo $cpp_function1 | makeCppFakes)" 34 | assertEquals '// void someFunction(Foo*) { BOOM_VOID_CPP }' "$(echo $cpp_function2 | makeCppFakes)" 35 | assertEquals '' "$(echo $cpp_global | makeCppFakes)" 36 | assertEquals '' "$(echo $c_undefined | makeCppFakes)" 37 | assertEquals '// missing destructor FooBar { BOOM_VOID_CPP }' "$(echo $cpp_destructor | makeCppFakes)" 38 | } 39 | 40 | testMakeCppGlobalFake() 41 | { 42 | cpp_function1="SomeClass::someFunction(Foo&)" 43 | cpp_function2="someFunction(Foo*)" 44 | cpp_global="SomeClass::someGlobal" 45 | c_undefined="someGlobal" 46 | cpp_destructor="vtable for FooBar" 47 | assertEquals '' "$(echo $cpp_function1 | makeCppGlobalFakes)" 48 | assertEquals '' "$(echo $cpp_function2 | makeCppGlobalFakes)" 49 | assertEquals '// cpp-global SomeClass::someGlobal;' "$(echo $cpp_global | makeCppGlobalFakes)" 50 | assertEquals '' "$(echo $c_undefined | makeCppGlobalFakes)" 51 | assertEquals '' "$(echo $cpp_destructor | makeCppGlobalFakes)" 52 | } 53 | 54 | 55 | testCommandLine() 56 | { 57 | assertContains "$(generate_fakes)" "usage" 58 | } 59 | 60 | testSayWhenOverwriteingGeneratedFakes() 61 | { 62 | LS_OUTPUT="something" 63 | out="$(generate_fakes $EXAMPLES_DIR/gcc-link-error-legacy.txt)" 64 | assertContains "\n${out}\n" "Removing earlier generated fakes" 65 | } 66 | 67 | testLinkErrorSuggestions() 68 | { 69 | LS_OUTPUT="nothing" 70 | out="$(generate_fakes $EXAMPLES_DIR/gcc-link-error-legacy.txt)" 71 | assertContains "\n${out}\n" "${out}" "Generating fakes" 72 | assertContains "\n${out}\n" "${out}" "Removing earlier generated fakes" 73 | } 74 | 75 | diffWithGolden() 76 | { 77 | assertEquals "$2 is different than golden copy" "" "$(diff ${TEST_DIR}/${TEMP_DIR}/$2 ${TEST_DIR}/golden/$2)" 78 | } 79 | 80 | checkOutputSameAsGolden() 81 | { 82 | mkdir -p tmp 83 | generate_fakes $TEST_DIR/example-output/$1-link-errors.txt $TEST_DIR/$TEMP_DIR/$FAKES_BASENAME-$1 84 | diffWithGolden $1 $FAKES_BASENAME-$1-c.c 85 | diffWithGolden $1 $FAKES_BASENAME-$1-cpp.cpp 86 | diffWithGolden $1 $FAKES_BASENAME-$1-cpp-globals.cpp 87 | } 88 | 89 | testOutputSameAsGoldenGcc() 90 | { 91 | checkOutputSameAsGolden gcc 92 | } 93 | 94 | # testOutputSameAsGoldenClang() 95 | # { 96 | # checkOutputSameAsGolden clang 97 | # } 98 | 99 | # testOutputSameAsGoldenVS() 100 | # { 101 | # checkOutputSameAsGolden vs 102 | # } 103 | 104 | cleanup() 105 | { 106 | rm -rf $TEST_DIR/$TEMP_DIR 107 | } 108 | 109 | 110 | cleanup 111 | . ../gen-xfakes.sh 112 | . ../shunit2/shunit2 113 | -------------------------------------------------------------------------------- /test/example-output/clang-link-errors.txt: -------------------------------------------------------------------------------- 1 | Making clean 2 | compiling LightSchedulerTest.cpp 3 | compiling AllTests.cpp 4 | compiling LightScheduler.cpp 5 | Building archive lib/libHomeAutomation.a 6 | a - objs/src/LightScheduler.o 7 | Linking HomeAutomation_tests 8 | Undefined symbols for architecture x86_64: 9 | "LightSwitch::On(int)", referenced from: 10 | LightScheduler::TimeToCheckTheSchedule() in libHomeAutomation.a(LightScheduler.o) 11 | "LightSwitch::Off(int)", referenced from: 12 | LightScheduler::TimeToCheckTheSchedule() in libHomeAutomation.a(LightScheduler.o) 13 | "LightSwitch::LightSwitch()", referenced from: 14 | LightScheduler::LightScheduler() in libHomeAutomation.a(LightScheduler.o) 15 | "LightSwitch::~LightSwitch()", referenced from: 16 | LightScheduler::LightScheduler() in libHomeAutomation.a(LightScheduler.o) 17 | LightScheduler::~LightScheduler() in libHomeAutomation.a(LightScheduler.o) 18 | "TimeService::wakePeriodically(std::__1::unique_ptr >)", referenced from: 19 | LightScheduler::LightScheduler() in libHomeAutomation.a(LightScheduler.o) 20 | "TimeService::getTime()", referenced from: 21 | LightScheduler::TimeToCheckTheSchedule() in libHomeAutomation.a(LightScheduler.o) 22 | "TimeService::TimeService()", referenced from: 23 | LightScheduler::LightScheduler() in libHomeAutomation.a(LightScheduler.o) 24 | "TimeService::~TimeService()", referenced from: 25 | LightScheduler::LightScheduler() in libHomeAutomation.a(LightScheduler.o) 26 | LightScheduler::~LightScheduler() in libHomeAutomation.a(LightScheduler.o) 27 | "WakeUpAction::WakeUpAction(int)", referenced from: 28 | LightSchedulerWakeUpAction::LightSchedulerWakeUpAction(LightScheduler*) in libHomeAutomation.a(LightScheduler.o) 29 | "WakeUpAction::~WakeUpAction()", referenced from: 30 | LightSchedulerWakeUpAction::~LightSchedulerWakeUpAction() in libHomeAutomation.a(LightScheduler.o) 31 | "RandomMinuteGenerator::Get()", referenced from: 32 | LightScheduler::TimeToCheckTheSchedule() in libHomeAutomation.a(LightScheduler.o) 33 | "RandomMinuteGenerator::RandomMinuteGenerator(int, int)", referenced from: 34 | LightScheduler::LightScheduler() in libHomeAutomation.a(LightScheduler.o) 35 | "RandomMinuteGenerator::~RandomMinuteGenerator()", referenced from: 36 | LightScheduler::LightScheduler() in libHomeAutomation.a(LightScheduler.o) 37 | LightScheduler::~LightScheduler() in libHomeAutomation.a(LightScheduler.o) 38 | "Time::Time(Time const&)", referenced from: 39 | LightSchedulerWakeUpAction::wakeUp(Time) in libHomeAutomation.a(LightScheduler.o) 40 | "Time::~Time()", referenced from: 41 | LightScheduler::TimeToCheckTheSchedule() in libHomeAutomation.a(LightScheduler.o) 42 | LightSchedulerWakeUpAction::wakeUp(Time) in libHomeAutomation.a(LightScheduler.o) 43 | "Time::getDay() const", referenced from: 44 | LightScheduler::TimeToCheckTheSchedule() in libHomeAutomation.a(LightScheduler.o) 45 | "Time::getMinute() const", referenced from: 46 | LightScheduler::TimeToCheckTheSchedule() in libHomeAutomation.a(LightScheduler.o) 47 | "typeinfo for WakeUpAction", referenced from: 48 | typeinfo for LightSchedulerWakeUpAction in libHomeAutomation.a(LightScheduler.o) 49 | "_eventList", referenced from: 50 | LightScheduler::LightScheduler() in libHomeAutomation.a(LightScheduler.o) 51 | LightScheduler::TimeToCheckTheSchedule() in libHomeAutomation.a(LightScheduler.o) 52 | LightScheduler::AddTurnOn(int, Time::Day, int) in libHomeAutomation.a(LightScheduler.o) 53 | LightScheduler::RandomizeTurnOn(int, Time::Day, int) in libHomeAutomation.a(LightScheduler.o) 54 | LightScheduler::AddTurnOff(int, Time::Day, int) in libHomeAutomation.a(LightScheduler.o) 55 | LightScheduler::Remove(int, Time::Day, int) in libHomeAutomation.a(LightScheduler.o) 56 | "_log_debug", referenced from: 57 | LightScheduler::LightScheduler() in libHomeAutomation.a(LightScheduler.o) 58 | LightScheduler::~LightScheduler() in libHomeAutomation.a(LightScheduler.o) 59 | ld: symbol(s) not found for architecture x86_64 60 | clang: error: linker command failed with exit code 1 (use -v to see invocation) 61 | -------------------------------------------------------------------------------- /test/example-output/gcc-link-errors.txt: -------------------------------------------------------------------------------- 1 | Building build/test_WebServer 2 | g++ -Wall -DQNX_BUILD -Wno-narrowing -DEOK=0 -DTEST -Wfatal-errors -D__LITTLEENDIAN__ -D__X86__ -D__LINUX__ -D__i386 -include forced_include.h -I../../../include/catch -I../ -I./ -I./fake_includes -I /usr/include/ -I../../..//Libraries/AcmeDatabase/exports -I../../..//Libraries/AcmeWpa/exports -I../../..//Libraries/AcmeSocket/exports -I../../..//Libraries/AcmeCrypto/exports -I../../..//Libraries/AcmeJSON/exports -I../../..//Libraries/AcmeLog/exports -I../../..//Libraries/AcmeNeutrino/exports -I../../..//include ../HardConnect.cpp -o build/test_WebServer ./build/test_WebServer.o 3 | ../HardConnect.cpp: In function ‘bool Cloudserver1LinkRequest(const string&, const string&, std::__cxx11::string*)’: 4 | ../HardConnect.cpp:510:64: warning: format ‘%d’ expects argument of type ‘int’, but argument 4 has type ‘std::__cxx11::basic_string::size_type {aka long unsigned int}’ [-Wformat=] 5 | snprintf(tempBuffer, sizeof( tempBuffer ), "%d", body.length()); 6 | ^ 7 | ../HardConnect.cpp:510:64: warning: format ‘%d’ expects argument of type ‘int’, but argument 4 has type ‘std::__cxx11::basic_string::size_type {aka long unsigned int}’ [-Wformat=] 8 | /tmp/xxxxxx.o: In function `recordWpaConnected(std::__cxx11::basic_string, std::allocator > const&)': 9 | HardConnect.cpp:(.text+0x20): undefined reference to `AcmeWpa::clockGetSeconds()' 10 | HardConnect.cpp:(.text+0x5a): undefined reference to `log_it' 11 | HardConnect.cpp:(.text+0x19c): undefined reference to `AcmeWpa::clockGetSeconds()' 12 | /tmp/xxxxxx.o: In function `applyTimeZoneUTCOffset(std::__cxx11::basic_string, std::allocator >, std::__cxx11::basic_string, std::allocator >)': 13 | HardConnect.cpp:(.text+0x643): undefined reference to `AcmeUpdateTZEnv(char const*, char const*)' 14 | HardConnect.cpp:(.text+0x6fc): undefined reference to `AcmeWpa::clock' 15 | HardConnect.cpp:(.text+0x72b): undefined reference to `AcmeWpa::restartDhcp(double, std::__cxx11::basic_string, std::allocator >*)' 16 | HardConnect.cpp:(.text+0xd44): undefined reference to `AcmeDatabase_SetCloudserver1Linked(bool)' 17 | HardConnect.cpp:(.text+0xd80): undefined reference to `log_it' 18 | HardConnect.cpp:(.text+0xd9a): undefined reference to `AcmeDatabase_GetCloudserver1Linked(bool*)' 19 | HardConnect.cpp:(.text+0xdd8): undefined reference to `log_it' 20 | HardConnect.cpp:(.text+0xe06): undefined reference to `AcmeRegistry::Write(char const*, char const*)' 21 | HardConnect.cpp:(.text+0xe06): undefined reference to `AcmeRegistry::instance' 22 | HardConnect.cpp:(.text+0xebb): undefined reference to `AcmeCrypto_RemoveKeyFile(char const*)' 23 | HardConnect.cpp:(.text+0x24e3): undefined reference to `pthread_setname_np' 24 | HardConnect.cpp:(.text+0x24e3): undefined reference to `myJSON_GetObjectItem' 25 | HardConnect.cpp:(.text._ZN32JsonHardConnectInitializeRequest15getNestedStringERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES7_PS5_[_ZN32JsonHardConnectInitializeRequest15getNestedStringERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES7_PS5_]+0x8c): undefined reference to `myJSON_IsString' 26 | /tmp/xxxxxx.o: In function `JsonCloudserver1LinkRequest::JsonCloudserver1LinkRequest()': 27 | HardConnect.cpp:(.text._ZN22JsonCloudserver1LinkRequestC2Ev[_ZN22JsonCloudserver1LinkRequestC5Ev]+0x18): undefined reference to `myJSON_CreateObject' 28 | /tmp/xxxxxx.o: In function `JsonCloudserver1LinkRequest::~JsonCloudserver1LinkRequest()': 29 | HardConnect.cpp:(.text._ZN22JsonCloudserver1LinkRequestD2Ev[_ZN22JsonCloudserver1LinkRequestD5Ev]+0x17): undefined reference to `myJSON_Delete' 30 | basic_stringIcSt11char_traitsIcESaIcEEES7_]+0x44): undefined reference to `myJSON_AddStringToObject' 31 | /tmp/xxxxxx.o: In function `AcmeRegistry::GetInstance()': 32 | HardConnect.cpp:(.text._ZN13AcmeRegistry11GetInstanceEv[_ZN13AcmeRegistry11GetInstanceEv]+0x32): undefined reference to `AcmeRegistry::AcmeRegistry()' 33 | HardConnect.cpp:(.text._ZN13AcmeRegistry11GetInstanceEv[_ZN13AcmeRegistry11GetInstanceEv]+0x4b): undefined reference to `AcmeRegistry::~AcmeRegistry()' 34 | collect2: error: ld returned 1 exit status 35 | make: allerrors.txt a.out build cpputest_build.sh cpputest_main.cpp cpputest_WebServer.cpp errors.txt fake_includes forced_include.h Makefile test_WebServer.cpp [build/test_WebServer] Error 1 36 | 37 | -------------------------------------------------------------------------------- /test/example-output/vs-link-errors.txt: -------------------------------------------------------------------------------- 1 | 1>------ Build started: Project: AllTests, Configuration: Debug Win32 ------ 2 | 1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Microsoft\VC\v160\Microsoft.CppBuild.targets(452,5): warning MSB8028: The intermediate directory (.\Debug\) contains files shared from another project (ProductionCodeLib.vcxproj). This can lead to incorrect clean and rebuild behavior. 3 | 1>states.c 4 | 1>C:\Users\bagins\Documents\Local Project Copies\EPM\branches\EPM3 V003 Inline\states.c(1011,15): warning C4013: '_EINT' undefined; assuming extern returning int 5 | 1>C:\Users\bagins\Documents\Local Project Copies\EPM\branches\EPM3 V003 Inline\states.c(1814,42): warning C4013: 'RadioLeaveNetwork' undefined; assuming extern returning int 6 | 1>C:\Users\bagins\Documents\Local Project Copies\EPM\branches\EPM3 V003 Inline\states.c(1814,42): warning C4013: C:\Users\bagins\Documents\Local Project Copies\EPM\branches\EPM3 V003 Inline\states.c(3543) : warning C4700: uninitialized local variable 'error' used 7 | 1>AllTests.cpp 8 | 1>ExampleTest.cpp 9 | 1>MyFirstTest.cpp 10 | 1>Generating Code... 11 | 1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Microsoft\VC\v160\Microsoft.CppBuild.targets(452,5): warning MSB8028: The intermediate directory (.\Debug\) contains files shared from another project (AllTests.vcxproj). This can lead to incorrect clean and rebuild behavior. 12 | 1>Done building project "ProductionCodeLib.vcxproj". 13 | 1>states.obj : warning LNK4075: ignoring '/EDITANDCONTINUE' due to '/SAFESEH' specification 14 | 1>states.obj : error LNK2019: unresolved external symbol _errorHalt referenced in function _State_Update 15 | 1>states.obj : error LNK2019: unresolved external symbol _Add_double referenced in function _State_Update 16 | 1>states.obj : error LNK2019: unresolved external symbol _Get_Digit_UINT32 referenced in function _State_Update_BatchDispense 17 | 1>states.obj : error LNK2019: unresolved external symbol _Set_Digit_UINT16 referenced in function _State_Update_BatchDispense 18 | 19 | Error 1 error LNK2019: unresolved external symbol "__declspec(dllimport) public: static double __cdecl vtkLine::DistanceToLine(double * const,double * const,double * const,double &,double * const)" (__imp_?DistanceToLine@vtkLine@@SANQAN00AAN0@Z) referenced in function _main E:\DistancePointToLine\DistancePointToLine.obj DistancePointToLine 20 | 21 | Error 2 error LNK2019: unresolved external symbol "__declspec(dllimport) public: static double __cdecl vtkLine::DistanceToLine(double * const,double * const,double * const)" (__imp_?DistanceToLine@vtkLine@@SANQAN00@Z) referenced in function _main E:\DistancePointToLine\DistancePointToLine.obj DistancePointToLine 22 | 23 | : error LNK2019: unresolved external symbol "__declspec(dllimport) public: virtual signed char __cdecl icu_62::UCharCharacterIterator::hasNext(void)" (__imp_?hasNext@UCharCharacterIterator@icu_62@@UEAACXZ) referenced in function "void __cdecl tensorflow::anonymous namespace'::Encode(enum tensorflow::UnicodeEncoding,class icu_62::UnicodeString const &,class std::basic_string *)" (?Encode@?A0xb9816742@tensorflow@@YAXW4UnicodeEncoding@2@AEBVUnicodeString@icu_62@@peav?$basic_string@DU?$char_traits@D@std@@v?$allocator@D@2@@std@@@z) 24 | unicode_ops.lo.lib(unicode_ops.obj) 25 | 26 | : error LNK2019: unresolved external symbol "__declspec(dllimport) public: signed char __cdecl icu_62::ErrorCode::isSuccess(void)const " (_imp?isSuccess@ErrorCode@icu_62@@QEBACXZ) referenced in function "public: virtual void __cdecl tensorflow::UnicodeScriptOp::Compute(class tensorflow::OpKernelContext *)" (?Compute@UnicodeScriptOp@tensorflow@@UEAAXPEAVOpKernelContext@2@@z) 27 | 28 | unicode_script_op.lo.lib(unicode_script_op.obj) : error LNK2019: unresolved external symbol "__declspec(dllimport) public: enum UErrorCode __cdecl icu_62::ErrorCode::reset(void)" (_imp?reset@ErrorCode@icu_62@@QEAA?AW4UErrorCode@@xz) referenced in function "public: virtual void __cdecl tensorflow::UnicodeScriptOp::Compute(class tensorflow::OpKernelContext *)" (?Compute@UnicodeScriptOp@tensorflow@@UEAAXPEAVOpKernelContext@2@@z) 29 | 30 | unicode_script_op.lo.lib(unicode_script_op.obj) : error LNK2019: unresolved external symbol "__declspec(dllimport) const icu_62::ErrorCode::`vftable'" (_imp??_7ErrorCode@icu_62@@6b@) referenced in function "public: virtual void __cdecl tensorflow::UnicodeScriptOp::Compute(class tensorflow::OpKernelContext *)" (?Compute@UnicodeScriptOp@tensorflow@@UEAAXPEAVOpKernelContext@2@@z)icuuc.lib(udata.obj) 31 | 32 | : error LNK2019: unresolved external symbol __imp_icudt62_dat referenced in function "struct UDataMemory * __cdecl openCommonData(char const *,int,enum UErrorCode *)" (?openCommonData@@YAPEAUUDataMemory@@PEBDHPEAW4UErrorCode@@@z) 33 | 34 | error LNK2001: unresolved external symbol "public: static class beta alpha::var" (?var@alpha@@2Vbeta@@A) 35 | 36 | bazel-out/x64_windows-opt/bin/tensorflow/cc/example/example.exe : fatal error LNK1120: 9 unresolved externals 37 | Target //tensorflow/cc/example:example failed to build 38 | INFO: Elapsed time: 19976.467s, Critical Path: 13898.60s 39 | INFO: 1461 processes: 1461 local. 40 | FAILED: Build did NOT complete successfully 41 | FAILED: Build did NOT complete successfully 42 | ** 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /gen-xfakes.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | FAKES_BASENAME=tmp-xfakes 4 | 5 | 6 | preambleCFakes() 7 | { 8 | cat > $1 <<- EOM 9 | /* 10 | Fakes generated from: $2 11 | 12 | Generated file to help to quickly stub C-linkage unresolved external references 13 | 14 | * When EXPLODING_FAKE_FOR is executed, a message is printed and the test run is existed 15 | * You could customize EXPLODING_FAKE_FOR to only fail the test 16 | * Add this file to your test build. 17 | * Do not include the header files for the referenced functions. The C-linker does not care. 18 | 19 | Note: a EXPLODING_FAKE_FOR() is generated for global variables too. 20 | * They will explode upon write :-) 21 | * You might want to resolve these a different way. 22 | 23 | */ 24 | 25 | #include 26 | #include 27 | 28 | #define BOOM_MESSAGE printf("BOOM! time to write a better fake for %s\n", __func__) 29 | #define EXPLODING_FAKE_FOR(f) void f(void); void f(void) { BOOM_MESSAGE; exit(1); } 30 | #define NULL_VOID_FAKE_FOR(f) void f(void); void f(void) {} 31 | #define NULL_VALUE_FAKE_FOR(value_type, f, result) value_type f(void); value_type f(void) { return result; } 32 | 33 | 34 | EOM 35 | } 36 | 37 | preambleCppFakes() 38 | { 39 | cat > $1 <<- EOM 40 | /* 41 | Fakes generated from: $2 42 | 43 | Generated file to help to quickly stub C++ undefined external functions. 44 | 45 | * Add this file to your test build. 46 | * One at a time 47 | * Uncomment an exploing fake function definition. 48 | * Add needed the include file. 49 | * Modify non-void function return types and provide a return value. 50 | * Fix errors. 51 | * Work carefully. Use the compiler and link error output to test your changes. 52 | 53 | * You could customize the BOOM macros to only fail the test, rather than exit the 54 | test runner. 55 | 56 | */ 57 | 58 | #include 59 | #include 60 | 61 | #define BOOM_MESSAGE printf("BOOM! time to write a better fake for %s\n", __func__) 62 | #define BOOM_VOID_CPP BOOM_MESSAGE; exit(1); 63 | #define BOOM_VALUE_CPP(result) BOOM_MESSAGE; exit(1); return result; 64 | 65 | /* 66 | * Production code header files 67 | */ 68 | 69 | // #include "your.h" 70 | 71 | EOM 72 | } 73 | 74 | preambleCppGlobalFakes() 75 | { 76 | cat > $1 <<- EOM 77 | /* 78 | Fakes generated from: $2 79 | 80 | Generated file to help to quickly stub C++ undefined external globals. 81 | 82 | * One at a time 83 | * Add the file containing the global definition to your build or 84 | add the global data definition (and its declaratiob) to this file. 85 | Adding the global to this file is probably not sustainable, but a 86 | pragmatic choice until you decide how to better organioze your global 87 | data. 88 | * Add include files as neededd. 89 | * Work carefully. Use the compiler and link error output to test your changes. 90 | 91 | */ 92 | 93 | EOM 94 | } 95 | 96 | # linkErrorClang() 97 | # { 98 | # grep ", referenced from:" 99 | # } 100 | 101 | # isolateUndefinedSymbolsClang() 102 | # { 103 | # linkErrorClang | sed -e's/^ *"//' -e's/".*//' -e's/^_//' 104 | # } 105 | 106 | # linkErrorGcc() 107 | # { 108 | # grep ": undefined reference to " 109 | # } 110 | 111 | # isolateUndefinedSymbolsGcc() 112 | # { 113 | # linkErrorGcc | sed -e's/.*`//' -e"s/'$//" 114 | # } 115 | 116 | # linkErrorVS_C() 117 | # { 118 | # grep "LNK2019.*symbol _" 119 | # } 120 | 121 | # linkErrorVS_Cpp() 122 | # { 123 | # grep "LNK2019\|LNK2001" | grep ".*symbol \"" 124 | # } 125 | 126 | # isolateUndefinedSymbolsVS_C() 127 | # { 128 | # linkErrorVS_C | sed -e's/^.*symbol _/__C__/' -e's/ referenced.*//' -e's/__C__//' 129 | # } 130 | 131 | # isolateUndefinedSymbolsVS_Cpp() 132 | # { 133 | # linkErrorVS_Cpp | sed -e's/^.*symbol "/__CPP__/' -e's/" .*//' -e's/__CPP__//' 134 | # } 135 | 136 | usage() 137 | { 138 | echo "usage $0 linker-error-output.txt out-file-basename" 139 | exit 1 140 | } 141 | 142 | must_exist() 143 | { 144 | if [ ! -e $1 ]; then 145 | echo "Input file does not exist: $1" 146 | exit 1 147 | fi 148 | } 149 | 150 | cant_exist() 151 | { 152 | if [ -e $1 ]; then 153 | echo "Output file exists: $1" 154 | exit 1 155 | fi 156 | } 157 | 158 | makeFakes() 159 | { 160 | cant_exist $4 161 | preamble$3Fakes $4 $1 162 | cat $2 | make$3Fakes >> $4 163 | } 164 | 165 | makeCFakes() 166 | { 167 | grep -v "::\|vtable" | grep -v "(.*)" | grep -v "typeinfo" | sed -e's/^/EXPLODING_FAKE_FOR(/' -e's/$/)/' 168 | } 169 | 170 | makeCppFakes() 171 | { 172 | # grep "vtable" | sed -e's|vtable for \(.*$\)|// ~\1::\1|' -e's/$/ { BOOM_VOID_CPP }/' 173 | grep "(.*)\|vtable" | sed -e's|^|// void |' -e's/$/ { BOOM_VOID_CPP }/' -e's/void vtable for/missing destructor/' 174 | } 175 | 176 | makeCppGlobalFakes() 177 | { 178 | grep -v "(.*)" | grep "::" | sed -e's|^|// cpp-global |' -e's/$/;&/' 179 | } 180 | 181 | show_fakes_stats_for() 182 | { 183 | echo "$1 has $(grep -v "#define" $1 |grep -c "$2" | sed -e's/:/ generated /' -e's/$/ exploding fakes/')" 184 | } 185 | 186 | show_fakes_stats() 187 | { 188 | show_fakes_stats_for ${FAKES_BASENAME}-c.c "^EXPLODING" 189 | show_fakes_stats_for ${FAKES_BASENAME}-cpp.cpp "^//.*BOOM" 190 | show_fakes_stats_for ${FAKES_BASENAME}-cpp-globals.cpp "// cpp-global" 191 | } 192 | 193 | usage() 194 | { 195 | echo "usage $0 sorted-undefined-symbols-file" 196 | exit 1 197 | } 198 | 199 | 200 | gen_xfakes() 201 | { 202 | input_file=$1 203 | must_exist $input_file 204 | sorted_undefines=$SORTED_UNDEFINES 205 | must_exist $sorted_undefines 206 | 207 | fakes_c=$3-c.c 208 | fakes_cpp=$3-cpp.cpp 209 | fakes_cpp_globals=$3-cpp-globals.cpp 210 | 211 | makeFakes $input_file $sorted_undefines C $fakes_c 212 | makeFakes $input_file $sorted_undefines Cpp $fakes_cpp 213 | makeFakes $input_file $sorted_undefines CppGlobal $fakes_cpp_globals 214 | 215 | } 216 | 217 | generate_fakes() 218 | { 219 | if [[ "$#" != "1" ]]; then 220 | usage 221 | fi 222 | [ ! -e $SORTED_UNDEFINES ] && return 0 223 | echo "Removing earlier generated fakes " 224 | rm -f ${FAKES_BASENAME}-*.* 225 | echo "Generating fakes" 226 | gen_xfakes $ERROR_FILE $SORTED_UNDEFINES $FAKES_BASENAME 227 | echo "Review generated fakes, and incrementally add them to the build:" 228 | show_fakes_stats 229 | return 0 230 | } 231 | 232 | 233 | if [[ "$0" = "$BASH_SOURCE" ]]; then 234 | generate_fakes $@ 235 | fi 236 | -------------------------------------------------------------------------------- /legacy-suggest.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # gcc settings, -fatal-errors 4 | ERROR_FILE=tmp-build-errors.txt 5 | FAKES_BASENAME=tmp-xfakes 6 | SORTED_UNDEFINES=tmp-undefined-sorted.txt 7 | INCLUDE_ROOT=${INCLUDE_ROOT:-.} 8 | MAKEFILE_INCLUDE_STR=${MAKEFILE_INCLUDE_STR:-"INCLUDE_DIRS += "} 9 | MAKEFILE_WARNING_STR=${MAKEFILE_WARNING_STR:-"CPPUTEST_WARNINGFLAGS += "} 10 | 11 | # GEN_XFAKES=$(dirname $0)/gen-xfakes.sh 12 | # if [ ! -e "${GEN_XFAKES}" ]; then 13 | # echo "error: missing ${GEN_XFAKES}" 14 | # exit 1 15 | # fi 16 | # source $GEN_XFAKES 17 | 18 | looks_like() 19 | { 20 | echo "Looks like you $1" 21 | } 22 | 23 | 24 | declare -a not_declared=( 25 | "not declared in this scope" 26 | "unknown type name" 27 | ) 28 | 29 | declare -a include_head=( 30 | ".* error: '" 31 | ".* error: " 32 | ) 33 | declare -a include_tail=( 34 | ": No such file or directory" 35 | "' file not found" 36 | ) 37 | declare -a linker_error_in_file=( 38 | "error: ld" 39 | "clang: error: linker" 40 | "LNK2019" 41 | ) 42 | 43 | show_not_declared() 44 | { 45 | for text in "${not_declared[@]}"; do 46 | out=$(grep "${text}" $1) 47 | if [ "$?" = "0" ]; then 48 | echo $out 49 | looks_like "have a missing #include (${text})" 50 | return 0 51 | fi 52 | done 53 | return 1 54 | } 55 | 56 | show_missing_include_path() 57 | { 58 | for text in "${include_tail[@]}"; do 59 | out=$(grep "${text}" $1) 60 | if [ "$?" = "0" ]; then 61 | echo $out 62 | looks_like "a missing include path in your makefile (${text})" 63 | grep "#include" $1 64 | file=$(isolate_missing_file "${out}") 65 | echo "Missing include path to ${file}" 66 | suggest_include_path $file 67 | return 0 68 | fi 69 | done 70 | return 1 71 | } 72 | 73 | isolate_missing_file() 74 | { 75 | line="$@" 76 | for text in "${include_head[@]}" ]; do 77 | line=$(echo $line | sed -e"s/${text}//") 78 | done 79 | for text in "${include_tail[@]}" ]; do 80 | line=$(echo $line | sed -e"s/${text}//") 81 | done 82 | echo $line 83 | } 84 | 85 | suggest_include_path() 86 | { 87 | cd $INCLUDE_ROOT 88 | target=$(basename $1) 89 | partial_path=$(dirname $1) 90 | 91 | echo "$ cd ${INCLUDE_ROOT}" 92 | echo "$ find . -name ${target}" 93 | cd ${INCLUDE_ROOT} 94 | filepath=$(find . -name ${target}) 95 | if [ "${filepath}" == "" ]; then 96 | echo "${target} not found under ${INCLUDE_ROOT}" 97 | else 98 | echo "Path to $1 under ${INCLUDE_ROOT}" 99 | echo $filepath 100 | if [ "${partial_path}" == "." ]; then 101 | dir=$(dirname $filepath) 102 | include_path="\$(INCLUDE_ROOT)${dir#?}" 103 | echo "Add this to your makefile:" 104 | echo "${MAKEFILE_INCLUDE_STR}${include_path}" 105 | fi 106 | fi 107 | } 108 | 109 | show_noise_reduced_heading() 110 | { 111 | echo "-----------------------------------------------------" 112 | echo "--------- Noise reduced build error output ----------" 113 | echo "-----------------------------------------------------" 114 | } 115 | 116 | show_warnings() 117 | { 118 | grep "\[\-W" $1 119 | test "$?" = "1" && return 1 120 | echo "You could [temporarily] turn off the warning with" 121 | echo "${MAKEFILE_WARNING_STR}-Wno-" 122 | return 0 123 | } 124 | 125 | link_errors_exist() 126 | { 127 | rm -f $SORTED_UNDEFINES 128 | for text in "${linker_error_in_file[@]}"; do 129 | grep "${text}" $1 >/dev/null 130 | if [ "$?" == "0" ]; then 131 | return 0 132 | fi 133 | done 134 | return 1 135 | } 136 | 137 | show_other_compile_errors() 138 | { 139 | link_errors_exist $1 && return 1 140 | grep ": error: " $1 141 | [ "$?" = "1" ] && return 1 142 | echo "Sorry, I can't help with this build error." 143 | rm -f outcome.special 144 | return 0 145 | } 146 | 147 | linkErrorClang() 148 | { 149 | grep ", referenced from:" 150 | } 151 | 152 | isolateUndefinedSymbolsClang() 153 | { 154 | linkErrorClang | sed -e's/^ *"//' -e's/".*//' -e's/^_//' 155 | } 156 | 157 | linkErrorGcc() 158 | { 159 | grep ": undefined reference to " 160 | } 161 | 162 | isolateUndefinedSymbolsGcc() 163 | { 164 | linkErrorGcc | sed -e's/.*`//' -e"s/'$//" 165 | } 166 | 167 | linkErrorVS_C() 168 | { 169 | grep "LNK2019.*symbol _" 170 | } 171 | 172 | linkErrorVS_Cpp() 173 | { 174 | grep "LNK2019\|LNK2001" | grep ".*symbol \"" 175 | } 176 | 177 | isolateUndefinedSymbolsVS_C() 178 | { 179 | linkErrorVS_C | sed -e's/^.*symbol _/__C__/' -e's/ referenced.*//' -e's/__C__//' 180 | } 181 | 182 | isolateUndefinedSymbolsVS_Cpp() 183 | { 184 | linkErrorVS_Cpp | sed -e's/^.*symbol "/__CPP__/' -e's/" .*//' -e's/__CPP__//' 185 | } 186 | 187 | isolate_linker_errors() 188 | { 189 | input_file=$1 190 | must_exist $input_file 191 | undefines=$(mktemp) 192 | 193 | isolateUndefinedSymbolsGcc <$input_file >$undefines 194 | isolateUndefinedSymbolsClang <$input_file >>$undefines 195 | isolateUndefinedSymbolsVS_C <$input_file >>$undefines 196 | isolateUndefinedSymbolsVS_Cpp <$input_file >>$undefines 197 | LC_ALL=C sort $undefines | uniq >$SORTED_UNDEFINES 198 | echo "***********************************" 199 | echo "You have linker errors. See '${SORTED_UNDEFINES}' for a sorted list." 200 | echo "You have a choice to make." 201 | echo " 1) Add the missing implementation to the build." 202 | echo " 2) Add the generated exploding fakes to the build." 203 | echo " 3) Make your own fake." 204 | echo "***********************************" 205 | rm $undefines 206 | } 207 | 208 | file_empty() 209 | { 210 | [ ! -s $1 ] 211 | } 212 | 213 | legacy_suggest() 214 | { 215 | echo "one of the recognized errors" > outcome.special 216 | file_empty $1 && return 0 217 | show_noise_reduced_heading 218 | show_not_declared $1 && return 1 219 | show_missing_include_path $1 && return 1 220 | show_warnings $1 && return 1 221 | show_other_compile_errors $1 && return 1 222 | link_errors_exist $1 && isolate_linker_errors $1 223 | return 1 224 | } 225 | 226 | check_input() 227 | { 228 | if [ "$#" == "0" ]; then 229 | echo "usage: $0 compiler-output-error-file" 230 | exit 1 231 | fi 232 | 233 | if [[ ! -e "$1" ]]; then 234 | echo "Error file does not exist: $1" 235 | exit 1 236 | fi 237 | } 238 | 239 | legacy_build_suggestion() 240 | { 241 | check_input $1 && legacy_suggest $1 242 | } 243 | 244 | if [[ "$0" = "$BASH_SOURCE" ]]; then 245 | legacy_build_suggestion $1 246 | fi 247 | -------------------------------------------------------------------------------- /test/test-legacy-suggest.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | TEST_DIR=. 4 | TEMP_DIR=tmp 5 | EXAMPLES_DIR=$TEST_DIR/example-output 6 | 7 | test_get_filename_for_missing_include() 8 | { 9 | error="blah fatal error: RandomMinuteGenerator.h: No such file or directory" 10 | assertEquals 'RandomMinuteGenerator.h' $(isolate_missing_file "${error}") 11 | } 12 | 13 | test_not_declared_suggestion() 14 | { 15 | out=$(show_not_declared $EXAMPLES_DIR/gcc-undeclared-error.txt) 16 | assertEquals "show_not_declared should return 1 for not delcared errors" "0" "$?" 17 | assertContains "${out}" "#include" 18 | } 19 | 20 | find() #faking find 21 | { 22 | echo "./foo/bar/Filename.h" 23 | } 24 | 25 | test_show_missing_include_path() 26 | { 27 | out=$(show_missing_include_path $EXAMPLES_DIR/gcc-missing-include-path.txt) 28 | assertEquals "show_missing_include_path" "0" "$?" 29 | assertContains "${out}" "Missing include path to Filename.h" 30 | assertContains "${out}" 'INCLUDE_DIRS += $(INCLUDE_ROOT)/foo/bar' 31 | } 32 | 33 | test_show_missing_include_partial_path() 34 | { 35 | out=$(show_missing_include_path $EXAMPLES_DIR/gcc-missing-include-partial-path.txt) 36 | assertEquals "show_missing_include_path" "0" "$?" 37 | assertContains "${out}" "Path to foo/bar/Filename.h" 38 | assertContains "${out}" './foo/bar/Filename.h' 39 | } 40 | 41 | test_warning_suggestion() 42 | { 43 | out="$(cat $EXAMPLES_DIR/gcc-warning.txt | show_warnings)" 44 | assertEquals "show_warnings" "0" "$?" 45 | assertContains "${out}" "turn off the warning" 46 | assertContains "${out}" "-Wno-" 47 | } 48 | 49 | helper_test_link_errors_exist() 50 | { 51 | link_errors_exist $1 52 | assertEquals "link_errors_exist failed for $1" "0" "$?" 53 | } 54 | 55 | test_link_errors_exist_in_examples_gcc() 56 | { 57 | helper_test_link_errors_exist $EXAMPLES_DIR/gcc-link-error-legacy.txt 58 | helper_test_link_errors_exist $EXAMPLES_DIR/gcc-link-errors.txt 59 | } 60 | 61 | test_link_errors_exist_in_examples_clang() 62 | { 63 | helper_test_link_errors_exist $EXAMPLES_DIR/clang-link-errors.txt 64 | } 65 | 66 | test_link_errors_exist_in_examples_vs() 67 | { 68 | helper_test_link_errors_exist $EXAMPLES_DIR/vs-link-errors.txt 69 | } 70 | 71 | test_other_error_not_confused_by_linker_error() 72 | { 73 | out="$(show_other_compile_errors ${EXAMPLES_DIR}/gcc-link-error-legacy.txt)" 74 | assertEquals "show_other_compile_errors" "1" "$?" 75 | } 76 | 77 | test_other_error_give_up() 78 | { 79 | out="$(show_other_compile_errors ${EXAMPLES_DIR}/gcc-other-error.txt)" 80 | assertEquals "show_other_compile_errors" "0" "$?" 81 | assertContains "${out}" "Sorry" 82 | } 83 | 84 | ignore_test_unique_link_errors() 85 | { 86 | out="$(unique_link_errors ${EXAMPLES_DIR}/gcc-other-error.txt)" 87 | assertEquals "nothing" "${out}" 88 | } 89 | 90 | ignore_testUniqueLinkCount() 91 | { 92 | out="$(unique_link_error_count $EXAMPLES_DIR/gcc-link-error-legacy.txt)" 93 | assertEquals "5" "${out}" 94 | } 95 | 96 | show_fakes_stats() # fake 97 | { 98 | echo "Showing stats with grep" 99 | } 100 | 101 | LS_OUTPUT="" 102 | ls() 103 | { 104 | if [ "${LS_OUTPUT}" = "nothing" ]; then 105 | : 106 | else 107 | echo "fake run ls $1" 108 | fi 109 | } 110 | 111 | 112 | run_generate_fakes_script() 113 | { 114 | echo "fake run_generate_fakes_script $1 $2" 115 | } 116 | 117 | testFilterLinkerErrorsClang() 118 | { 119 | cpp_function1=' "SomeClass::someFunction(Foo&)", referenced from:' 120 | cpp_function2=' "someFunction(Foo*)", referenced from:' 121 | cpp_global=' "SomeClass::someGlobal", referenced from:' 122 | cpp_typeinfo="typeinfo for SomeClass'" 123 | c_undefined=' "_someGlobal", referenced from:' 124 | assertEquals 'SomeClass::someFunction(Foo&)' "$(echo $cpp_function1 | isolateUndefinedSymbolsClang)" 125 | assertEquals 'someFunction(Foo*)' "$(echo $cpp_function2 | isolateUndefinedSymbolsClang)" 126 | assertEquals 'SomeClass::someGlobal' "$(echo $cpp_global | isolateUndefinedSymbolsClang)" 127 | assertEquals '' "$(echo $cpp_typeinfo | isolateUndefinedSymbolsClang)" 128 | assertEquals 'someGlobal' "$(echo $c_undefined | isolateUndefinedSymbolsClang)" 129 | } 130 | 131 | testFilterLinkerErrorsGcc() 132 | { 133 | cpp_function1="blah: undefined reference to \`SomeClass::someFunction(Foo&)'" 134 | cpp_function2="blah: undefined reference to \`someFunction(Foo*)'" 135 | cpp_global="blah: undefined reference to \`SomeClass::someGlobal'" 136 | c_undefined="blah: undefined reference to \`someGlobal'" 137 | assertEquals 'SomeClass::someFunction(Foo&)' "$(echo $cpp_function1 | isolateUndefinedSymbolsGcc)" 138 | assertEquals 'someFunction(Foo*)' "$(echo $cpp_function2 | isolateUndefinedSymbolsGcc)" 139 | assertEquals 'SomeClass::someGlobal' "$(echo $cpp_global | isolateUndefinedSymbolsGcc)" 140 | assertEquals 'someGlobal' "$(echo $c_undefined | isolateUndefinedSymbolsGcc)" 141 | } 142 | 143 | testFilterLinkerErrorsVS_Cpp() 144 | { 145 | cpp_function1="blah: LNK2019 blah symbol \"SomeClass::someFunction(Foo&)\" blah blah" 146 | cpp_function2="blah: LNK2019 blah symbol \"__declspec(dllimport) someFunction(Foo*)\" blah blah" 147 | cpp_global="blah: LNK2019 blah symbol \"SomeClass::someGlobal\" blah blah" 148 | cpp_wierd_global="error LNK2001: unresolved external symbol \"public: static class beta alpha::var\" (?var@alpha@@2Vbeta@@A)" 149 | assertEquals 'SomeClass::someFunction(Foo&)' "$(echo $cpp_function1 | isolateUndefinedSymbolsVS_Cpp)" 150 | assertEquals '__declspec(dllimport) someFunction(Foo*)' "$(echo $cpp_function2 | isolateUndefinedSymbolsVS_Cpp)" 151 | assertEquals 'SomeClass::someGlobal' "$(echo $cpp_global | isolateUndefinedSymbolsVS_Cpp)" 152 | assertEquals 'public: static class beta alpha::var' "$(echo $cpp_wierd_global | isolateUndefinedSymbolsVS_Cpp)" 153 | } 154 | 155 | testFilterLinkerErrorsVS_Cpp_IgnoresC() 156 | { 157 | c_undefined="blah: LNK2019 blah symbol _someGlobal referenced blah" 158 | assertEquals '' "$(echo $c_undefined | isolateUndefinedSymbolsVS_Cpp)" 159 | } 160 | 161 | testFilterLinkerErrorsVS_C() 162 | { 163 | c_undefined="blah: LNK2019 blah symbol _someGlobal referenced blah" 164 | assertEquals 'someGlobal' "$(echo $c_undefined | isolateUndefinedSymbolsVS_C)" 165 | } 166 | 167 | testFilterLinkerErrorsVS_C_IgnoresCpp() 168 | { 169 | cpp_function1="blah: LNK2019 blah symbol \"SomeClass::someFunction(Foo&)\" blah blah" 170 | cpp_function2="blah: LNK2019 blah symbol \"__declspec(dllimport) someFunction(Foo*)\" blah blah" 171 | cpp_global="blah: LNK2019 blah symbol \"SomeClass::someGlobal\" blah blah" 172 | assertEquals '' "$(echo $cpp_function1 | isolateUndefinedSymbolsVS_C)" 173 | assertEquals '' "$(echo $cpp_function2 | isolateUndefinedSymbolsVS_C)" 174 | assertEquals '' "$(echo $cpp_global | isolateUndefinedSymbolsVS_C)" 175 | } 176 | 177 | 178 | 179 | . ../legacy-suggest.sh 180 | . ../shunit2/shunit2 181 | --------------------------------------------------------------------------------