Skip to content

Instantly share code, notes, and snippets.

@mhamrah
Last active January 7, 2016 05:12
Show Gist options
  • Save mhamrah/79ed07a00209754a0ab1 to your computer and use it in GitHub Desktop.
Save mhamrah/79ed07a00209754a0ab1 to your computer and use it in GitHub Desktop.
#if !defined(REQUIRE_EQUAL_CONTAINERS_H)
#define REQUIRE_EQUAL_CONTAINERS_H
#include <boost/version.hpp>
#include <utility>
#include <vector>
#if BOOST_VERSION >= 105900
namespace boost
{
namespace test_tools
{
namespace tt_detail
{
// teach Boost.Test how to print std::vector<T>
template <typename T>
inline std::ostream &operator<<(std::ostream &str, std::vector<T> const &items)
{
str << '[';
bool first = true;
for (auto const& element : items) {
str << (!first ? "," : "") << element;
first = false;
}
return str << ']';
}
// teach Boost.Test how to print std::pair<K,V>
template <typename K, typename V>
inline std::ostream &operator<<(std::ostream &str, std::pair<K, V> const& item)
{
return str << '<' << item.first << ',' << item.second << '>';
}
} // namespace tt_detail
} // namespace test_tools
} // namespace boost
#else // BOOST_VERSION < 105900
namespace boost
{
// teach Boost.Test how to print std::vector to wrap_stringstream
template <typename T>
inline wrap_stringstream&
operator<<(wrap_stringstream& wrapped, std::vector<T> const& item)
{
wrapped << '[';
bool first = true;
for (auto const& element : item) {
wrapped << (!first ? "," : "") << element;
first = false;
}
return wrapped << ']';
}
// teach Boost.Test how to print std::pair<K,V> to wrap_stringstream
template <typename K, typename V>
inline wrap_stringstream &operator<<(wrap_stringstream &str, std::pair<K, V> const& item)
{
return str << '<' << item.first << ',' << item.second << '>';
}
namespace test_tools
{
// teach Boost.Test how to print std::pair with BOOST_REQUIRE_EQUAL
template<>
struct print_log_value<std::pair<int, int>>
{
void operator()(std::ostream& ostr, std::pair<int, int> const& item)
{
ostr << '<' << item.first << ',' << item.second << '>';
}
};
} // namespace test_tools
} // namespace boost
#endif // BOOST_VERSION
#define REQUIRE_EQUAL_CONTAINERS(left_, right_) \
BOOST_REQUIRE_EQUAL_COLLECTIONS(left_.begin(), left_.end(), right_.begin(), right_.end())
#endif
#if !defined(WORD_COUNT_H)
#define WORD_COUNT_H
#include <map>
#include <string>
namespace word_count
{
std::map<std::string, int> words(std::string const& text);
}
#endif
#include "word_count.h"
#include <algorithm>
#include <cctype>
#include <iterator>
#include <vector>
#include <boost/algorithm/string.hpp>
using namespace std;
namespace
{
string normalize_text(string const& text)
{
string normalized;
transform(text.begin(), text.end(), back_inserter(normalized),
[](const char c) { return (isalnum(c) || c == '\'') ? tolower(c) : ' '; });
return normalized;
}
string trim_word(string const& word)
{
return boost::trim_copy_if(word, boost::is_any_of("' "));
}
vector<string> split_text_into_words(string const& text)
{
vector<string> words;
boost::split(words, text, boost::is_any_of("\t "));
transform(words.begin(), words.end(), words.begin(), trim_word);
return words;
}
}
namespace word_count
{
map<string, int> words(string const& text)
{
map<string, int> count;
for (auto const& word : split_text_into_words(normalize_text(text)))
{
if (!word.empty())
{
++count[word];
}
}
return count;
}
}
#include "word_count.h"
#define BOOST_TEST_MAIN
#include <boost/test/unit_test.hpp>
#include <map>
#include "require_equal_containers.h"
using namespace std;
BOOST_AUTO_TEST_CASE(counts_one_word)
{
const map<string, int> expected{{"word", 1}};
const auto actual = word_count::words("word");
REQUIRE_EQUAL_CONTAINERS(expected, actual);
}
#if defined(EXERCISM_RUN_ALL_TESTS)
BOOST_AUTO_TEST_CASE(counts_one_of_each)
{
const map<string, int> expected{{"one", 1}, {"of", 1}, {"each", 1}};
const auto actual = word_count::words("one of each");
REQUIRE_EQUAL_CONTAINERS(expected, actual);
}
BOOST_AUTO_TEST_CASE(counts_multiple_occurrences)
{
const map<string, int> expected{{"one", 1}, {"fish", 4}, {"two", 1}, {"red", 1}, {"blue", 1}};
const auto actual = word_count::words("one fish two fish red fish blue fish");
REQUIRE_EQUAL_CONTAINERS(expected, actual);
}
BOOST_AUTO_TEST_CASE(ignores_punctuation)
{
const map<string, int> expected{{"car", 1}, {"carpet", 1}, {"as", 1}, {"java", 1}, {"javascript", 1}};
const auto actual = word_count::words("car : carpet as java : javascript!!&@$%^&");
REQUIRE_EQUAL_CONTAINERS(expected, actual);
}
BOOST_AUTO_TEST_CASE(includes_numbers)
{
const map<string, int> expected{{"testing", 2}, {"1", 1}, {"2", 1}};
const auto actual = word_count::words("testing, 1, 2 testing");
REQUIRE_EQUAL_CONTAINERS(expected, actual);
}
BOOST_AUTO_TEST_CASE(normalizes_case)
{
const map<string, int> expected{{"go", 3}};
const auto actual = word_count::words("go Go GO");
REQUIRE_EQUAL_CONTAINERS(expected, actual);
}
BOOST_AUTO_TEST_CASE(counts_constructor)
{
const map<string, int> expected{{"constructor", 2}};
const auto actual = word_count::words("constructor Constructor");
REQUIRE_EQUAL_CONTAINERS(expected, actual);
}
BOOST_AUTO_TEST_CASE(counts_multiline)
{
const map<string, int> expected{{"hello", 1}, {"world", 1}};
const auto actual = word_count::words("hello\nworld");
REQUIRE_EQUAL_CONTAINERS(expected, actual);
}
BOOST_AUTO_TEST_CASE(count_everything_just_once)
{
const map<string, int> expected{{"all", 2}, {"the", 2}, {"kings", 2}, {"horses", 1}, {"and", 1}, {"men", 1}};
const auto actual = word_count::words("all the kings horses and all the kings men");
REQUIRE_EQUAL_CONTAINERS(expected, actual);
}
BOOST_AUTO_TEST_CASE(handles_cramped_list)
{
const map<string, int> expected{{"one", 1}, {"two", 1}, {"three", 1}};
const auto actual = word_count::words("one,two,three");
REQUIRE_EQUAL_CONTAINERS(expected, actual);
}
BOOST_AUTO_TEST_CASE(with_apostrophes)
{
const map<string, int> expected{{"first", 1}, {"don't", 2}, {"laugh", 1}, {"then", 1}, {"cry", 1}};
const auto actual = word_count::words("First: don't laugh. Then: don't cry.");
REQUIRE_EQUAL_CONTAINERS(expected, actual);
}
BOOST_AUTO_TEST_CASE(with_free_standing_apostrophes)
{
const map<string, int> expected{{ "go", 3 }};
const auto actual = word_count::words("go ' Go '' GO");
REQUIRE_EQUAL_CONTAINERS(expected, actual);
}
BOOST_AUTO_TEST_CASE(with_apostrophes_as_quotes)
{
const map<string, int> expected{{"she", 1}, {"said", 1}, {"let's", 1}, {"meet", 1}, {"at", 1}, {"twelve", 1}, {"o'clock", 1}};
const auto actual = word_count::words("She said, 'let's meet at twelve o'clock'");
REQUIRE_EQUAL_CONTAINERS(expected, actual);
}
#endif
@LegalizeAdulthood
Copy link

Compile error:

~/dev/gh/xcpp/word-count/build remotes/upstream/boost*
> make
Scanning dependencies of target word-count
[ 33%] Building CXX object CMakeFiles/word-count.dir/word_count_test.cpp.o
In file included from /Users/mhamrah/dev/gh/xcpp/word-count/word_count_test.cpp:3:
In file included from /usr/local/include/boost/test/unit_test.hpp:18:
In file included from /usr/local/include/boost/test/test_tools.hpp:38:
In file included from /usr/local/include/boost/test/tools/old/impl.hpp:24:
/usr/local/include/boost/test/tools/detail/print_helper.hpp:50:14: error: call to function 'operator<<' that is neither visible in the template definition nor found by argument-dependent lookup
        ostr << t;
             ^
/usr/local/include/boost/test/tools/detail/print_helper.hpp:172:5: note: in instantiation of member function 'boost::test_tools::tt_detail::print_log_value<std::__1::pair<const std::__1::basic_string<char>, int> >::operator()' requested here
    print_log_value<T>()( ostr, ph.m_t );
    ^
/usr/local/include/boost/test/utils/wrap_stringstream.hpp:66:19: note: in instantiation of function template specialization 'boost::test_tools::tt_detail::operator<<<std::__1::pair<const std::__1::basic_string<char>, int> >' requested here
    targ.stream() << t;
                  ^
/usr/local/include/boost/test/tools/old/impl.hpp:212:19: note: in instantiation of function template specialization 'boost::operator<<<char, boost::test_tools::tt_detail::print_helper_t<std::__1::pair<const std::__1::basic_string<char>, int> > >' requested here
                  << ::boost::test_tools::tt_detail::print_helper(*left_begin)
                  ^
/Users/mhamrah/dev/gh/xcpp/word-count/word_count_test.cpp:15:5: note: in instantiation of function template specialization 'boost::test_tools::tt_detail::equal_coll_impl::operator()<std::__1::__map_const_iterator<std::__1::__tree_const_iterator<std::__1::__value_type<std::__1::basic_string<char>, int>, std::__1::__tree_node<std::__1::__value_type<std::__1::basic_string<char>, int>, void *> *, long> >, std::__1::__map_const_iterator<std::__1::__tree_const_iterator<std::__1::__value_type<std::__1::basic_string<char>, int>, std::__1::__tree_node<std::__1::__value_type<std::__1::basic_string<char>, int>, void *> *, long> > >' requested here
    REQUIRE_EQUAL_CONTAINERS(expected, actual);
    ^
/Users/mhamrah/dev/gh/xcpp/word-count/require_equal_containers.h:86:5: note: expanded from macro 'REQUIRE_EQUAL_CONTAINERS
    BOOST_REQUIRE_EQUAL_COLLECTIONS(left_.begin(), left_.end(), right_.begin(), r...
    ^
/usr/local/include/boost/test/tools/old/interface.hpp:245:5: note: expanded from macro 'BOOST_REQUIRE_EQUAL_COLLECTIONS'
    BOOST_TEST_TOOL_IMPL( 1, ::boost::test_tools::tt_detail::equal_coll_impl(),         \
    ^
/usr/local/include/boost/test/tools/old/interface.hpp:66:9: note: expanded from macro 'BOOST_TEST_TOOL_IMPL'
        BOOST_JOIN( BOOST_TEST_TOOL_PASS_PRED, frwd_type )( P, ARGS ), \
        ^
note: (skipping 3 expansions in backtrace; use -fmacro-backtrace-limit=0 to see all)
<scratch space>:88:1: note: expanded from here
BOOST_TEST_TOOL_PASS_PRED1
^
/usr/local/include/boost/test/tools/old/interface.hpp:48:49: note: expanded from macro 'BOOST_TEST_TOOL_PASS_PRED1'
#define BOOST_TEST_TOOL_PASS_PRED1( P, ARGS ) P BOOST_PP_SEQ_TO_TUPLE(ARGS)
                                                ^
/usr/local/include/boost/preprocessor/seq/to_tuple.hpp:21:40: note: expanded from macro 'BOOST_PP_SEQ_TO_TUPLE'
#    define BOOST_PP_SEQ_TO_TUPLE(seq) (BOOST_PP_SEQ_ENUM(seq))
                                       ^
/Users/mhamrah/dev/gh/xcpp/word-count/require_equal_containers.h:32:22: note: 'operator<<' should be declared prior to the call site
inline std::ostream &operator<<(std::ostream &str, std::pair<K, V> const& item)
                     ^
1 error generated.
make[2]: *** [CMakeFiles/word-count.dir/word_count_test.cpp.o] Error 1
make[1]: *** [CMakeFiles/word-count.dir/all] Error 2
make: *** [all] Error 2

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment