diff --git a/test/date_test/day.pass.cpp b/test/date_test/day.pass.cpp new file mode 100644 index 0000000..37c7376 --- /dev/null +++ b/test/date_test/day.pass.cpp @@ -0,0 +1,125 @@ +// Howard Hinnant +// This work is licensed under a Creative Commons Attribution 4.0 International License. +// http://creativecommons.org/licenses/by/4.0/ + +// class day +// { +// unsigned char d_; +// public: +// explicit constexpr day(unsigned d) noexcept; +// +// day& operator++() noexcept; +// day operator++(int) noexcept; +// day& operator--() noexcept; +// day operator--(int) noexcept; +// +// day& operator+=(const days& d) noexcept; +// day& operator-=(const days& d) noexcept; +// +// constexpr explicit operator unsigned() const noexcept; +// constexpr bool ok() const noexcept; +// }; +// +// constexpr bool operator==(const day& x, const day& y) noexcept; +// constexpr bool operator!=(const day& x, const day& y) noexcept; +// constexpr bool operator< (const day& x, const day& y) noexcept; +// constexpr bool operator> (const day& x, const day& y) noexcept; +// constexpr bool operator<=(const day& x, const day& y) noexcept; +// constexpr bool operator>=(const day& x, const day& y) noexcept; +// +// constexpr day operator+(const day& x, const days& y) noexcept; +// constexpr day operator+(const days& x, const day& y) noexcept; +// constexpr day operator-(const day& x, const days& y) noexcept; +// constexpr days operator-(const day& x, const day& y) noexcept; +// +// constexpr day operator "" _d(unsigned long long d) noexcept; +// std::ostream& operator<<(std::ostream& os, const day& d); + +#include "date.h" + +#include +#include +#include + +static_assert( std::is_trivially_destructible{}, ""); +static_assert(!std::is_default_constructible{}, ""); +static_assert( std::is_trivially_copy_constructible{}, ""); +static_assert( std::is_trivially_copy_assignable{}, ""); +static_assert( std::is_trivially_move_constructible{}, ""); +static_assert( std::is_trivially_move_assignable{}, ""); + +static_assert( std::is_nothrow_constructible{}, ""); +static_assert( std::is_nothrow_constructible{}, ""); +static_assert(!std::is_convertible{}, ""); +static_assert(!std::is_convertible{}, ""); +static_assert(static_cast(date::day{1}) == 1, ""); + +static_assert(!date::day{0}.ok(), ""); +static_assert( date::day{1}.ok(), ""); +static_assert( date::day{2}.ok(), ""); +static_assert( date::day{3}.ok(), ""); +static_assert( date::day{29}.ok(), ""); +static_assert( date::day{30}.ok(), ""); +static_assert( date::day{31}.ok(), ""); +static_assert(!date::day{32}.ok(), ""); + +int +main() +{ + using namespace date; + static_assert(std::is_same{}, ""); + + static_assert(1_d == date::day{1}, ""); + static_assert(2_d == date::day{2}, ""); + + static_assert( 1_d == 1_d, ""); + static_assert(!(1_d == 2_d), ""); + static_assert(!(2_d == 1_d), ""); + + static_assert(!(1_d != 1_d), ""); + static_assert( 1_d != 2_d, ""); + static_assert( 2_d != 1_d, ""); + + static_assert(!(1_d < 1_d), ""); + static_assert( 1_d < 2_d, ""); + static_assert(!(2_d < 1_d), ""); + + static_assert( 1_d <= 1_d, ""); + static_assert( 1_d <= 2_d, ""); + static_assert(!(2_d <= 1_d), ""); + + static_assert(!(1_d > 1_d), ""); + static_assert(!(1_d > 2_d), ""); + static_assert( 2_d > 1_d, ""); + + static_assert( 1_d >= 1_d, ""); + static_assert(!(1_d >= 2_d), ""); + static_assert( 2_d >= 1_d, ""); + + static_assert(3_d + days{7} == 10_d, ""); + static_assert(days{7} + 3_d == 10_d, ""); + static_assert(3_d + weeks{1} == 10_d, ""); + static_assert(weeks{1} + 3_d == 10_d, ""); + + static_assert(7_d - days{3} == 4_d, ""); + static_assert(3_d - 7_d == days{-4}, ""); + static_assert(25_d - 11_d == weeks{2}, ""); + + auto d = 1_d; + assert(++d == 2_d); + assert(d++ == 2_d); + assert(d == 3_d); + assert(d-- == 3_d); + assert(d == 2_d); + assert(--d == 1_d); + assert((d += days{2}) == 3_d); + assert((d -= days{2}) == 1_d); + + std::ostringstream os; + os << d; + assert(os.str() == "01"); + d += days{11}; + os.str(""); + os << d; + assert(os.str() == "12"); +} diff --git a/test/date_test/daypday.fail.cpp b/test/date_test/daypday.fail.cpp new file mode 100644 index 0000000..e330181 --- /dev/null +++ b/test/date_test/daypday.fail.cpp @@ -0,0 +1,14 @@ +// Howard Hinnant +// This work is licensed under a Creative Commons Attribution 4.0 International License. +// http://creativecommons.org/licenses/by/4.0/ + +// day + day not allowed + +#include "date.h" + +int +main() +{ + using namespace date; + auto x = 3_d + 7_d; +} diff --git a/test/date_test/daysmday.fail.cpp b/test/date_test/daysmday.fail.cpp new file mode 100644 index 0000000..a3982c8 --- /dev/null +++ b/test/date_test/daysmday.fail.cpp @@ -0,0 +1,14 @@ +// Howard Hinnant +// This work is licensed under a Creative Commons Attribution 4.0 International License. +// http://creativecommons.org/licenses/by/4.0/ + +// days - day not allowed + +#include "date.h" + +int +main() +{ + using namespace date; + auto x = days{3} - 7_d; +} diff --git a/test/date_test/durations.pass.cpp b/test/date_test/durations.pass.cpp new file mode 100644 index 0000000..e20cf5c --- /dev/null +++ b/test/date_test/durations.pass.cpp @@ -0,0 +1,77 @@ +// Howard Hinnant +// This work is licensed under a Creative Commons Attribution 4.0 International License. +// http://creativecommons.org/licenses/by/4.0/ + +// durations +// +// using days = std::chrono::duration +// , std::chrono::hours::period>>; +// +// using weeks = std::chrono::duration +// , days::period>>; +// +// using years = std::chrono::duration +// , days::period>>; +// +// using months = std::chrono::duration +// >>; +// +// time_point +// +// using day_point = std::chrono::time_point; + +#include "date.h" + +#include + +static_assert(date::days{1} == std::chrono::seconds{86400}, ""); +static_assert(date::days{1} == std::chrono::hours{24}, ""); +static_assert( std::is_convertible{}, ""); +static_assert( std::is_convertible{}, ""); +static_assert( std::is_convertible{}, ""); +static_assert(!std::is_convertible{}, ""); +static_assert(!std::is_convertible{}, ""); +static_assert(!std::is_convertible{}, ""); + +static_assert(date::weeks{1} == std::chrono::seconds{604800}, ""); +static_assert(date::weeks{1} == date::days{7}, ""); +static_assert( std::is_convertible{}, ""); +static_assert( std::is_convertible{}, ""); +static_assert( std::is_convertible{}, ""); +static_assert( std::is_convertible{}, ""); +static_assert(!std::is_convertible{}, ""); +static_assert(!std::is_convertible{}, ""); + +static_assert(date::months{1} == std::chrono::seconds{2629746}, ""); +static_assert(date::days{30} < date::months{1} && date::months{1} < date::days{31}, ""); +static_assert(date::weeks{4} < date::months{1} && date::months{1} < date::weeks{5}, ""); +static_assert(!std::is_convertible{}, ""); +static_assert(!std::is_convertible{}, ""); +static_assert(!std::is_convertible{}, ""); +static_assert(!std::is_convertible{}, ""); +static_assert(!std::is_convertible{}, ""); +static_assert( std::is_convertible{}, ""); +static_assert( std::is_convertible{}, ""); +static_assert( std::is_convertible{}, ""); +static_assert( std::is_convertible{}, ""); + +static_assert(date::years{1} == std::chrono::seconds{31556952}, ""); +static_assert(date::days{365} < date::years{1} && date::years{1} < date::days{366}, ""); +static_assert(date::weeks{52} < date::years{1} && date::years{1} < date::weeks{53}, ""); +static_assert(date::years{1} == date::months{12}, ""); +static_assert( std::is_convertible{}, ""); +static_assert(!std::is_convertible{}, ""); +static_assert(!std::is_convertible{}, ""); +static_assert(!std::is_convertible{}, ""); +static_assert(!std::is_convertible{}, ""); +static_assert( std::is_convertible{}, ""); +static_assert( std::is_convertible{}, ""); +static_assert( std::is_convertible{}, ""); +static_assert( std::is_convertible{}, ""); + +static_assert(std::is_same{}, ""); + +int +main() +{ +} diff --git a/test/date_test/last.pass.cpp b/test/date_test/last.pass.cpp new file mode 100644 index 0000000..fc2b1e3 --- /dev/null +++ b/test/date_test/last.pass.cpp @@ -0,0 +1,16 @@ +// Howard Hinnant +// This work is licensed under a Creative Commons Attribution 4.0 International License. +// http://creativecommons.org/licenses/by/4.0/ + +// constexpr struct last_spec {} last{}; + +#include "date.h" + +#include + +static_assert(std::is_same{}, ""); + +int +main() +{ +} diff --git a/test/date_test/month.pass.cpp b/test/date_test/month.pass.cpp new file mode 100644 index 0000000..1f1c728 --- /dev/null +++ b/test/date_test/month.pass.cpp @@ -0,0 +1,163 @@ +// Howard Hinnant +// This work is licensed under a Creative Commons Attribution 4.0 International License. +// http://creativecommons.org/licenses/by/4.0/ + +// class month +// { +// unsigned char m_; +// public: +// explicit constexpr month(unsigned m) noexcept; +// +// month& operator++() noexcept; +// month operator++(int) noexcept; +// month& operator--() noexcept; +// month operator--(int) noexcept; +// +// month& operator+=(const months& m) noexcept; +// month& operator-=(const months& m) noexcept; +// +// constexpr explicit operator unsigned() const noexcept; +// constexpr bool ok() const noexcept; +// }; +// +// constexpr bool operator==(const month& x, const month& y) noexcept; +// constexpr bool operator!=(const month& x, const month& y) noexcept; +// constexpr bool operator< (const month& x, const month& y) noexcept; +// constexpr bool operator> (const month& x, const month& y) noexcept; +// constexpr bool operator<=(const month& x, const month& y) noexcept; +// constexpr bool operator>=(const month& x, const month& y) noexcept; +// +// constexpr month operator+(const month& x, const months& y) noexcept; +// constexpr month operator+(const months& x, const month& y) noexcept; +// constexpr month operator-(const month& x, const months& y) noexcept; +// constexpr months operator-(const month& x, const month& y) noexcept; +// +// std::ostream& operator<<(std::ostream& os, const month& m); + +// constexpr month jan{1}; +// constexpr month feb{2}; +// constexpr month mar{3}; +// constexpr month apr{4}; +// constexpr month may{5}; +// constexpr month jun{6}; +// constexpr month jul{7}; +// constexpr month aug{8}; +// constexpr month sep{9}; +// constexpr month oct{10}; +// constexpr month nov{11}; +// constexpr month dec{12}; + +#include "date.h" + +#include +#include +#include + +static_assert( std::is_trivially_destructible{}, ""); +static_assert(!std::is_default_constructible{}, ""); +static_assert( std::is_trivially_copy_constructible{}, ""); +static_assert( std::is_trivially_copy_assignable{}, ""); +static_assert( std::is_trivially_move_constructible{}, ""); +static_assert( std::is_trivially_move_assignable{}, ""); + +static_assert( std::is_nothrow_constructible{}, ""); +static_assert( std::is_nothrow_constructible{}, ""); +static_assert(!std::is_convertible{}, ""); +static_assert(!std::is_convertible{}, ""); +static_assert(static_cast(date::month{1}) == 1, ""); + +static_assert(!date::month{0}.ok(), ""); +static_assert( date::month{1}.ok(), ""); +static_assert( date::month{2}.ok(), ""); +static_assert( date::month{3}.ok(), ""); +static_assert( date::month{4}.ok(), ""); +static_assert( date::month{5}.ok(), ""); +static_assert( date::month{6}.ok(), ""); +static_assert( date::month{7}.ok(), ""); +static_assert( date::month{8}.ok(), ""); +static_assert( date::month{9}.ok(), ""); +static_assert( date::month{10}.ok(), ""); +static_assert( date::month{11}.ok(), ""); +static_assert( date::month{12}.ok(), ""); +static_assert(!date::month{13}.ok(), ""); + +int +main() +{ + using namespace date; + + static_assert(jan == date::month{1}, ""); + static_assert(feb == date::month{2}, ""); + static_assert(mar == date::month{3}, ""); + static_assert(apr == date::month{4}, ""); + static_assert(may == date::month{5}, ""); + static_assert(jun == date::month{6}, ""); + static_assert(jul == date::month{7}, ""); + static_assert(aug == date::month{8}, ""); + static_assert(sep == date::month{9}, ""); + static_assert(oct == date::month{10}, ""); + static_assert(nov == date::month{11}, ""); + static_assert(dec == date::month{12}, ""); + + static_assert(!(jan != jan), ""); + static_assert( jan != feb, ""); + static_assert( feb != jan, ""); + + static_assert(!(jan < jan), ""); + static_assert( jan < feb, ""); + static_assert(!(feb < jan), ""); + + static_assert( jan <= jan, ""); + static_assert( jan <= feb, ""); + static_assert(!(feb <= jan), ""); + + static_assert(!(jan > jan), ""); + static_assert(!(jan > feb), ""); + static_assert( feb > jan, ""); + + static_assert( jan >= jan, ""); + static_assert(!(jan >= feb), ""); + static_assert( feb >= jan, ""); + + assert(mar + months{7} == oct); + assert(mar + months{27} == jun); + assert(months{7} + mar == oct); + assert(months{27} + mar == jun); + + assert(mar - months{7} == aug); + assert(mar - months{27} == dec); + + assert(mar - feb == months{1}); + assert(feb - mar == months{11}); + +#if __cplusplus >= 201402 + static_assert(mar + months{7} == oct, ""); + static_assert(mar + months{27} == jun, ""); + static_assert(months{7} + mar == oct, ""); + static_assert(months{27} + mar == jun, ""); + + static_assert(mar - months{7} == aug, ""); + static_assert(mar - months{27} == dec, ""); + + static_assert(mar - feb == months{1}, ""); + static_assert(feb - mar == months{11}, ""); +#endif + + auto m = dec; + assert(++m == jan); + assert(m++ == jan); + assert(m == feb); + assert(m-- == feb); + assert(m == jan); + assert(--m == dec); + assert((m += months{2}) == feb); + assert((m -= months{2}) == dec); + + std::ostringstream os; + os << m; + assert(os.str() == "Dec"); + m += months{11}; + os.str(""); + os << m; + assert(os.str() == "Nov"); +} diff --git a/test/date_test/monthpmonth.fail.cpp b/test/date_test/monthpmonth.fail.cpp new file mode 100644 index 0000000..e6b5560 --- /dev/null +++ b/test/date_test/monthpmonth.fail.cpp @@ -0,0 +1,14 @@ +// Howard Hinnant +// This work is licensed under a Creative Commons Attribution 4.0 International License. +// http://creativecommons.org/licenses/by/4.0/ + +// month + month not allowed + +#include "date.h" + +int +main() +{ + using namespace date; + auto x = mar + jul; +} diff --git a/test/date_test/monthsmmonth.fail.cpp b/test/date_test/monthsmmonth.fail.cpp new file mode 100644 index 0000000..964b047 --- /dev/null +++ b/test/date_test/monthsmmonth.fail.cpp @@ -0,0 +1,14 @@ +// Howard Hinnant +// This work is licensed under a Creative Commons Attribution 4.0 International License. +// http://creativecommons.org/licenses/by/4.0/ + +// months - month not allowed + +#include "date.h" + +int +main() +{ + using namespace date; + auto x = months{3} - jul; +} diff --git a/test/just.pass.cpp b/test/just.pass.cpp new file mode 100644 index 0000000..3acc30b --- /dev/null +++ b/test/just.pass.cpp @@ -0,0 +1,8 @@ +// Howard Hinnant +// This work is licensed under a Creative Commons Attribution 4.0 International License. +// http://creativecommons.org/licenses/by/4.0/ + +int +main() +{ +} diff --git a/test/testit b/test/testit new file mode 100755 index 0000000..8777470 --- /dev/null +++ b/test/testit @@ -0,0 +1,160 @@ +#!/bin/sh +# Howard Hinnant +# This work is licensed under a Creative Commons Attribution 4.0 International License. +# http://creativecommons.org/licenses/by/4.0/ + +currentpath=`pwd` +origpath=$currentpath +currentdir=`basename $currentpath` +while [ $currentdir != "test" ]; do + if [ $currentdir = "/" ] + then + echo "current directory must be in or under \"test\"." + exit 1 + fi + cd .. + currentpath=`pwd` + currentdir=`basename $currentpath` +done + +cd .. +ROOT=`pwd` +cd $origpath + +if [ -z "$CXX" ] +then + CXX=clang++ +fi + +if [ -z "$CXX_LANG" ] +then + CXX_LANG=c++14 +fi +if [ -z "$OPTIONS" ] +then + OPTIONS="-std=${CXX_LANG}" +fi +OPTIONS="$OPTIONS -I$ROOT" + +case $TRIPLE in + *-*-mingw* | *-*-cygwin* | *-*-win*) + TEST_EXE=test.exe + ;; + *) + TEST_EXE=a.out + ;; +esac + +case $(uname -s) in + NetBSD) + THREAD_FLAGS=-lpthread + ;; +esac + +FAIL=0 +PASS=0 +UNIMPLEMENTED=0 +IMPLEMENTED_FAIL=0 +IMPLEMENTED_PASS=0 + +afunc() { + fail=0 + pass=0 + if (ls ${TEST_PREFIX}*fail.cpp > /dev/null 2>&1) + then + for FILE in $(ls ${TEST_PREFIX}*fail.cpp); do + if $CXX $OPTIONS $HEADER_INCLUDE $SOURCE_LIB $FILE $LIBS -o ./$TEST_EXE > /dev/null 2>&1 + then + rm ./$TEST_EXE + echo "$FILE should not compile" + fail=$(($fail+1)) + else + pass=$(($pass+1)) + fi + done + fi + + if (ls ${TEST_PREFIX}*pass.cpp > /dev/null 2>&1) + then + for FILE in $(ls ${TEST_PREFIX}*pass.cpp); do + if [ "$VERBOSE" ] + then + echo "Running test: " $FILE + fi + if $CXX $OPTIONS $HEADER_INCLUDE $SOURCE_LIB $FILE $LIBS $(test $1 = no || echo $THREAD_FLAGS) -o ./$TEST_EXE + then + if ./$TEST_EXE + then + rm ./$TEST_EXE + pass=$(($pass+1)) + else + echo "`pwd`/$FILE failed at run time" + echo "Compile line was:" $CXX $OPTIONS $HEADER_INCLUDE $SOURCE_LIB $FILE $LIBS $(test $1 = no || echo $THREAD_FLAGS) + fail=$(($fail+1)) + rm ./$TEST_EXE + fi + else + echo "`pwd`/$FILE failed to compile" + echo "Compile line was:" $CXX $OPTIONS $HEADER_INCLUDE $SOURCE_LIB $FILE $LIBS $(test $1 = no || echo $THREAD_FLAGS) + fail=$(($fail+1)) + fi + done + fi + + if [ $fail -gt 0 ] + then + echo "failed $fail tests in `pwd`" + IMPLEMENTED_FAIL=$(($IMPLEMENTED_FAIL+1)) + fi + if [ $pass -gt 0 ] + then + echo "passed $pass tests in `pwd`" + if [ $fail -eq 0 ] + then + IMPLEMENTED_PASS=$((IMPLEMENTED_PASS+1)) + fi + fi + if [ $fail -eq 0 -a $pass -eq 0 ] + then + echo "not implemented: `pwd`" + UNIMPLEMENTED=$(($UNIMPLEMENTED+1)) + fi + + FAIL=$(($FAIL+$fail)) + PASS=$(($PASS+$pass)) + + for FILE in * + do + if [ -d "$FILE" ]; + then + cd $FILE + if [ $FILE = thread -o $1 = yes ]; then + afunc yes + else + afunc no + fi + cd .. + fi + done +} + +afunc no + +echo "****************************************************" +echo "Results for `pwd`:" +echo "using `$CXX --version`" +echo "with $OPTIONS $HEADER_INCLUDE $SOURCE_LIB" +echo "----------------------------------------------------" +echo "sections without tests : $UNIMPLEMENTED" +echo "sections with failures : $IMPLEMENTED_FAIL" +echo "sections without failures: $IMPLEMENTED_PASS" +echo " + ----" +echo "total number of sections : $(($UNIMPLEMENTED+$IMPLEMENTED_FAIL+$IMPLEMENTED_PASS))" +echo "----------------------------------------------------" +echo "number of tests failed : $FAIL" +echo "number of tests passed : $PASS" +echo " + ----" +echo "total number of tests : $(($FAIL+$PASS))" +echo "****************************************************" + +exit $FAIL