Add Catch unittest framework and some tests.

This commit is contained in:
John Preston 2017-08-30 20:36:12 +03:00
parent 48e2a5472e
commit 5faca8d4f6
17 changed files with 453 additions and 39 deletions

4
.gitignore vendored
View File

@ -18,6 +18,10 @@
/Telegram/Resources/art/sprite_125x.png
/Telegram/Resources/art/sprite_150x.png
/Telegram/Debug/
/Telegram/Release/
/Telegram/tests/
/Telegram/gyp/tests/*.test
/Telegram/out/
/Telegram/*.user
*.vcxproj*
*.sln

3
.gitmodules vendored
View File

@ -7,3 +7,6 @@
[submodule "Telegram/ThirdParty/GSL"]
path = Telegram/ThirdParty/GSL
url = https://github.com/Microsoft/GSL.git
[submodule "Telegram/ThirdParty/Catch"]
path = Telegram/ThirdParty/Catch
url = https://github.com/philsquared/Catch

View File

@ -37,6 +37,7 @@ The source code is published under GPLv3 with OpenSSL exception, the license is
* Mapbox Variant ([BSD License](https://github.com/mapbox/variant/blob/master/LICENSE))
* Open Sans font ([Apache License 2.0](http://www.apache.org/licenses/LICENSE-2.0.html))
* Emoji alpha codes ([MIT License](https://github.com/emojione/emojione/blob/master/extras/alpha-codes/LICENSE.md))
* Catch test framework ([Boost License](https://github.com/philsquared/Catch/blob/master/LICENSE.txt))
## Build instructions

View File

@ -1,33 +1,5 @@
diff --git a/pylib/gyp/generator/cmake.py b/pylib/gyp/generator/cmake.py
index a2b9629..68d7020 100644
--- a/pylib/gyp/generator/cmake.py
+++ b/pylib/gyp/generator/cmake.py
@@ -1070,6 +1070,23 @@ def WriteTarget(namer, qualified_target, target_dicts, build_dir, config_to_use,
output.write(')\n')
+ # Precompile header
+ precompiled_header = config.get('cmake_precompiled_header', '')
+ if precompiled_header:
+ precompiled_header_script = config.get('cmake_precompiled_header_script', '')
+ if not precompiled_header_script:
+ print ('ERROR: cmake_precompiled_header requires cmake_precompiled_header_script')
+ cmake_precompiled_header = NormjoinPath(path_from_cmakelists_to_gyp, precompiled_header)
+ cmake_precompiled_header_script = NormjoinPathForceCMakeSource(path_from_cmakelists_to_gyp, precompiled_header_script)
+ output.write('include(')
+ output.write(cmake_precompiled_header_script)
+ output.write(')\n')
+ output.write('add_precompiled_header(')
+ output.write(cmake_target_name)
+ output.write(' ')
+ output.write(cmake_precompiled_header)
+ output.write(')\n')
+
UnsetVariable(output, 'TOOLSET')
UnsetVariable(output, 'TARGET')
diff --git a/pylib/gyp/generator/xcode.py b/pylib/gyp/generator/xcode.py
index db99d6a..f8398cc 100644
index 0e3fb93..4c824ec 100644
--- a/pylib/gyp/generator/xcode.py
+++ b/pylib/gyp/generator/xcode.py
@@ -72,6 +72,10 @@ generator_additional_non_configuration_keys = [
@ -41,7 +13,7 @@ index db99d6a..f8398cc 100644
'mac_bundle',
'mac_bundle_resources',
'mac_framework_headers',
@@ -772,6 +776,26 @@ def GenerateOutput(target_list, target_dicts, data, params):
@@ -761,6 +765,26 @@ def GenerateOutput(target_list, target_dicts, data, params):
xcode_targets[qualified_target] = xct
xcode_target_to_target_dict[xct] = spec
@ -68,3 +40,13 @@ index db99d6a..f8398cc 100644
spec_actions = spec.get('actions', [])
spec_rules = spec.get('rules', [])
@@ -1130,7 +1154,8 @@ exit 1
groups = [x for x in groups if not x.endswith('_excluded')]
for group in groups:
for item in rule.get(group, []):
- pbxp.AddOrGetFileInRootGroup(item)
+ concrete_item = ExpandXcodeVariables(item, rule_input_dict)
+ pbxp.AddOrGetFileInRootGroup(concrete_item)
# Add "sources".
for source in spec.get('sources', []):

View File

@ -20,6 +20,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#pragma once
#include <deque>
#include "base/optional.h"
namespace base {

View File

@ -0,0 +1,51 @@
/*
This file is part of Telegram Desktop,
the official desktop version of Telegram messaging app, see https://telegram.org
Telegram Desktop is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
It is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
In addition, as a special exception, the copyright holders give permission
to link the code of portions of this program with the OpenSSL library.
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#include "catch.hpp"
#include "base/flat_map.h"
#include <string>
using namespace std;
TEST_CASE("flat_maps should keep items sorted by key", "[flat_map]") {
base::flat_map<int, string> v;
v.emplace(0, "a");
v.emplace(5, "b");
v.emplace(4, "d");
v.emplace(2, "e");
auto checkSorted = [&] {
auto prev = v.begin();
REQUIRE(prev != v.end());
for (auto i = prev + 1; i != v.end(); prev = i, ++i) {
REQUIRE(prev->first < i->first);
}
};
REQUIRE(v.size() == 4);
checkSorted();
SECTION("adding item puts it in the right position") {
v.emplace(3, "c");
REQUIRE(v.size() == 5);
REQUIRE(v.find(3) != v.end());
checkSorted();
}
}

View File

@ -20,6 +20,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#pragma once
#include <deque>
namespace base {
template <typename Type>

View File

@ -0,0 +1,48 @@
/*
This file is part of Telegram Desktop,
the official desktop version of Telegram messaging app, see https://telegram.org
Telegram Desktop is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
It is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
In addition, as a special exception, the copyright holders give permission
to link the code of portions of this program with the OpenSSL library.
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#include "catch.hpp"
#include "base/flat_set.h"
TEST_CASE("flat_sets should keep items sorted", "[flat_set]") {
base::flat_set<int> v;
v.insert(0);
v.insert(5);
v.insert(4);
v.insert(2);
auto checkSorted = [&] {
auto prev = v.begin();
REQUIRE(prev != v.end());
for (auto i = prev + 1; i != v.end(); prev = i, ++i) {
REQUIRE(*prev < *i);
}
};
REQUIRE(v.size() == 4);
checkSorted();
SECTION("adding item puts it in the right position") {
v.insert(3);
REQUIRE(v.size() == 5);
REQUIRE(v.find(3) != v.end());
checkSorted();
}
}

View File

@ -0,0 +1,97 @@
/*
This file is part of Telegram Desktop,
the official desktop version of Telegram messaging app, see https://telegram.org
Telegram Desktop is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
It is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
In addition, as a special exception, the copyright holders give permission
to link the code of portions of this program with the OpenSSL library.
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#define CATCH_CONFIG_RUNNER
#include "catch.hpp"
#include "reporters/catch_reporter_compact.hpp"
#include <QFile>
namespace Catch {
struct MinimalReporter : CompactReporter {
MinimalReporter( ReporterConfig const& _config )
: CompactReporter( _config )
{}
virtual void testRunEnded( TestRunStats const& _testRunStats ) {
printTotals( _testRunStats.totals );
}
private:
// Colour, message variants:
// - white: No tests ran.
// - red: Failed [both/all] N test cases, failed [both/all] M assertions.
// - white: Passed [both/all] N test cases (no assertions).
// - red: Failed N tests cases, failed M assertions.
// - green: Passed [both/all] N tests cases with M assertions.
std::string bothOrAll( std::size_t count ) const {
return count == 1 ? std::string() : count == 2 ? "both " : "all " ;
}
void printTotals( const Totals& totals ) const {
if( totals.testCases.total() == 0 ) {
}
else if( totals.testCases.failed == totals.testCases.total() ) {
Colour colour( Colour::ResultError );
const std::string qualify_assertions_failed =
totals.assertions.failed == totals.assertions.total() ?
bothOrAll( totals.assertions.failed ) : std::string();
stream <<
"Failed " << bothOrAll( totals.testCases.failed )
<< pluralise( totals.testCases.failed, "test case" ) << ", "
"failed " << qualify_assertions_failed <<
pluralise( totals.assertions.failed, "assertion" ) << '.';
}
else if( totals.assertions.total() == 0 ) {
stream <<
"Passed " << bothOrAll( totals.testCases.total() )
<< pluralise( totals.testCases.total(), "test case" )
<< " (no assertions).";
}
else if( totals.assertions.failed ) {
Colour colour( Colour::ResultError );
stream <<
"Failed " << pluralise( totals.testCases.failed, "test case" ) << ", "
"failed " << pluralise( totals.assertions.failed, "assertion" ) << '.';
}
else {
}
}
};
INTERNAL_CATCH_REGISTER_REPORTER( "minimal", MinimalReporter )
} // end namespace Catch
int main(int argc, const char *argv[]) {
const char *catch_argv[] = { argv[0], "-r", "minimal" };
constexpr auto catch_argc = sizeof(catch_argv) / sizeof(catch_argv[0]);
auto result = Catch::Session().run(catch_argc, catch_argv);
if (result == 0) {
for (auto i = 0; i != argc; ++i) {
if (argv[i] == QString("--touch") && i + 1 != argc) {
QFile(QFile::decodeName(argv[++i])).open(QIODevice::WriteOnly);
}
}
}
return (result < 0xff ? result : 0xff);
}

1
Telegram/ThirdParty/Catch vendored Submodule

@ -0,0 +1 @@
Subproject commit 5ca44b68721833ae3731802ed99af67c6f38a53a

View File

@ -4,7 +4,10 @@ set "FullScriptPath=%~dp0"
set "FullExecPath=%cd%"
set "Command=%1"
if "%Command%" == "header" (
if "%Command%" == "test" (
call :write_test %2
exit /b %errorlevel%
) else if "%Command%" == "header" (
call :write_header %2
exit /b %errorlevel%
) else if "%Command%" == "source" (
@ -87,6 +90,34 @@ exit /b %errorlevel%
exit /b
)
:write_test
(
set "CommandPath=%1"
set "CommandPathUnix=!CommandPath:\=/!"
set "CommandPathWin=!CommandPath:/=\!"
if "!CommandPathUnix!" == "" (
echo Provide source path.
exit /b 1
) else if exist "SourceFiles\!CommandPathWin!.cpp" (
echo This source already exists.
exit /b 1
)
echo Generating test !CommandPathUnix!.cpp..
mkdir "SourceFiles\!CommandPathWin!.cpp"
rmdir "SourceFiles\!CommandPathWin!.cpp"
call :write_comment !CommandPathWin!.cpp
set "quote="""
set "quote=!quote:~0,1!"
set "source1=#include !quote!catch.hpp!quote!"
(
echo !source1!
echo.
)>> "SourceFiles\!CommandPathWin!.cpp"
exit /b
)
:write_comment
(
set "Path=%1"

View File

@ -79,6 +79,7 @@
'codegen.gyp:codegen_lang',
'codegen.gyp:codegen_numbers',
'codegen.gyp:codegen_style',
'tests/tests.gyp:tests',
'utils.gyp:Updater',
'../ThirdParty/libtgvoip/libtgvoip.gyp:libtgvoip',
],

View File

@ -225,14 +225,14 @@
'<(linux_lib_ssl)',
'<(linux_lib_crypto)',
'<!@(python -c "for s in \'<(linux_lib_icu)\'.split(\' \'): print(s)")',
'xcb',
'X11',
'X11-xcb',
'dbus-1',
'dl',
'gthread-2.0',
'glib-2.0',
'pthread',
'-lxcb',
'-lX11',
'-lX11-xcb',
'-ldbus-1',
'-ldl',
'-lgthread-2.0',
'-lglib-2.0',
'-lpthread',
],
'include_dirs': [
'<(qt_loc)/mkspecs/linux-g++',

View File

@ -0,0 +1,34 @@
# This file is part of Telegram Desktop,
# the official desktop version of Telegram messaging app, see https://telegram.org
#
# Telegram Desktop is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# It is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# In addition, as a special exception, the copyright holders give permission
# to link the code of portions of this program with the OpenSSL library.
#
# Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
# Copyright (c) 2014 John Preston, https://desktop.telegram.org
{
'includes': [
'../common_executable.gypi',
'../qt.gypi',
],
'include_dirs': [
'<(src_loc)',
'<(submodules_loc)/GSL/include',
'<(submodules_loc)/variant/include',
'<(submodules_loc)/Catch/include'
],
'sources': [
'<(src_loc)/base/tests_main.cpp',
],
}

View File

@ -0,0 +1,79 @@
'''
This file is part of Telegram Desktop,
the official desktop version of Telegram messaging app, see https://telegram.org
Telegram Desktop is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
It is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
In addition, as a special exception, the copyright holders give permission
to link the code of portions of this program with the OpenSSL library.
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014 John Preston, https://desktop.telegram.org
'''
from __future__ import print_function
import sys
import os
import re
import time
import codecs
def eprint(*args, **kwargs):
print(*args, file=sys.stderr, **kwargs)
sys.exit(1)
my_path = os.path.dirname(os.path.realpath(__file__)).replace('\\', '/')
next_input_path = 0
input_path = ''
write_sources = 0
next_self = 1
for arg in sys.argv:
if next_self != 0:
next_self = 0
continue
if arg == '--sources':
write_sources = 1
continue
if arg == '--input':
next_input_path = 1
continue
elif next_input_path == 1:
next_input_path = 0
input_path = arg
continue
tests_names = []
if input_path != '':
if not os.path.isfile(input_path):
eprint('Input path not found.')
else:
with open(input_path, 'r') as f:
for line in f:
test_name = line.strip()
if test_name[0:2] != '//' and test_name != '':
tests_names.append(test_name)
if write_sources != 0:
tests_path = my_path + '/';
if not os.path.isdir(tests_path):
os.mkdir(tests_path)
for test_name in tests_names:
test_path = tests_path + test_name + '.test'
if not os.path.isfile(test_path):
with open(test_path, 'w') as out:
out.write('1')
print(test_name + '.test')
else:
for test_name in tests_names:
print(test_name)

View File

@ -0,0 +1,77 @@
# This file is part of Telegram Desktop,
# the official desktop version of Telegram messaging app, see https://telegram.org
#
# Telegram Desktop is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# It is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# In addition, as a special exception, the copyright holders give permission
# to link the code of portions of this program with the OpenSSL library.
#
# Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
# Copyright (c) 2014 John Preston, https://desktop.telegram.org
{
'includes': [
'../common.gypi',
],
'variables': {
'libs_loc': '../../../../Libraries',
'src_loc': '../../SourceFiles',
'submodules_loc': '../../ThirdParty',
'mac_target': '10.10',
'list_tests_command': 'python <(DEPTH)/tests/list_tests.py --input <(DEPTH)/tests/tests_list.txt',
},
'targets': [{
'target_name': 'tests',
'type': 'none',
'includes': [
'../common.gypi',
],
'dependencies': [
'<!@(<(list_tests_command))',
],
'sources': [
'<!@(<(list_tests_command) --sources)',
],
'rules': [{
'rule_name': 'run_tests',
'extension': 'test',
'inputs': [
'<(PRODUCT_DIR)/<(RULE_INPUT_ROOT)<(exe_ext)',
],
'outputs': [
'<(SHARED_INTERMEDIATE_DIR)/<(RULE_INPUT_ROOT).timestamp',
],
'action': [
'<(PRODUCT_DIR)/<(RULE_INPUT_ROOT)<(exe_ext)',
'--touch', '<(SHARED_INTERMEDIATE_DIR)/<(RULE_INPUT_ROOT).timestamp',
],
'message': 'Running <(RULE_INPUT_ROOT)..',
}]
}, {
'target_name': 'tests_flat_map',
'includes': [
'common_test.gypi',
],
'sources': [
'<(src_loc)/base/flat_map.h',
'<(src_loc)/base/flat_map_tests.cpp',
],
}, {
'target_name': 'tests_flat_set',
'includes': [
'common_test.gypi',
],
'sources': [
'<(src_loc)/base/flat_set.h',
'<(src_loc)/base/flat_set_tests.cpp',
],
}],
}

View File

@ -0,0 +1,2 @@
tests_flat_map
tests_flat_set