2
0
mirror of https://github.com/boostorg/nowide.git synced 2026-02-21 15:12:30 +00:00

Merge pull request #86 from Flamefire/test_fixes

Test fixes
This commit is contained in:
Alexander Grund
2020-04-03 19:19:18 +02:00
committed by GitHub
16 changed files with 679 additions and 622 deletions

View File

@@ -34,10 +34,9 @@ pr:
- develop
variables:
- name: B2_VARIANT
value: release,debug
- name: B2_LINK
value: shared,static
B2_CI_VERSION: 1
B2_VARIANT: release,debug
B2_LINK: shared,static
stages:
@@ -126,7 +125,6 @@ stages:
B2_TOOLSET: clang
B2_CXXSTD: 03,11,14,17,2a
XCODE_APP: /Applications/Xcode_11.3.1.app
B2_LINK: static
B2_JOBS: 3 # Workaround for https://github.com/boostorg/boost-ci/issues/50
steps:
- bash: |

View File

@@ -25,48 +25,51 @@ env:
anchors:
libcpp: &libcpp { apt: { packages: [libc++-dev, libc++-helpers] } }
ubuntu-toolchain-r-test:
- &ubuntu-toolchain-r-test
sourceline: "ppa:ubuntu-toolchain-r/test"
clang-33: &clang-33 { apt: { packages: [ "clang-3.3"] } }
clang-34: &clang-34 { apt: { packages: [ "clang-3.4"] } }
clang-35: &clang-35 { apt: { packages: [ "clang-3.5"], sources: [ "ubuntu-toolchain-r-test" ] } }
clang-36: &clang-36 { apt: { packages: [ "clang-3.6"], sources: [ "ubuntu-toolchain-r-test" ] } }
clang-37: &clang-37 { apt: { packages: [ "clang-3.7"], sources: [ "ubuntu-toolchain-r-test" ] } }
clang-38: &clang-38 { apt: { packages: [ "clang-3.8"], sources: [ "ubuntu-toolchain-r-test" ] } }
clang-39: &clang-39 { apt: { packages: [ "clang-3.9"], sources: [ "ubuntu-toolchain-r-test" ] } }
clang-35: &clang-35 { apt: { packages: [ "clang-3.5"], sources: [ *ubuntu-toolchain-r-test ] } }
clang-36: &clang-36 { apt: { packages: [ "clang-3.6"], sources: [ *ubuntu-toolchain-r-test ] } }
clang-37: &clang-37 { apt: { packages: [ "clang-3.7"], sources: [ *ubuntu-toolchain-r-test ] } }
clang-38: &clang-38 { apt: { packages: [ "clang-3.8"], sources: [ *ubuntu-toolchain-r-test ] } }
clang-39: &clang-39 { apt: { packages: [ "clang-3.9"], sources: [ *ubuntu-toolchain-r-test ] } }
clang-4: &clang-4 { apt: { packages: [ "clang-4.0",
"libstdc++-6-dev" ], sources: [ "llvm-toolchain-xenial-4.0",
"ubuntu-toolchain-r-test" ] } }
*ubuntu-toolchain-r-test ] } }
clang-5: &clang-5 { apt: { packages: [ "clang-5.0",
"libstdc++-7-dev" ], sources: [ "llvm-toolchain-xenial-5.0",
"ubuntu-toolchain-r-test" ] } }
*ubuntu-toolchain-r-test ] } }
clang-6: &clang-6 { apt: { packages: [ "clang-6.0",
"libc6-dbg",
"libc++-dev",
"libstdc++-8-dev" ], sources: [ "llvm-toolchain-xenial-6.0",
"ubuntu-toolchain-r-test" ] } }
*ubuntu-toolchain-r-test ] } }
clang-7: &clang-7 { apt: { packages: [ "clang-7",
"libc6-dbg",
"libc++-dev",
"libstdc++-8-dev" ], sources: [ "llvm-toolchain-xenial-7",
"ubuntu-toolchain-r-test" ] } }
*ubuntu-toolchain-r-test ] } }
clang-8: &clang-8 { apt: { packages: [ "clang-8",
"libc6-dbg",
"libc++-dev",
"libstdc++-8-dev" ], sources: [ "llvm-toolchain-xenial-8",
"ubuntu-toolchain-r-test" ] } }
clang-9: &clang-9 { apt: { packages: [ "clang-9" ], sources: [ "ubuntu-toolchain-r-test",
*ubuntu-toolchain-r-test ] } }
clang-9: &clang-9 { apt: { packages: [ "clang-9" ], sources: [ *ubuntu-toolchain-r-test,
{ sourceline: 'deb https://apt.llvm.org/xenial/ llvm-toolchain-xenial-9 main',
key_url: 'https://apt.llvm.org/llvm-snapshot.gpg.key'} ] } }
gcc-44: &gcc-44 { apt: { packages: [ "g++-4.4" ], sources: [ "ubuntu-toolchain-r-test" ] } }
gcc-46: &gcc-46 { apt: { packages: [ "g++-4.6" ], sources: [ "ubuntu-toolchain-r-test" ] } }
gcc-47: &gcc-47 { apt: { packages: [ "g++-4.7" ], sources: [ "ubuntu-toolchain-r-test" ] } }
gcc-48: &gcc-48 { apt: { packages: [ "g++-4.8" ], sources: [ "ubuntu-toolchain-r-test" ] } }
gcc-49: &gcc-49 { apt: { packages: [ "g++-4.9" ], sources: [ "ubuntu-toolchain-r-test" ] } }
gcc-5: &gcc-5 { apt: { packages: [ "g++-5" ], sources: [ "ubuntu-toolchain-r-test" ] } }
gcc-6: &gcc-6 { apt: { packages: [ "g++-6" ], sources: [ "ubuntu-toolchain-r-test" ] } }
gcc-7: &gcc-7 { apt: { packages: [ "g++-7" ], sources: [ "ubuntu-toolchain-r-test" ] } }
gcc-8: &gcc-8 { apt: { packages: [ "g++-8" ], sources: [ "ubuntu-toolchain-r-test" ] } }
gcc-9: &gcc-9 { apt: { packages: [ "g++-9" ], sources: [ "ubuntu-toolchain-r-test" ] } }
gcc-44: &gcc-44 { apt: { packages: [ "g++-4.4" ], sources: [ *ubuntu-toolchain-r-test ] } }
gcc-46: &gcc-46 { apt: { packages: [ "g++-4.6" ], sources: [ *ubuntu-toolchain-r-test ] } }
gcc-47: &gcc-47 { apt: { packages: [ "g++-4.7" ], sources: [ *ubuntu-toolchain-r-test ] } }
gcc-48: &gcc-48 { apt: { packages: [ "g++-4.8" ], sources: [ *ubuntu-toolchain-r-test ] } }
gcc-49: &gcc-49 { apt: { packages: [ "g++-4.9" ], sources: [ *ubuntu-toolchain-r-test ] } }
gcc-5: &gcc-5 { apt: { packages: [ "g++-5" ], sources: [ *ubuntu-toolchain-r-test ] } }
gcc-6: &gcc-6 { apt: { packages: [ "g++-6" ], sources: [ *ubuntu-toolchain-r-test ] } }
gcc-7: &gcc-7 { apt: { packages: [ "g++-7" ], sources: [ *ubuntu-toolchain-r-test ] } }
gcc-8: &gcc-8 { apt: { packages: [ "g++-8" ], sources: [ *ubuntu-toolchain-r-test ] } }
gcc-9: &gcc-9 { apt: { packages: [ "g++-9" ], sources: [ *ubuntu-toolchain-r-test ] } }
jobs:
include:
@@ -77,8 +80,7 @@ jobs:
- { compiler: clang++-libc++, env: 'SANITIZERS=1 B2_CXXSTD=03,11,14', addons: *libcpp, dist: trusty }
- os: osx
compiler: clang++
# DYLD_LIBRARY_PATH causes problems on system() spawned processes -> static build only
env: SANITIZERS=1 B2_CXXSTD=03,11,14,1z B2_LINK=link=static
env: SANITIZERS=1 B2_CXXSTD=03,11,14,1z
# Codecov
- compiler: g++-8
env: COMMENT=codecov.io B2_CXXSTD=03,11 GCOV=gcov-8

View File

@@ -6,3 +6,5 @@ codecov:
wait_for_ci: yes
comment:
layout: "diff, files"
ignore:
- "test/test.hpp"

View File

@@ -33,7 +33,7 @@ run test_fstream_cxx11.cpp : : : <define>BOOST_NOWIDE_USE_FILEBUF_REPLACEMENT=1
run test_iostream.cpp ;
run test_stackstring.cpp ;
run test_stdio.cpp ;
run test_system.cpp : : : <define>BOOST_NOWIDE_TEST_USE_NARROW=1 <target-os>windows:<library>shell32 : test_system_n ;
run test_system.cpp : : : <define>BOOST_NOWIDE_TEST_USE_NARROW=1 <target-os>windows:<library>shell32 <target-os>darwin,<link>shared:<build>no : test_system_n ;
run test_system.cpp : : : <define>BOOST_NOWIDE_TEST_USE_NARROW=0 <target-os>windows:<library>shell32 <build>no <target-os>windows:<build>yes : test_system_w ;
compile benchmark_fstream.cpp : <define>BOOST_NOWIDE_USE_WIN_FSTREAM=1 <library>/boost/chrono//boost_chrono/ ;

View File

@@ -7,7 +7,8 @@
// http://www.boost.org/LICENSE_1_0.txt)
//
#include "test.hpp"
#define BOOST_NOWIDE_TEST_NO_MAIN
#include <boost/nowide/convert.hpp>
#include <boost/nowide/cstdio.hpp>
#include <boost/nowide/fstream.hpp>
@@ -22,6 +23,8 @@
#include <stdexcept>
#include <vector>
#include "test.hpp"
template<typename Key, typename Value, typename Key2>
Value get(const std::map<Key, Value>& map, const Key2& key)
{

View File

@@ -1,6 +1,6 @@
//
// Copyright (c) 2012 Artyom Beilis (Tonkikh)
// Copyright (c) 2019 Alexander Grund
// Copyright (c) 2019-2020 Alexander Grund
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
@@ -10,6 +10,7 @@
#define BOOST_NOWIDE_LIB_TEST_H_INCLUDED
#include <cstdlib>
#include <iostream>
#include <sstream>
#include <stdexcept>
@@ -51,6 +52,16 @@ inline void test_failed(const char* expr, const char* file, const int line, cons
throw std::runtime_error(ss.str());
}
template<typename T, typename U>
inline void test_equal_impl(const T& lhs, const U& rhs, const char* file, const int line, const char* function)
{
if(lhs == rhs)
return;
std::ostringstream ss;
ss << "[" << lhs << "!=" << rhs << "]";
test_failed(ss.str().c_str(), file, line, function);
}
#ifdef _MSC_VER
#define DISABLE_CONST_EXPR_DETECTED __pragma(warning(push)) __pragma(warning(disable : 4127))
#define DISABLE_CONST_EXPR_DETECTED_POP __pragma(warning(pop))
@@ -68,5 +79,31 @@ inline void test_failed(const char* expr, const char* file, const int line, cons
test_failed(#x, __FILE__, __LINE__, __FUNCTION__); \
DISABLE_CONST_EXPR_DETECTED \
} while(0) DISABLE_CONST_EXPR_DETECTED_POP
#define TEST_EQ(lhs, rhs) \
do \
{ \
test_mon(); \
test_equal_impl((lhs), (rhs), __FILE__, __LINE__, __FUNCTION__); \
break; \
DISABLE_CONST_EXPR_DETECTED \
} while(0) DISABLE_CONST_EXPR_DETECTED_POP
#endif // #ifndef BOOST_NOWIDE_LIB_TEST_H_INCLUDED
#ifndef BOOST_NOWIDE_TEST_NO_MAIN
// Tests should implement this
void test_main(int argc, char** argv, char** env);
int main(int argc, char** argv, char** env)
{
try
{
test_main(argc, argv, env);
} catch(const std::exception& e)
{
std::cerr << "Failed " << e.what() << std::endl;
return 1;
}
return 0;
}
#endif

View File

@@ -6,16 +6,18 @@
// http://www.boost.org/LICENSE_1_0.txt)
//
#include "test.hpp"
#include "test_sets.hpp"
#include <boost/nowide/convert.hpp>
#include <boost/nowide/utf8_codecvt.hpp>
#include <boost/nowide/convert.hpp>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <locale>
#include <vector>
#include "test.hpp"
#include "test_sets.hpp"
static const char* utf8_name =
"\xf0\x9d\x92\x9e-\xD0\xBF\xD1\x80\xD0\xB8\xD0\xB2\xD0\xB5\xD1\x82-\xE3\x82\x84\xE3\x81\x82.txt";
static const std::wstring wide_name_str = boost::nowide::widen(utf8_name);
@@ -318,19 +320,9 @@ void test_codecvt_subst()
run_all(codecvt_to_wide, codecvt_to_narrow);
}
int main()
void test_main(int, char**, char**)
{
try
{
test_codecvt_conv();
test_codecvt_err();
test_codecvt_subst();
} catch(const std::exception& e)
{
std::cerr << "Failed : " << e.what() << std::endl;
return 1;
}
return 0;
test_codecvt_conv();
test_codecvt_err();
test_codecvt_subst();
}

View File

@@ -6,11 +6,12 @@
// http://www.boost.org/LICENSE_1_0.txt)
//
#include "test.hpp"
#include "test_sets.hpp"
#include <boost/nowide/convert.hpp>
#include <iostream>
#include "test.hpp"
#include "test_sets.hpp"
#if defined(BOOST_MSVC) && BOOST_MSVC < 1700
#pragma warning(disable : 4428) // universal-character-name encountered in source
#endif
@@ -67,60 +68,51 @@ std::string narrow_raw_string_and_size(const std::wstring& s)
return boost::nowide::narrow(s2.c_str(), s.size());
}
int main()
void test_main(int, char**, char**)
{
try
{
std::string hello = "\xd7\xa9\xd7\x9c\xd7\x95\xd7\x9d";
std::wstring whello = L"\u05e9\u05dc\u05d5\u05dd";
std::wstring whello_3e = L"\u05e9\u05dc\u05d5\ufffd";
std::wstring whello_3 = L"\u05e9\u05dc\u05d5";
std::string hello = "\xd7\xa9\xd7\x9c\xd7\x95\xd7\x9d";
std::wstring whello = L"\u05e9\u05dc\u05d5\u05dd";
std::wstring whello_3e = L"\u05e9\u05dc\u05d5\ufffd";
std::wstring whello_3 = L"\u05e9\u05dc\u05d5";
std::cout << "- boost::nowide::widen" << std::endl;
{
const char* b = hello.c_str();
const char* e = b + hello.size();
wchar_t buf[6] = {0, 0, 0, 0, 0, 1};
TEST(boost::nowide::widen(buf, 5, b, e) == buf);
TEST(buf == whello);
TEST(buf[5] == 1);
TEST(boost::nowide::widen(buf, 4, b, e) == 0);
TEST(boost::nowide::widen(buf, 5, b, e - 1) == buf);
TEST(buf == whello_3e);
TEST(boost::nowide::widen(buf, 5, b, e - 2) == buf);
TEST(buf == whello_3);
TEST(boost::nowide::widen(buf, 5, b, b) == buf && buf[0] == 0);
TEST(boost::nowide::widen(buf, 5, b, b + 2) == buf && buf[1] == 0 && buf[0] == whello[0]);
}
std::cout << "- boost::nowide::narrow" << std::endl;
{
const wchar_t* b = whello.c_str();
const wchar_t* e = b + whello.size(); //-V594
char buf[10] = {0};
buf[9] = 1;
TEST(boost::nowide::narrow(buf, 9, b, e) == buf);
TEST(buf == hello);
TEST(buf[9] == 1);
TEST(boost::nowide::narrow(buf, 8, b, e) == 0);
TEST(boost::nowide::narrow(buf, 7, b, e - 1) == buf);
TEST(buf == hello.substr(0, 6));
}
std::cout << "- (output_buffer, buffer_size, input_raw_string)" << std::endl;
run_all(widen_buf_ptr, narrow_buf_ptr);
std::cout << "- (output_buffer, buffer_size, input_raw_string, string_len)" << std::endl;
run_all(widen_buf_range, narrow_buf_range);
std::cout << "- (input_raw_string)" << std::endl;
run_all(widen_raw_string, narrow_raw_string);
std::cout << "- (input_raw_string, size)" << std::endl;
run_all(widen_raw_string_and_size, narrow_raw_string_and_size);
std::cout << "- (const std::string&)" << std::endl;
run_all(boost::nowide::widen, boost::nowide::narrow);
} catch(const std::exception& e)
std::cout << "- boost::nowide::widen" << std::endl;
{
std::cerr << "Failed :" << e.what() << std::endl;
return 1;
const char* b = hello.c_str();
const char* e = b + hello.size();
wchar_t buf[6] = {0, 0, 0, 0, 0, 1};
TEST(boost::nowide::widen(buf, 5, b, e) == buf);
TEST(buf == whello);
TEST(buf[5] == 1);
TEST(boost::nowide::widen(buf, 4, b, e) == 0);
TEST(boost::nowide::widen(buf, 5, b, e - 1) == buf);
TEST(buf == whello_3e);
TEST(boost::nowide::widen(buf, 5, b, e - 2) == buf);
TEST(buf == whello_3);
TEST(boost::nowide::widen(buf, 5, b, b) == buf && buf[0] == 0);
TEST(boost::nowide::widen(buf, 5, b, b + 2) == buf && buf[1] == 0 && buf[0] == whello[0]);
}
std::cout << "- boost::nowide::narrow" << std::endl;
{
const wchar_t* b = whello.c_str();
const wchar_t* e = b + whello.size(); //-V594
char buf[10] = {0};
buf[9] = 1;
TEST(boost::nowide::narrow(buf, 9, b, e) == buf);
TEST(buf == hello);
TEST(buf[9] == 1);
TEST(boost::nowide::narrow(buf, 8, b, e) == 0);
TEST(boost::nowide::narrow(buf, 7, b, e - 1) == buf);
TEST(buf == hello.substr(0, 6));
}
return 0;
std::cout << "- (output_buffer, buffer_size, input_raw_string)" << std::endl;
run_all(widen_buf_ptr, narrow_buf_ptr);
std::cout << "- (output_buffer, buffer_size, input_raw_string, string_len)" << std::endl;
run_all(widen_buf_range, narrow_buf_range);
std::cout << "- (input_raw_string)" << std::endl;
run_all(widen_raw_string, narrow_raw_string);
std::cout << "- (input_raw_string, size)" << std::endl;
run_all(widen_raw_string_and_size, narrow_raw_string_and_size);
std::cout << "- (const std::string&)" << std::endl;
run_all(boost::nowide::widen, boost::nowide::narrow);
}

View File

@@ -8,7 +8,6 @@
#include <boost/nowide/cstdlib.hpp>
#include <cstring>
#include <iostream>
#if defined(BOOST_NOWIDE_TEST_INCLUDE_WINDOWS) && defined(BOOST_WINDOWS)
#include <windows.h>
@@ -28,40 +27,31 @@ void strcpy_safe(char (&dest)[size], const char* src)
dest[len] = 0;
}
int main()
void test_main(int, char**, char**)
{
try
{
std::string example = "\xd7\xa9-\xd0\xbc-\xce\xbd";
char penv[256] = {0};
strcpy_safe(penv, ("BOOST_TEST2=" + example + "x").c_str());
std::string example = "\xd7\xa9-\xd0\xbc-\xce\xbd";
char penv[256] = {0};
strcpy_safe(penv, ("BOOST_TEST2=" + example + "x").c_str());
TEST(boost::nowide::setenv("BOOST_TEST1", example.c_str(), 1) == 0);
TEST(boost::nowide::getenv("BOOST_TEST1"));
TEST(boost::nowide::getenv("BOOST_TEST1") == example);
TEST(boost::nowide::setenv("BOOST_TEST1", "xx", 0) == 0);
TEST(boost::nowide::getenv("BOOST_TEST1") == example);
TEST(boost::nowide::putenv(penv) == 0);
TEST(boost::nowide::getenv("BOOST_TEST2"));
TEST(boost::nowide::getenv("BOOST_TEST_INVALID") == 0);
TEST(boost::nowide::getenv("BOOST_TEST2") == example + "x");
TEST(boost::nowide::setenv("BOOST_TEST1", example.c_str(), 1) == 0);
TEST(boost::nowide::getenv("BOOST_TEST1"));
TEST(boost::nowide::getenv("BOOST_TEST1") == example);
TEST(boost::nowide::setenv("BOOST_TEST1", "xx", 0) == 0);
TEST(boost::nowide::getenv("BOOST_TEST1") == example);
TEST(boost::nowide::putenv(penv) == 0);
TEST(boost::nowide::getenv("BOOST_TEST2"));
TEST(boost::nowide::getenv("BOOST_TEST_INVALID") == 0);
TEST(boost::nowide::getenv("BOOST_TEST2") == example + "x");
#ifdef BOOST_WINDOWS
// Passing a variable without an equals sign (before \0) is an error
// But GLIBC has an extension that unsets the env var instead
char penv2[256] = {0};
const char* sPenv2 = "BOOST_TEST1SOMEGARBAGE=";
strcpy_safe(penv2, sPenv2);
// End the string before the equals sign -> Expect fail
penv2[strlen("BOOST_TEST1")] = '\0';
TEST(boost::nowide::putenv(penv2) == -1);
TEST(boost::nowide::getenv("BOOST_TEST1"));
TEST(boost::nowide::getenv("BOOST_TEST1") == example);
// Passing a variable without an equals sign (before \0) is an error
// But GLIBC has an extension that unsets the env var instead
char penv2[256] = {0};
const char* sPenv2 = "BOOST_TEST1SOMEGARBAGE=";
strcpy_safe(penv2, sPenv2);
// End the string before the equals sign -> Expect fail
penv2[strlen("BOOST_TEST1")] = '\0';
TEST(boost::nowide::putenv(penv2) == -1);
TEST(boost::nowide::getenv("BOOST_TEST1"));
TEST(boost::nowide::getenv("BOOST_TEST1") == example);
#endif
} catch(const std::exception& e)
{
std::cerr << "Failed " << e.what() << std::endl;
return 1;
}
return 0;
}

View File

@@ -6,66 +6,56 @@
// http://www.boost.org/LICENSE_1_0.txt)
//
#include <boost/nowide/filesystem.hpp>
#include <boost/nowide/convert.hpp>
#include <boost/nowide/cstdio.hpp>
#include <boost/nowide/filesystem.hpp>
#include <boost/nowide/fstream.hpp>
#include <boost/filesystem/operations.hpp>
#include <iostream>
#include "test.hpp"
int main()
void test_main(int, char**, char**)
{
try
boost::nowide::nowide_filesystem();
const std::string prefix = boost::filesystem::unique_path("nowide-%%%%-%%%%-").string();
const std::string utf8_name =
prefix + "\xf0\x9d\x92\x9e-\xD0\xBF\xD1\x80\xD0\xB8\xD0\xB2\xD0\xB5\xD1\x82-\xE3\x82\x84\xE3\x81\x82.txt";
{
boost::nowide::nowide_filesystem();
const std::string prefix = boost::filesystem::unique_path("nowide-%%%%-%%%%-").string();
const std::string utf8_name =
prefix + "\xf0\x9d\x92\x9e-\xD0\xBF\xD1\x80\xD0\xB8\xD0\xB2\xD0\xB5\xD1\x82-\xE3\x82\x84\xE3\x81\x82.txt";
{
boost::nowide::ofstream f(utf8_name.c_str());
TEST(f);
f << "Test" << std::endl;
}
TEST(boost::filesystem::is_regular_file(boost::nowide::widen(utf8_name)));
TEST(boost::filesystem::is_regular_file(utf8_name));
TEST(boost::nowide::remove(utf8_name.c_str()) == 0);
TEST(!boost::filesystem::is_regular_file(boost::nowide::widen(utf8_name)));
TEST(!boost::filesystem::is_regular_file(utf8_name));
const boost::filesystem::path path = utf8_name;
{
boost::nowide::ofstream f(path);
TEST(f);
f << "Test" << std::endl;
TEST(is_regular_file(path));
}
{
boost::nowide::ifstream f(path);
TEST(f);
std::string test;
f >> test;
TEST(test == "Test");
}
{
boost::nowide::fstream f(path);
TEST(f);
std::string test;
f >> test;
TEST(test == "Test");
}
boost::filesystem::remove(path);
} catch(const std::exception& e)
{
std::cerr << "Failed : " << e.what() << std::endl;
return 1;
boost::nowide::ofstream f(utf8_name.c_str());
TEST(f);
f << "Test" << std::endl;
}
std::cout << "Ok" << std::endl;
return 0;
TEST(boost::filesystem::is_regular_file(boost::nowide::widen(utf8_name)));
TEST(boost::filesystem::is_regular_file(utf8_name));
TEST(boost::nowide::remove(utf8_name.c_str()) == 0);
TEST(!boost::filesystem::is_regular_file(boost::nowide::widen(utf8_name)));
TEST(!boost::filesystem::is_regular_file(utf8_name));
const boost::filesystem::path path = utf8_name;
{
boost::nowide::ofstream f(path);
TEST(f);
f << "Test" << std::endl;
TEST(is_regular_file(path));
}
{
boost::nowide::ifstream f(path);
TEST(f);
std::string test;
f >> test;
TEST(test == "Test");
}
{
boost::nowide::fstream f(path);
TEST(f);
std::string test;
f >> test;
TEST(test == "Test");
}
boost::filesystem::remove(path);
}

View File

@@ -7,14 +7,16 @@
// http://www.boost.org/LICENSE_1_0.txt)
//
#include "test.hpp"
#include <boost/nowide/fstream.hpp>
#include <boost/nowide/convert.hpp>
#include <boost/nowide/cstdio.hpp>
#include <boost/nowide/fstream.hpp>
#include <fstream>
#include <iostream>
#include <string>
#include "test.hpp"
namespace nw = boost::nowide;
void make_empty_file(const char* filepath)
@@ -488,33 +490,24 @@ void test_is_open(const char* filename)
TEST(nw::remove(filename) == 0);
}
int main(int, char** argv)
void test_main(int, char** argv, char**)
{
const std::string exampleFilename = std::string(argv[0]) + "-\xd7\xa9-\xd0\xbc-\xce\xbd.txt";
try
{
std::cout << "Testing fstream" << std::endl;
test_ofstream_creates_file(exampleFilename.c_str());
test_ofstream_write(exampleFilename.c_str());
test_ifstream_open_read(exampleFilename.c_str());
test_fstream(exampleFilename.c_str());
test_is_open(exampleFilename.c_str());
std::cout << "Testing fstream" << std::endl;
test_ofstream_creates_file(exampleFilename.c_str());
test_ofstream_write(exampleFilename.c_str());
test_ifstream_open_read(exampleFilename.c_str());
test_fstream(exampleFilename.c_str());
test_is_open(exampleFilename.c_str());
std::cout << "Complex IO" << std::endl;
test_with_different_buffer_sizes(exampleFilename.c_str());
std::cout << "Complex IO" << std::endl;
test_with_different_buffer_sizes(exampleFilename.c_str());
std::cout << "filebuf::close" << std::endl;
test_close(exampleFilename.c_str());
std::cout << "filebuf::close" << std::endl;
test_close(exampleFilename.c_str());
std::cout << "Flush - Sanity Check" << std::endl;
test_flush<std::ifstream, std::ofstream>(exampleFilename.c_str());
std::cout << "Flush - Test" << std::endl;
test_flush<nw::ifstream, nw::ofstream>(exampleFilename.c_str());
} catch(const std::exception& e)
{
std::cerr << e.what() << std::endl;
return 1;
}
std::cout << "Ok" << std::endl;
return 0;
std::cout << "Flush - Sanity Check" << std::endl;
test_flush<std::ifstream, std::ofstream>(exampleFilename.c_str());
std::cout << "Flush - Test" << std::endl;
test_flush<nw::ifstream, nw::ofstream>(exampleFilename.c_str());
}

View File

@@ -10,13 +10,14 @@
#if BOOST_NOWIDE_CXX11
#include "test.hpp"
#include <boost/nowide/cstdio.hpp>
#include <boost/nowide/fstream.hpp>
#include <iostream>
#include <boost/nowide/cstdio.hpp>
#include <iterator>
#include <utility>
#include "test.hpp"
namespace nw = boost::nowide;
void create_file(const std::string& filename, const std::string& contents)
@@ -180,21 +181,12 @@ void test_fstream(const std::string& filename)
TEST(nw::remove(filename.c_str()) == 0);
}
int main(int, char** argv)
void test_main(int, char** argv, char**)
{
const std::string exampleFilename = std::string(argv[0]) + "-\xd7\xa9-\xd0\xbc-\xce\xbd.txt";
try
{
test_ifstream(exampleFilename);
test_ofstream(exampleFilename);
test_fstream(exampleFilename);
} catch(const std::exception& e)
{
std::cerr << e.what() << std::endl;
return 1;
}
std::cout << "Ok" << std::endl;
return 0;
test_ifstream(exampleFilename);
test_ofstream(exampleFilename);
test_fstream(exampleFilename);
}
#else
@@ -204,7 +196,6 @@ int main(int, char** argv)
int main()
{
std::cout << "Test skipped as there is no C++11 support by the compiler" << std::endl;
return 0;
}
#endif

View File

@@ -6,9 +6,9 @@
// http://www.boost.org/LICENSE_1_0.txt)
//
#include <boost/nowide/detail/utf.hpp>
#include <boost/nowide/iostream.hpp>
#include <iostream>
#include <boost/nowide/detail/utf.hpp>
#include <string>
#include "test.hpp"
@@ -25,7 +25,7 @@ bool isValidUTF8(const std::string& s)
return true;
}
int main(int argc, char** argv)
void test_main(int argc, char** argv, char**)
{
const char* example = "Basic letters: \xd7\xa9-\xd0\xbc-\xce\xbd\n"
"East Asian Letters: \xe5\x92\x8c\xe5\xb9\xb3\n"
@@ -33,64 +33,55 @@ int main(int argc, char** argv)
"Invalid UTF-8: `\xFF' `\xd7\xFF' `\xe5\xFF\x8c' `\xf0\x9d\x84\xFF' \n"
"\n";
try
// If we are using the standard rdbuf we can only put back 1 char
if(boost::nowide::cin.rdbuf() == std::cin.rdbuf())
{
// If we are using the standard rdbuf we can only put back 1 char
if(boost::nowide::cin.rdbuf() == std::cin.rdbuf())
std::cout << "Using std::cin" << std::endl;
int maxval = 15000;
for(int i = 0; i < maxval; i++)
{
std::cout << "Using std::cin" << std::endl;
int maxval = 15000;
for(int i = 0; i < maxval; i++)
{
char c = i % 96 + ' ';
TEST(boost::nowide::cin.putback(c));
int ci = i % 96 + ' ';
TEST(boost::nowide::cin.get() == ci);
}
} else
{
int maxval = 15000;
for(int i = 0; i < maxval; i++)
{
char c = i % 96 + ' ';
TEST(boost::nowide::cin.putback(c));
}
for(int i = maxval - 1; i >= 0; i--)
{
int c = i % 96 + ' ';
TEST(boost::nowide::cin.get() == c);
}
char c = i % 96 + ' ';
TEST(boost::nowide::cin.putback(c));
int ci = i % 96 + ' ';
TEST(boost::nowide::cin.get() == ci);
}
boost::nowide::cout << "Normal I/O:" << std::endl;
boost::nowide::cout << example << std::endl;
boost::nowide::cerr << example << std::endl;
boost::nowide::cout << "Flushing each character:" << std::endl;
for(const char* s = example; *s; s++)
} else
{
int maxval = 15000;
for(int i = 0; i < maxval; i++)
{
boost::nowide::cout << *s << std::flush;
TEST(boost::nowide::cout);
char c = i % 96 + ' ';
TEST(boost::nowide::cin.putback(c));
}
for(int i = maxval - 1; i >= 0; i--)
{
int c = i % 96 + ' ';
TEST(boost::nowide::cin.get() == c);
}
}
boost::nowide::cout << "Normal I/O:" << std::endl;
boost::nowide::cout << example << std::endl;
boost::nowide::cerr << example << std::endl;
boost::nowide::cout << "Flushing each character:" << std::endl;
for(const char* s = example; *s; s++)
{
boost::nowide::cout << *s << std::flush;
TEST(boost::nowide::cout);
TEST(boost::nowide::cerr);
if(argc == 2 && argv[1] == std::string("-i"))
{
std::string v1, v2;
boost::nowide::cin >> v1 >> v2;
TEST(boost::nowide::cin);
TEST(isValidUTF8(v1));
TEST(isValidUTF8(v2));
boost::nowide::cout << "First: " << v1 << std::endl;
boost::nowide::cout << "Second: " << v2 << std::endl;
TEST(boost::nowide::cout);
}
} catch(const std::exception& e)
{
std::cerr << "Fail: " << e.what() << std::endl;
return 1;
}
return 0;
TEST(boost::nowide::cout);
TEST(boost::nowide::cerr);
if(argc == 2 && argv[1] == std::string("-i"))
{
std::string v1, v2;
boost::nowide::cin >> v1 >> v2;
TEST(boost::nowide::cin);
TEST(isValidUTF8(v1));
TEST(isValidUTF8(v2));
boost::nowide::cout << "First: " << v1 << std::endl;
boost::nowide::cout << "Second: " << v2 << std::endl;
TEST(boost::nowide::cout);
}
}

View File

@@ -7,12 +7,13 @@
// http://www.boost.org/LICENSE_1_0.txt)
//
#include "test.hpp"
#include "test_sets.hpp"
#include <boost/nowide/stackstring.hpp>
#include <iostream>
#include <vector>
#include "test.hpp"
#include "test_sets.hpp"
#if defined(BOOST_MSVC) && BOOST_MSVC < 1700
#pragma warning(disable : 4428) // universal-character-name encountered in source
#endif
@@ -71,194 +72,185 @@ std::string heap_stackstring_to_narrow(const std::wstring& s)
return ss.get();
}
int main()
void test_main(int, char**, char**)
{
try
{
std::string hello = "\xd7\xa9\xd7\x9c\xd7\x95\xd7\x9d";
std::wstring whello = boost::nowide::widen(hello);
const wchar_t* wempty = L"";
std::string hello = "\xd7\xa9\xd7\x9c\xd7\x95\xd7\x9d";
std::wstring whello = boost::nowide::widen(hello);
const wchar_t* wempty = L"";
{
std::cout << "-- Default constructed string is NULL" << std::endl;
const boost::nowide::short_stackstring s;
TEST(s.get() == NULL);
}
{
std::cout << "-- NULL ptr passed to ctor results in NULL" << std::endl;
const boost::nowide::short_stackstring s(NULL);
TEST(s.get() == NULL);
const boost::nowide::short_stackstring s2(NULL, NULL);
TEST(s2.get() == NULL);
}
{
std::cout << "-- NULL ptr passed to convert results in NULL" << std::endl;
boost::nowide::short_stackstring s(L"foo");
TEST(s.get() == std::string("foo"));
s.convert(NULL);
TEST(s.get() == NULL);
boost::nowide::short_stackstring s2(L"foo");
TEST(s2.get() == std::string("foo"));
s2.convert(NULL, NULL);
TEST(s2.get() == NULL);
}
{
std::cout << "-- An empty string is accepted" << std::endl;
const boost::nowide::short_stackstring s(wempty);
TEST(s.get());
TEST(s.get() == std::string());
const boost::nowide::short_stackstring s2(wempty, wempty);
TEST(s2.get());
TEST(s2.get() == std::string());
}
{
std::cout << "-- An empty string is accepted" << std::endl;
boost::nowide::short_stackstring s, s2;
TEST(s.convert(wempty));
TEST(s.get() == std::string());
TEST(s2.convert(wempty, wempty));
TEST(s2.get() == std::string());
}
{
std::cout << "-- Will be put on heap" << std::endl;
test_basic_stackstring<wchar_t, char, 3> sw;
TEST(sw.convert(hello.c_str()));
TEST(sw.uses_heap_memory());
TEST(sw.get() == whello);
TEST(sw.convert(hello.c_str(), hello.c_str() + hello.size()));
TEST(sw.uses_heap_memory());
TEST(sw.get() == whello);
}
{
std::cout << "-- Will be put on stack" << std::endl;
test_basic_stackstring<wchar_t, char, 40> sw;
TEST(sw.convert(hello.c_str()));
TEST(sw.uses_stack_memory());
TEST(sw.get() == whello);
TEST(sw.convert(hello.c_str(), hello.c_str() + hello.size()));
TEST(sw.uses_stack_memory());
TEST(sw.get() == whello);
}
{
std::cout << "-- Will be put on heap" << std::endl;
test_basic_stackstring<char, wchar_t, 3> sw;
TEST(sw.convert(whello.c_str()));
TEST(sw.uses_heap_memory());
TEST(sw.get() == hello);
TEST(sw.convert(whello.c_str(), whello.c_str() + whello.size()));
TEST(sw.uses_heap_memory());
TEST(sw.get() == hello);
}
{
std::cout << "-- Will be put on stack" << std::endl;
test_basic_stackstring<char, wchar_t, 40> sw;
TEST(sw.convert(whello.c_str()));
TEST(sw.uses_stack_memory());
TEST(sw.get() == hello);
TEST(sw.convert(whello.c_str(), whello.c_str() + whello.size()));
TEST(sw.uses_stack_memory());
TEST(sw.get() == hello);
}
{
typedef test_basic_stackstring<wchar_t, char, 6> stackstring;
const std::wstring heapVal = L"heapValue";
const std::wstring stackVal = L"stack";
const stackstring heap(boost::nowide::narrow(heapVal).c_str());
const stackstring stack(boost::nowide::narrow(stackVal).c_str());
TEST(heap.uses_heap_memory());
TEST(stack.uses_stack_memory());
{
stackstring sw2(heap), sw3, sEmpty;
sw3 = heap;
TEST(sw2.get() == heapVal);
TEST(sw3.get() == heapVal);
// Self assign avoiding clang self-assign-overloaded warning
sw3 = static_cast<const stackstring&>(sw3); //-V570
TEST(sw3.get() == heapVal);
// Assign empty
sw3 = sEmpty; //-V820
TEST(sw3.get() == NULL);
}
{
stackstring sw2(stack), sw3, sEmpty;
sw3 = stack;
TEST(sw2.get() == stackVal);
TEST(sw3.get() == stackVal);
// Self assign avoiding clang self-assign-overloaded warning
sw3 = static_cast<const stackstring&>(sw3); //-V570
TEST(sw3.get() == stackVal);
// Assign empty
sw3 = sEmpty; //-V820
TEST(sw3.get() == NULL);
}
{
stackstring sw2(stack);
sw2 = heap;
TEST(sw2.get() == heapVal);
}
{
stackstring sw2(heap);
sw2 = stack;
TEST(sw2.get() == stackVal);
}
{
stackstring sw2(heap), sw3(stack), sEmpty1, sEmpty2;
swap(sw2, sw3);
TEST(sw2.get() == stackVal);
TEST(sw3.get() == heapVal);
swap(sw2, sw3);
TEST(sw2.get() == heapVal);
TEST(sw3.get() == stackVal);
swap(sw2, sEmpty1);
TEST(sEmpty1.get() == heapVal);
TEST(sw2.get() == NULL);
swap(sw3, sEmpty2);
TEST(sEmpty2.get() == stackVal);
TEST(sw3.get() == NULL);
}
{
stackstring sw2(heap), sw3(heap);
sw3.get()[0] = 'z';
const std::wstring val2 = sw3.get();
swap(sw2, sw3);
TEST(sw2.get() == val2);
TEST(sw3.get() == heapVal);
}
{
stackstring sw2(stack), sw3(stack);
sw3.get()[0] = 'z';
const std::wstring val2 = sw3.get();
swap(sw2, sw3);
TEST(sw2.get() == val2);
TEST(sw3.get() == stackVal);
}
std::cout << "-- Sanity check" << std::endl;
TEST(stack.get() == stackVal);
TEST(heap.get() == heapVal);
}
{
std::cout << "-- Test putting stackstrings into vector (done by args) class" << std::endl;
// Use a smallish buffer, to have stack and heap values
typedef boost::nowide::basic_stackstring<wchar_t, char, 5> stackstring;
std::vector<stackstring> strings;
strings.resize(2);
TEST(strings[0].convert("1234") == std::wstring(L"1234"));
TEST(strings[1].convert("Hello World") == std::wstring(L"Hello World"));
strings.push_back(stackstring("FooBar"));
TEST(strings[0].get() == std::wstring(L"1234"));
TEST(strings[1].get() == std::wstring(L"Hello World"));
TEST(strings[2].get() == std::wstring(L"FooBar"));
}
std::cout << "- Stackstring" << std::endl;
run_all(stackstring_to_wide, stackstring_to_narrow);
std::cout << "- Heap Stackstring" << std::endl;
run_all(heap_stackstring_to_wide, heap_stackstring_to_narrow);
} catch(const std::exception& e)
{
std::cerr << "Failed :" << e.what() << std::endl;
return 1;
std::cout << "-- Default constructed string is NULL" << std::endl;
const boost::nowide::short_stackstring s;
TEST(s.get() == NULL);
}
{
std::cout << "-- NULL ptr passed to ctor results in NULL" << std::endl;
const boost::nowide::short_stackstring s(NULL);
TEST(s.get() == NULL);
const boost::nowide::short_stackstring s2(NULL, NULL);
TEST(s2.get() == NULL);
}
{
std::cout << "-- NULL ptr passed to convert results in NULL" << std::endl;
boost::nowide::short_stackstring s(L"foo");
TEST(s.get() == std::string("foo"));
s.convert(NULL);
TEST(s.get() == NULL);
boost::nowide::short_stackstring s2(L"foo");
TEST(s2.get() == std::string("foo"));
s2.convert(NULL, NULL);
TEST(s2.get() == NULL);
}
{
std::cout << "-- An empty string is accepted" << std::endl;
const boost::nowide::short_stackstring s(wempty);
TEST(s.get());
TEST(s.get() == std::string());
const boost::nowide::short_stackstring s2(wempty, wempty);
TEST(s2.get());
TEST(s2.get() == std::string());
}
{
std::cout << "-- An empty string is accepted" << std::endl;
boost::nowide::short_stackstring s, s2;
TEST(s.convert(wempty));
TEST(s.get() == std::string());
TEST(s2.convert(wempty, wempty));
TEST(s2.get() == std::string());
}
{
std::cout << "-- Will be put on heap" << std::endl;
test_basic_stackstring<wchar_t, char, 3> sw;
TEST(sw.convert(hello.c_str()));
TEST(sw.uses_heap_memory());
TEST(sw.get() == whello);
TEST(sw.convert(hello.c_str(), hello.c_str() + hello.size()));
TEST(sw.uses_heap_memory());
TEST(sw.get() == whello);
}
{
std::cout << "-- Will be put on stack" << std::endl;
test_basic_stackstring<wchar_t, char, 40> sw;
TEST(sw.convert(hello.c_str()));
TEST(sw.uses_stack_memory());
TEST(sw.get() == whello);
TEST(sw.convert(hello.c_str(), hello.c_str() + hello.size()));
TEST(sw.uses_stack_memory());
TEST(sw.get() == whello);
}
{
std::cout << "-- Will be put on heap" << std::endl;
test_basic_stackstring<char, wchar_t, 3> sw;
TEST(sw.convert(whello.c_str()));
TEST(sw.uses_heap_memory());
TEST(sw.get() == hello);
TEST(sw.convert(whello.c_str(), whello.c_str() + whello.size()));
TEST(sw.uses_heap_memory());
TEST(sw.get() == hello);
}
{
std::cout << "-- Will be put on stack" << std::endl;
test_basic_stackstring<char, wchar_t, 40> sw;
TEST(sw.convert(whello.c_str()));
TEST(sw.uses_stack_memory());
TEST(sw.get() == hello);
TEST(sw.convert(whello.c_str(), whello.c_str() + whello.size()));
TEST(sw.uses_stack_memory());
TEST(sw.get() == hello);
}
{
typedef test_basic_stackstring<wchar_t, char, 6> stackstring;
const std::wstring heapVal = L"heapValue";
const std::wstring stackVal = L"stack";
const stackstring heap(boost::nowide::narrow(heapVal).c_str());
const stackstring stack(boost::nowide::narrow(stackVal).c_str());
TEST(heap.uses_heap_memory());
TEST(stack.uses_stack_memory());
return 0;
{
stackstring sw2(heap), sw3, sEmpty;
sw3 = heap;
TEST(sw2.get() == heapVal);
TEST(sw3.get() == heapVal);
// Self assign avoiding clang self-assign-overloaded warning
sw3 = static_cast<const stackstring&>(sw3); //-V570
TEST(sw3.get() == heapVal);
// Assign empty
sw3 = sEmpty; //-V820
TEST(sw3.get() == NULL);
}
{
stackstring sw2(stack), sw3, sEmpty;
sw3 = stack;
TEST(sw2.get() == stackVal);
TEST(sw3.get() == stackVal);
// Self assign avoiding clang self-assign-overloaded warning
sw3 = static_cast<const stackstring&>(sw3); //-V570
TEST(sw3.get() == stackVal);
// Assign empty
sw3 = sEmpty; //-V820
TEST(sw3.get() == NULL);
}
{
stackstring sw2(stack);
sw2 = heap;
TEST(sw2.get() == heapVal);
}
{
stackstring sw2(heap);
sw2 = stack;
TEST(sw2.get() == stackVal);
}
{
stackstring sw2(heap), sw3(stack), sEmpty1, sEmpty2;
swap(sw2, sw3);
TEST(sw2.get() == stackVal);
TEST(sw3.get() == heapVal);
swap(sw2, sw3);
TEST(sw2.get() == heapVal);
TEST(sw3.get() == stackVal);
swap(sw2, sEmpty1);
TEST(sEmpty1.get() == heapVal);
TEST(sw2.get() == NULL);
swap(sw3, sEmpty2);
TEST(sEmpty2.get() == stackVal);
TEST(sw3.get() == NULL);
}
{
stackstring sw2(heap), sw3(heap);
sw3.get()[0] = 'z';
const std::wstring val2 = sw3.get();
swap(sw2, sw3);
TEST(sw2.get() == val2);
TEST(sw3.get() == heapVal);
}
{
stackstring sw2(stack), sw3(stack);
sw3.get()[0] = 'z';
const std::wstring val2 = sw3.get();
swap(sw2, sw3);
TEST(sw2.get() == val2);
TEST(sw3.get() == stackVal);
}
std::cout << "-- Sanity check" << std::endl;
TEST(stack.get() == stackVal);
TEST(heap.get() == heapVal);
}
{
std::cout << "-- Test putting stackstrings into vector (done by args) class" << std::endl;
// Use a smallish buffer, to have stack and heap values
typedef boost::nowide::basic_stackstring<wchar_t, char, 5> stackstring;
std::vector<stackstring> strings;
strings.resize(2);
TEST(strings[0].convert("1234") == std::wstring(L"1234"));
TEST(strings[1].convert("Hello World") == std::wstring(L"Hello World"));
strings.push_back(stackstring("FooBar"));
TEST(strings[0].get() == std::wstring(L"1234"));
TEST(strings[1].get() == std::wstring(L"Hello World"));
TEST(strings[2].get() == std::wstring(L"FooBar"));
}
std::cout << "- Stackstring" << std::endl;
run_all(stackstring_to_wide, stackstring_to_narrow);
std::cout << "- Heap Stackstring" << std::endl;
run_all(heap_stackstring_to_wide, heap_stackstring_to_narrow);
}

View File

@@ -50,7 +50,7 @@ void noop_invalid_param_handler(const wchar_t*, const wchar_t*, const wchar_t*,
{}
#endif
int main(int, char** argv)
void test_main(int, char** argv, char**)
{
const std::string prefix = argv[0];
const std::string filename = prefix + "\xd7\xa9-\xd0\xbc-\xce\xbd.txt";
@@ -59,95 +59,86 @@ int main(int, char** argv)
_set_invalid_parameter_handler(noop_invalid_param_handler);
#endif
try
std::cout << " -- fopen - existing file" << std::endl;
{
std::cout << " -- fopen - existing file" << std::endl;
{
create_test_file(filename);
FILE* f = boost::nowide::fopen(filename.c_str(), "r");
TEST(f);
char buf[16];
TEST(std::fgets(buf, 16, f) != 0);
TEST(strcmp(buf, "test\n") == 0);
std::fclose(f);
}
std::cout << " -- remove" << std::endl;
{
create_test_file(filename);
TEST(file_exists(filename));
TEST(boost::nowide::remove(filename.c_str()) == 0);
TEST(!file_exists(filename));
}
std::cout << " -- fopen non-existing file" << std::endl;
{
boost::nowide::remove(filename.c_str());
TEST(!file_exists(filename));
TEST(boost::nowide::fopen(filename.c_str(), "r") == NULL);
TEST(!file_exists(filename));
}
std::cout << " -- freopen" << std::endl;
{
create_test_file(filename);
FILE* f = boost::nowide::fopen(filename.c_str(), "r+");
TEST(f);
std::cout << " -- Can read & write" << std::endl;
{
char buf[32];
TEST(std::fgets(buf, 32, f) != 0);
TEST(strcmp(buf, "test\n") == 0);
TEST(std::fseek(f, 0, SEEK_END) == 0);
TEST(std::fputs("foobar\n", f) >= 0);
}
// Reopen in read mode
// Note that changing the mode is not possibly on all implementations
// E.g. MSVC disallows NULL completely as the file parameter
FILE* f2 = boost::nowide::freopen(NULL, "r", f);
if(!f2)
f2 = boost::nowide::freopen(filename.c_str(), "r", f);
std::cout << " -- no write possible" << std::endl;
{
TEST(f2 == f);
TEST(std::fputs("not-written\n", f) < 0);
TEST(std::fseek(f, 0, SEEK_SET) == 0);
char buf[32];
TEST(std::fgets(buf, 32, f) != 0);
TEST(strcmp(buf, "test\n") == 0);
TEST(std::fgets(buf, 32, f) != 0);
TEST(strcmp(buf, "foobar\n") == 0);
}
std::cout << " -- Reopen different file" << std::endl;
const std::string filename2 = filename + ".1.txt";
TEST(boost::nowide::freopen(filename2.c_str(), "w", f) == f);
{
char buf[32];
TEST(std::fputs("baz\n", f) >= 0);
std::fclose(f);
f = boost::nowide::fopen(filename2.c_str(), "r");
TEST(f);
TEST(std::fgets(buf, 32, f) != 0);
TEST(strcmp(buf, "baz\n") == 0);
}
std::fclose(f);
boost::nowide::remove(filename2.c_str());
}
std::cout << " -- rename" << std::endl;
{
create_test_file(filename);
const std::string filename2 = filename + ".1.txt";
boost::nowide::remove(filename2.c_str());
TEST(file_exists(filename));
TEST(!file_exists(filename2));
TEST(boost::nowide::rename(filename.c_str(), filename2.c_str()) == 0);
TEST(!file_exists(filename));
TEST(file_exists(filename2));
TEST(boost::nowide::remove(filename.c_str()) < 0);
TEST(boost::nowide::remove(filename2.c_str()) == 0);
}
} catch(const std::exception& e)
{
std::cerr << "Failed " << e.what() << std::endl;
return 1;
create_test_file(filename);
FILE* f = boost::nowide::fopen(filename.c_str(), "r");
TEST(f);
char buf[16];
TEST(std::fgets(buf, 16, f) != 0);
TEST(strcmp(buf, "test\n") == 0);
std::fclose(f);
}
std::cout << " -- remove" << std::endl;
{
create_test_file(filename);
TEST(file_exists(filename));
TEST(boost::nowide::remove(filename.c_str()) == 0);
TEST(!file_exists(filename));
}
std::cout << " -- fopen non-existing file" << std::endl;
{
boost::nowide::remove(filename.c_str());
TEST(!file_exists(filename));
TEST(boost::nowide::fopen(filename.c_str(), "r") == NULL);
TEST(!file_exists(filename));
}
std::cout << " -- freopen" << std::endl;
{
create_test_file(filename);
FILE* f = boost::nowide::fopen(filename.c_str(), "r+");
TEST(f);
std::cout << " -- Can read & write" << std::endl;
{
char buf[32];
TEST(std::fgets(buf, 32, f) != 0);
TEST(strcmp(buf, "test\n") == 0);
TEST(std::fseek(f, 0, SEEK_END) == 0);
TEST(std::fputs("foobar\n", f) >= 0);
}
// Reopen in read mode
// Note that changing the mode is not possibly on all implementations
// E.g. MSVC disallows NULL completely as the file parameter
FILE* f2 = boost::nowide::freopen(NULL, "r", f);
if(!f2)
f2 = boost::nowide::freopen(filename.c_str(), "r", f);
std::cout << " -- no write possible" << std::endl;
{
TEST(f2 == f);
TEST(std::fputs("not-written\n", f) < 0);
TEST(std::fseek(f, 0, SEEK_SET) == 0);
char buf[32];
TEST(std::fgets(buf, 32, f) != 0);
TEST(strcmp(buf, "test\n") == 0);
TEST(std::fgets(buf, 32, f) != 0);
TEST(strcmp(buf, "foobar\n") == 0);
}
std::cout << " -- Reopen different file" << std::endl;
const std::string filename2 = filename + ".1.txt";
TEST(boost::nowide::freopen(filename2.c_str(), "w", f) == f);
{
char buf[32];
TEST(std::fputs("baz\n", f) >= 0);
std::fclose(f);
f = boost::nowide::fopen(filename2.c_str(), "r");
TEST(f);
TEST(std::fgets(buf, 32, f) != 0);
TEST(strcmp(buf, "baz\n") == 0);
}
std::fclose(f);
boost::nowide::remove(filename2.c_str());
}
std::cout << " -- rename" << std::endl;
{
create_test_file(filename);
const std::string filename2 = filename + ".1.txt";
boost::nowide::remove(filename2.c_str());
TEST(file_exists(filename));
TEST(!file_exists(filename2));
TEST(boost::nowide::rename(filename.c_str(), filename2.c_str()) == 0);
TEST(!file_exists(filename));
TEST(file_exists(filename2));
TEST(boost::nowide::remove(filename.c_str()) < 0);
TEST(boost::nowide::remove(filename2.c_str()) == 0);
}
return 0;
}

View File

@@ -5,81 +5,174 @@
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#ifdef _MSC_VER
#define _CRT_SECURE_NO_WARNINGS
#endif
#include "test.hpp"
#include <boost/nowide/args.hpp>
#include <boost/nowide/cstdlib.hpp>
#include <boost/nowide/args.hpp>
#include <boost/nowide/detail/convert.hpp>
#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <string>
#include <vector>
int main(int argc, char** argv, char** env)
#include "test.hpp"
bool is_ascii(const std::string& s)
{
try
for(std::string::const_iterator it = s.begin(); it != s.end(); ++it)
{
std::string example = "\xd7\xa9-\xd0\xbc-\xce\xbd";
boost::nowide::args a(argc, argv, env);
if(argc == 2 && argv[1][0] != '-')
if(static_cast<unsigned char>(*it) > 0x7F)
return false;
}
return true;
}
std::string replace_non_ascii(const std::string& s)
{
std::string::const_iterator it = s.begin();
namespace utf = boost::nowide::detail::utf;
typedef utf::utf_traits<char> utf8;
std::string result;
result.reserve(s.size());
while(it != s.end())
{
utf::code_point c = utf8::decode(it, s.end());
TEST(c != utf::illegal && c != utf::incomplete);
if(c > 0x7F)
c = '?'; // WinAPI seems to do this
result.push_back(static_cast<char>(c));
}
return result;
}
void compare_string_arrays(char** main_val, char** utf8_val, bool sort)
{
std::vector<std::string> vec_main, vec_utf8;
for(; *main_val; ++main_val)
vec_main.push_back(std::string(*main_val));
for(; *utf8_val; ++utf8_val)
vec_utf8.push_back(std::string(*utf8_val));
// Same number of strings
TEST_EQ(vec_main.size(), vec_utf8.size());
if(sort)
{
// Order doesn't matter
std::sort(vec_main.begin(), vec_main.end());
std::sort(vec_utf8.begin(), vec_utf8.end());
}
for(size_t i = 0; i < vec_main.size(); ++i)
{
// Skip strings with non-ascii chars
if(is_ascii(vec_main[i]) && vec_main[i] != vec_utf8[i])
TEST_EQ(vec_main[i], replace_non_ascii(vec_utf8[i]));
}
}
void compare_getenv(char** env)
{
// For all all variables in env check against getenv
for(char** e = env; *e != 0; e++)
{
const char* key_begin = *e;
const char* key_end = strchr(key_begin, '=');
TEST(key_end);
std::string key = std::string(key_begin, key_end);
const char* std_value = std::getenv(key.c_str());
const char* bnw_value = boost::nowide::getenv(key.c_str());
// If std_value is set, bnw value must be too and be equal, else bnw value must be unset too
if(std_value)
{
TEST(argv[1] == example);
TEST(argv[2] == 0);
TEST(boost::nowide::getenv("BOOST_NOWIDE_TEST"));
TEST(boost::nowide::getenv("BOOST_NOWIDE_TEST_NONE") == 0);
TEST(boost::nowide::getenv("BOOST_NOWIDE_TEST") == example);
// Empty variables are unreliable on windows, hence skip. E.g. using "set FOO=" unsets FOO
TEST(bnw_value);
// Compare only if ascii
if(is_ascii(std_value) && std::string(std_value) != std::string(bnw_value))
TEST_EQ(std_value, replace_non_ascii(bnw_value));
} else
TEST(!bnw_value);
}
}
const std::string example = "\xd7\xa9-\xd0\xbc-\xce\xbd";
void run_child(int argc, char** argv, char** env)
{
// Test arguments
TEST(argc == 2);
TEST_EQ(argv[1], example);
TEST(argv[2] == 0);
// Test getenv
TEST(boost::nowide::getenv("BOOST_NOWIDE_TEST"));
TEST_EQ(boost::nowide::getenv("BOOST_NOWIDE_TEST"), example);
TEST(boost::nowide::getenv("BOOST_NOWIDE_TEST_NONE") == 0);
// Empty variables are unreliable on windows, hence skip. E.g. using "set FOO=" unsets FOO
#ifndef BOOST_WINDOWS
TEST(boost::nowide::getenv("BOOST_NOWIDE_EMPTY"));
TEST(boost::nowide::getenv("BOOST_NOWIDE_EMPTY") == std::string());
TEST(boost::nowide::getenv("BOOST_NOWIDE_EMPTY"));
TEST_EQ(boost::nowide::getenv("BOOST_NOWIDE_EMPTY"), std::string());
#endif // !_WIN32
std::string sample = "BOOST_NOWIDE_TEST=" + example;
bool found = false;
for(char** e = env; *e != 0; e++)
{
char* eptr = *e;
std::cout << "Checking " << eptr << std::endl;
char* key_end = strchr(eptr, '=');
TEST(key_end);
std::string key = std::string(eptr, key_end);
std::string value = key_end + 1;
#ifdef BOOST_WINDOWS
if(value.empty())
continue;
#endif
std::cout << "Key: " << key << " Value: " << value << std::endl;
TEST(boost::nowide::getenv(key.c_str()));
TEST(boost::nowide::getenv(key.c_str()) == value);
if(*e == sample)
found = true;
}
TEST(found);
std::cout << "Subprocess ok" << std::endl;
} else if(argc == 1)
{
#if BOOST_NOWIDE_TEST_USE_NARROW
TEST(boost::nowide::setenv("BOOST_NOWIDE_TEST", example.c_str(), 1) == 0);
TEST(boost::nowide::setenv("BOOST_NOWIDE_TEST_NONE", example.c_str(), 1) == 0);
TEST(boost::nowide::unsetenv("BOOST_NOWIDE_TEST_NONE") == 0);
TEST(boost::nowide::setenv("BOOST_NOWIDE_EMPTY", "", 1) == 0);
TEST(boost::nowide::getenv("BOOST_NOWIDE_EMPTY"));
std::string command = "\"";
command += argv[0];
command += "\" ";
command += example;
TEST(boost::nowide::system(command.c_str()) == 0);
std::cout << "Parent ok" << std::endl;
#else
std::wstring envVar = L"BOOST_NOWIDE_TEST=" + boost::nowide::widen(example);
TEST(_wputenv(envVar.c_str()) == 0);
std::wstring wcommand = boost::nowide::widen(argv[0]) + L" " + boost::nowide::widen(example);
TEST(_wsystem(wcommand.c_str()) == 0);
std::cout << "Wide Parent ok" << std::endl;
#endif
}
} catch(const std::exception& e)
// This must be contained in env
std::string sample = "BOOST_NOWIDE_TEST=" + example;
bool found = false;
for(char** e = env; *e != 0; e++)
{
std::cerr << "Failed " << e.what() << std::endl;
return 1;
if(*e == sample)
found = true;
}
TEST(found);
return 0;
std::cout << "Subprocess ok" << std::endl;
}
void run_parent(const char* exe_path)
{
#if BOOST_NOWIDE_TEST_USE_NARROW
TEST(boost::nowide::setenv("BOOST_NOWIDE_TEST", example.c_str(), 1) == 0);
TEST(boost::nowide::setenv("BOOST_NOWIDE_TEST_NONE", example.c_str(), 1) == 0);
TEST(boost::nowide::unsetenv("BOOST_NOWIDE_TEST_NONE") == 0);
TEST(boost::nowide::setenv("BOOST_NOWIDE_EMPTY", "", 1) == 0);
TEST(boost::nowide::getenv("BOOST_NOWIDE_EMPTY"));
std::string command = "\"";
command += exe_path;
command += "\" ";
command += example;
TEST(boost::nowide::system(command.c_str()) == 0);
std::cout << "Parent ok" << std::endl;
#else
std::wstring envVar = L"BOOST_NOWIDE_TEST=" + boost::nowide::widen(example);
TEST(_wputenv(envVar.c_str()) == 0);
std::wstring wcommand = boost::nowide::widen(exe_path) + L" " + boost::nowide::widen(example);
TEST(_wsystem(wcommand.c_str()) == 0);
std::cout << "Wide Parent ok" << std::endl;
#endif
}
void test_main(int argc, char** argv, char** env)
{
const int old_argc = argc;
char** old_argv = argv;
char** old_env = env;
{
boost::nowide::args _(argc, argv, env);
TEST(argc == old_argc);
std::cout << "Checking arguments" << std::endl;
compare_string_arrays(old_argv, argv, false);
std::cout << "Checking env" << std::endl;
compare_string_arrays(old_env, env, true);
compare_getenv(env);
}
// When `args` is destructed the old values must be restored
TEST(argc == old_argc);
TEST(argv == old_argv);
TEST(env == old_env);
boost::nowide::args a(argc, argv, env);
if(argc == 1)
run_parent(argv[0]);
else
run_child(argc, argv, env);
}