/////////////////////////////////////////////////////////////////////////////// // env_var.cpp // // Copyright 2012 Eric Niebler. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #include #include #include #include #include #include namespace proto = boost::proto; BOOST_PROTO_DEFINE_ENV_VAR(tag0_type, tag0); struct abstract { virtual ~abstract() = 0; }; abstract::~abstract() {} struct concrete : abstract { ~concrete() {} }; template void assert_has_env_var(Env const &) { BOOST_MPL_ASSERT((proto::result_of::has_env_var)); } template void assert_has_env_var_not(Env const &) { BOOST_MPL_ASSERT_NOT((proto::result_of::has_env_var)); } void test_is_env() { BOOST_MPL_ASSERT_NOT((proto::is_env)); BOOST_MPL_ASSERT_NOT((proto::is_env)); BOOST_MPL_ASSERT_NOT((proto::is_env)); BOOST_MPL_ASSERT_NOT((proto::is_env)); BOOST_MPL_ASSERT_NOT((proto::is_env)); BOOST_MPL_ASSERT_NOT((proto::is_env)); BOOST_MPL_ASSERT((proto::is_env)); BOOST_MPL_ASSERT((proto::is_env)); BOOST_MPL_ASSERT((proto::is_env)); BOOST_MPL_ASSERT((proto::is_env >)); BOOST_MPL_ASSERT((proto::is_env &>)); BOOST_MPL_ASSERT((proto::is_env const &>)); } void test_as_env() { proto::env e0 = proto::as_env(2); BOOST_CHECK_EQUAL(e0[proto::data], 2); assert_has_env_var(e0); assert_has_env_var_not(e0); int i = 39; proto::env e1 = proto::as_env(boost::ref(i)); assert_has_env_var(i); assert_has_env_var_not(i); BOOST_CHECK_EQUAL(e1[proto::data], 39); BOOST_CHECK_EQUAL(&e1[proto::data], &i); proto::empty_env e2 = proto::as_env(proto::empty_env()); proto::env e3 = proto::as_env(e1); proto::env & e4 = proto::as_env(boost::ref(e1)); BOOST_CHECK_EQUAL(&e4, &e1); concrete c; abstract &a = c; std::stringstream sout; int rgi[2] = {}; proto::env e5 = proto::as_env(a); proto::env e6 = proto::as_env(sout); BOOST_CHECK_EQUAL(&e6[proto::data], &sout); proto::env e7 = proto::as_env(rgi); BOOST_CHECK_EQUAL(&e7[proto::data][0], &rgi[0]); proto::env e8 = proto::as_env(test_as_env); BOOST_CHECK_EQUAL(&e8[proto::data], &test_as_env); } void test_comma() { proto::env e0 = (proto::data = 1); BOOST_CHECK_EQUAL(e0[proto::data], 1); int i = 39; proto::env e1 = (proto::data = boost::ref(i)); BOOST_CHECK_EQUAL(e1[proto::data], 39); BOOST_CHECK_EQUAL(&e1[proto::data], &i); concrete c; abstract &a = c; std::stringstream sout; int rgi[2] = {}; proto::env e5 = (proto::data = a); proto::env e6 = (proto::data = sout); BOOST_CHECK_EQUAL(&e6[proto::data], &sout); proto::env e7 = (proto::data = rgi); BOOST_CHECK_EQUAL(&e7[proto::data][0], &rgi[0]); // The test below fails on msvc due to a compiler bug // note: #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600)) proto::env e8 = (proto::data = boost::ref(test_as_env)); BOOST_CHECK_EQUAL(&e8[proto::data], &test_as_env); #else proto::env e8 = (proto::data = test_as_env); BOOST_CHECK_EQUAL(&e8[proto::data], &test_as_env); #endif proto::env< tag0_type , char const (&)[6] , proto::env > e9 = (proto::data = 1, tag0 = "hello"); BOOST_CHECK_EQUAL(e9[proto::data], 1); BOOST_CHECK_EQUAL(0, std::strcmp(e9[tag0], "hello")); proto::env< tag0_type , int , proto::env< tag0_type , char const (&)[6] , proto::env > > e10 = (proto::data = 1, tag0 = "hello", tag0 = 42); BOOST_CHECK_EQUAL(e10[proto::data], 1); BOOST_CHECK_EQUAL(e10[tag0], 42); proto::env< tag0_type , char const (&)[6] , proto::env > e11 = (a, tag0 = "hello"); BOOST_CHECK_EQUAL(&e11[proto::data], &a); BOOST_CHECK_EQUAL(0, std::strcmp(e11[tag0], "hello")); proto::env< tag0_type , int , proto::env< tag0_type , char const (&)[6] , proto::env > > e12 = (a, tag0 = "hello", tag0 = 42); BOOST_CHECK_EQUAL(&e12[proto::data], &a); BOOST_CHECK_EQUAL(e12[tag0], 42); proto::env e13 = (proto::empty_env(), tag0 = 42); BOOST_CHECK_EQUAL(e13[tag0], 42); assert_has_env_var(e13); assert_has_env_var_not(e13); proto::empty_env empty; proto::env e14 = (boost::ref(empty), tag0 = 42); BOOST_CHECK_EQUAL(e14[tag0], 42); proto::env< proto::data_type , char const (&)[6] , proto::env > e15 = (boost::ref(e14), proto::data = "hello"); BOOST_CHECK_EQUAL(e15[tag0], 42); BOOST_CHECK_EQUAL(0, std::strcmp(e15[proto::data], "hello")); proto::env< proto::data_type , char const (&)[6] , proto::env > e16 = (proto::as_env(boost::ref(e14)), proto::data = "hello"); BOOST_CHECK_EQUAL(e16[tag0], 42); BOOST_CHECK_EQUAL(0, std::strcmp(e16[proto::data], "hello")); } void test_result_of_env_var() { typedef proto::empty_env env0_type; BOOST_MPL_ASSERT((boost::is_same::type, proto::key_not_found>)); BOOST_MPL_ASSERT((boost::is_same::type, proto::key_not_found>)); BOOST_MPL_ASSERT((boost::is_same::type, proto::key_not_found>)); typedef proto::env env1_type; BOOST_MPL_ASSERT((boost::is_same::type, int>)); BOOST_MPL_ASSERT((boost::is_same::type, int>)); BOOST_MPL_ASSERT((boost::is_same::type, int>)); typedef proto::env env2_type; BOOST_MPL_ASSERT((boost::is_same::type, int &>)); BOOST_MPL_ASSERT((boost::is_same::type, int &>)); BOOST_MPL_ASSERT((boost::is_same::type, int &>)); typedef proto::env > env3_type; BOOST_MPL_ASSERT((boost::is_same::type, double>)); BOOST_MPL_ASSERT((boost::is_same::type, abstract &>)); BOOST_MPL_ASSERT((boost::is_same::type, double>)); BOOST_MPL_ASSERT((boost::is_same::type, abstract &>)); BOOST_MPL_ASSERT((boost::is_same::type, double>)); BOOST_MPL_ASSERT((boost::is_same::type, abstract &>)); typedef proto::env > env4_type; BOOST_MPL_ASSERT((boost::is_same::type, double>)); BOOST_MPL_ASSERT((boost::is_same::type, double>)); BOOST_MPL_ASSERT((boost::is_same::type, double>)); } void test_env_var() { proto::key_not_found x0 = proto::env_var(proto::empty_env()); proto::key_not_found x1 = proto::env_var(tag0 = 42); int x2 = proto::env_var(tag0 = 42); BOOST_CHECK_EQUAL(x2, 42); int x3 = proto::functional::env_var()(tag0 = 42); BOOST_CHECK_EQUAL(x3, 42); int i = 43; int & x4 = proto::env_var(tag0 = boost::ref(i)); BOOST_CHECK_EQUAL(&x4, &i); int & x5 = proto::functional::env_var()(tag0 = boost::ref(i)); BOOST_CHECK_EQUAL(&x5, &i); concrete c; abstract &a = c; abstract &x6 = proto::env_var(tag0 = a); BOOST_CHECK_EQUAL(&x6, &a); abstract &x7 = proto::functional::env_var()(tag0 = a); BOOST_CHECK_EQUAL(&x7, &a); abstract &x8 = proto::env_var((42, tag0 = a)); BOOST_CHECK_EQUAL(&x8, &a); abstract &x9 = proto::functional::env_var()((42, tag0 = a)); BOOST_CHECK_EQUAL(&x9, &a); } void test_env_var_tfx() { typedef proto::terminal::type int_; int_ i = {42}; // tests for _env BOOST_MPL_ASSERT((boost::is_same::type, proto::empty_env>)); BOOST_MPL_ASSERT((boost::is_same::type, proto::empty_env>)); BOOST_MPL_ASSERT((boost::is_same::type, float &>)); // Bummer, is there any way around this? #ifdef BOOST_RESULT_OF_USE_DECLTYPE BOOST_MPL_ASSERT((boost::is_same::type, float const &>)); BOOST_MPL_ASSERT((boost::is_same::type, float>)); #else BOOST_MPL_ASSERT((boost::is_same::type, float>)); BOOST_MPL_ASSERT((boost::is_same::type, float>)); #endif double d = 3.14; double & rd = proto::_env()(i, 0, d); BOOST_CHECK_EQUAL(&d, &rd); proto::env e0 = proto::_env()(i, 0, proto::as_env(42)); BOOST_CHECK_EQUAL(e0[proto::data], 42); proto::env e1 = proto::_env()(i, 0, proto::functional::as_env()(42)); BOOST_CHECK_EQUAL(e1[proto::data], 42); proto::env e2 = proto::_env()(i, 0, (proto::data = 42)); BOOST_CHECK_EQUAL(e2[proto::data], 42); proto::env > e3 = proto::_env()(i, 0, (42, proto::data = 43)); BOOST_CHECK_EQUAL(e3[proto::data], 43); } using namespace boost::unit_test; /////////////////////////////////////////////////////////////////////////////// // init_unit_test_suite // test_suite* init_unit_test_suite( int argc, char* argv[] ) { test_suite *test = BOOST_TEST_SUITE("test for environment variables"); test->add(BOOST_TEST_CASE(&test_as_env)); test->add(BOOST_TEST_CASE(&test_comma)); test->add(BOOST_TEST_CASE(&test_result_of_env_var)); test->add(BOOST_TEST_CASE(&test_env_var)); test->add(BOOST_TEST_CASE(&test_env_var_tfx)); return test; }