Author: brane Date: Fri Dec 28 09:33:29 2018 New Revision: 1849831 URL: http://svn.apache.org/viewvc?rev=1849831&view=rev Log: Add SVN++ encapsulation of svn_revnum_t and svn_opt_revision_t.
[in subversion/bindings/cxx] * include/svnxx/revision.hpp: New. * src/private/revision-private.hpp: New. * src/private.hpp: Include revision-private.hpp. * src/revision.cpp: New. * tests/test_revision.cpp: New. Added: subversion/trunk/subversion/bindings/cxx/include/svnxx/revision.hpp (with props) subversion/trunk/subversion/bindings/cxx/src/private/revision-private.hpp (with props) subversion/trunk/subversion/bindings/cxx/src/revision.cpp (with props) subversion/trunk/subversion/bindings/cxx/tests/test_revision.cpp (with props) Modified: subversion/trunk/subversion/bindings/cxx/src/private.hpp Added: subversion/trunk/subversion/bindings/cxx/include/svnxx/revision.hpp URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/cxx/include/svnxx/revision.hpp?rev=1849831&view=auto ============================================================================== --- subversion/trunk/subversion/bindings/cxx/include/svnxx/revision.hpp (added) +++ subversion/trunk/subversion/bindings/cxx/include/svnxx/revision.hpp Fri Dec 28 09:33:29 2018 @@ -0,0 +1,369 @@ +/** + * @copyright + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * @endcopyright + */ + +#ifndef SVNXX_REVISION_HPP +#define SVNXX_REVISION_HPP + +#include <chrono> +#include <cstdint> + +#include "tristate.hpp" + +namespace apache { +namespace subversion { +namespace svnxx { + +/** + * @brief A revision, see @ref svn_opt_revision_t. + * + * The @c revision can represent a revision number, a point in time + * in the repository or a property of the working copy or repository + * node (see revision::kind). + */ +class revision +{ +public: + /** + * @brief Revisiion number type. + */ + enum class number : long + { + invalid = -1, //< Invalid revision number. + }; + + /** + * @brief Revision by date/time uses the system clock. + */ + template<typename Duration> + using time = std::chrono::time_point<std::chrono::system_clock, Duration>; + + /** + * @brief The resolution of the stored date/time. + */ + using usec = std::chrono::microseconds; + + /** + * @brief Revision kind discriminator (see @ref svn_opt_revision_kind). + */ + // NOTE: Keep these values identical to those in svn_opt_revision_kind! + enum class kind : std::int8_t + { + unspecified, + number, + date, + committed, + previous, + base, + working, + head, + }; + + /** + * @brief Default constructor. + * @post get_kind() == kind::unspecified. + */ + revision() noexcept + : tag(kind::unspecified) + {} + + /** + * @brief Construct a revision of the given kind. + * @pre The @a revkind argument may be any @c kind value @b except + * kind::number or kind::date, which require additional + * parameters and therefore have their own constructors. + * @post get_kind() == @a revkind. + * @throw std::invalid_argument if the @a revkind value + * precondition is not met. + */ + explicit revision(kind revkind) + : tag(revkind) + { + if (revkind == kind::number || revkind == kind::date) + throw std::invalid_argument("invalid svn::revision::kind"); + } + + /** + * @brief Construct a numbered revision. + * @post get_kind() == kind::number. + */ + explicit revision(number revnum_) noexcept + : tag(kind::number), + revnum(revnum_) + {} + + /** + * @brief Construct a dated revision from a system clock time point. + * @post get_kind() == kind::date. + */ + template<typename D> + explicit revision(time<D> time_) noexcept + : tag(kind::date), + date(std::chrono::time_point_cast<usec>(time_)) + {} + + /** + * @brief Return the revision kind. + */ + kind get_kind() const noexcept + { + return tag; + } + + /** + * @brief Return the revision number. + * @pre get_kind() == kind::number. + * @throw std::logic_error if the precondition is not met. + */ + number get_number() const + { + if (tag != kind::number) + throw std::logic_error("svn::revision kind != number"); + return revnum; + } + + /** + * @brief Return the revision date/time as a system clock time point. + * @pre get_kind() == kind::date. + * @throw std::logic_error if the precondition is not met. + */ + template<typename D> + time<D> get_date() const + { + if (tag != kind::date) + throw std::logic_error("svn::revision kind != date"); + return std::chrono::time_point_cast<D>(date); + } + +private: + // Even if we were using C++17, we wouldn't use std::variant because we + // already maintain an explicit discriminator tag for the union. + kind tag; // Union discriminator + union { + number revnum; // (tag == kind::number): revision number. + time<usec> date; // (tag == kind::date): microseconds from epoch. + }; +}; + +/** + * @related revision + * @brief revision::number alias for convenience. + */ +using revnum = revision::number; + +/** + * @related revision + * @brief Equality comparison. + */ +inline bool operator==(const revision& a, const revision& b) +{ + const auto kind = a.get_kind(); + if (kind != b.get_kind()) + return false; + else if (kind == revision::kind::number) + return a.get_number() == b.get_number(); + else if (kind == revision::kind::date) + return a.get_date<revision::usec>() == b.get_date<revision::usec>(); + else + return true; +} + +/** + * @related revision + * @brief Inequality comparison. + */ +inline bool operator!=(const revision& a, const revision& b) +{ + return !(a == b); +} + +/** + * @related revision + * @brief Ordering: less-than (<tt>operator @<</tt>). + * @returns a @c tristate result of comparing two @c revision values, + * according to the following table: + * <table border=1> + * <tr> + * <th><center><code>@<</code></center></th> + * <th><center><tt>number</tt></center></th> + * <th><center><tt>date</tt></center></th> + * <th><center><em>other</em></center></th> + * </tr> + * <tr> + * <th><center><tt>number</tt></center></th> + * <td><center><tt>a.get_number() < b.get_number()</tt></td> + * <td><center><em>unknown</em></center></td> + * <td><center><em>unknown</em></center></td> + * </tr> + * <tr> + * <th><center><tt>date</tt></center></th> + * <td><center><em>unknown</em></center></td> + * <td><center><tt>a.get_date() < b.get_date()</tt></td> + * <td><center><em>unknown</em></center></td> + * </tr> + * <tr> + * <th><center><em>other</em></center></th> + * <td><center><em>unknown</em></center></td> + * <td><center><em>unknown</em></center></td> + * <td><center><em>unknown</em></center></td> + * </tr> + * </table> + */ +inline tristate operator<(const revision& a, const revision& b) +{ + const auto kind = a.get_kind(); + if (kind != b.get_kind()) + return tristate::unknown(); + else if (kind == revision::kind::number) + return a.get_number() < b.get_number(); + else if (kind == revision::kind::date) + return a.get_date<revision::usec>() < b.get_date<revision::usec>(); + else + return tristate::unknown(); +} + +/** + * @related revision + * @brief Ordering: greater-than (<tt>operator @></tt>). + * @returns a @c tristate result of comparing two @c revision values, + * according to the following table: + * <table border=1> + * <tr> + * <th><center><code>@></code></center></th> + * <th><center><tt>number</tt></center></th> + * <th><center><tt>date</tt></center></th> + * <th><center><em>other</em></center></th> + * </tr> + * <tr> + * <th><center><tt>number</tt></center></th> + * <td><center><tt>a.get_number() > b.get_number()</tt></td> + * <td><center><em>unknown</em></center></td> + * <td><center><em>unknown</em></center></td> + * </tr> + * <tr> + * <th><center><tt>date</tt></center></th> + * <td><center><em>unknown</em></center></td> + * <td><center><tt>a.get_date() > b.get_date()</tt></td> + * <td><center><em>unknown</em></center></td> + * </tr> + * <tr> + * <th><center><em>other</em></center></th> + * <td><center><em>unknown</em></center></td> + * <td><center><em>unknown</em></center></td> + * <td><center><em>unknown</em></center></td> + * </tr> + * </table> + */ +inline tristate operator>(const revision& a, const revision& b) +{ + const auto kind = a.get_kind(); + if (kind != b.get_kind()) + return tristate::unknown(); + else if (kind == revision::kind::number) + return a.get_number() > b.get_number(); + else if (kind == revision::kind::date) + return a.get_date<revision::usec>() > b.get_date<revision::usec>(); + else + return tristate::unknown(); +} + +/** + * @related revision + * @brief Ordering: less-or-equal (<tt>operator @<=</tt>). + * @returns a @c tristate result of comparing two @c revision values, + * according to the following table: + * <table border=1> + * <tr> + * <th><center><code>@<=</code></center></th> + * <th><center><tt>number</tt></center></th> + * <th><center><tt>date</tt></center></th> + * <th><center><em>other</em></center></th> + * </tr> + * <tr> + * <th><center><tt>number</tt></center></th> + * <td><center><tt>a.get_number() <= b.get_number()</tt></td> + * <td><center><em>unknown</em></center></td> + * <td><center><em>unknown</em></center></td> + * </tr> + * <tr> + * <th><center><tt>date</tt></center></th> + * <td><center><em>unknown</em></center></td> + * <td><center><tt>a.get_date() <= b.get_date()</tt></td> + * <td><center><em>unknown</em></center></td> + * </tr> + * <tr> + * <th><center><em>other</em></center></th> + * <td><center><em>unknown</em></center></td> + * <td><center><em>unknown</em></center></td> + * <td><center><em>true</em>† or <em>unknown</em></center></td> + * </tr> + * </table> + * † <em>true</em> when <tt>a.get_kind() == b.get_kind()</tt>. + */ +inline tristate operator<=(const revision& a, const revision& b) +{ + return (a == b || !(a > b)); +} + +/** + * @related revision + * @brief Ordering: greater-or-equal (<tt>operator @>=</tt>). + * @returns a @c tristate result of comparing two @c revision values, + * according to the following table: + * <table border=1> + * <tr> + * <th><center><code>@>=</code></center></th> + * <th><center><tt>number</tt></center></th> + * <th><center><tt>date</tt></center></th> + * <th><center><em>other</em></center></th> + * </tr> + * <tr> + * <th><center><tt>number</tt></center></th> + * <td><center><tt>a.get_number() >= b.get_number()</tt></td> + * <td><center><em>unknown</em></center></td> + * <td><center><em>unknown</em></center></td> + * </tr> + * <tr> + * <th><center><tt>date</tt></center></th> + * <td><center><em>unknown</em></center></td> + * <td><center><tt>a.get_date() >= b.get_date()</tt></td> + * <td><center><em>unknown</em></center></td> + * </tr> + * <tr> + * <th><center><em>other</em></center></th> + * <td><center><em>unknown</em></center></td> + * <td><center><em>unknown</em></center></td> + * <td><center><em>true</em>† or <em>unknown</em></center></td> + * </tr> + * </table> + * † <em>true</em> when <tt>a.get_kind() == b.get_kind()</tt>. + */ +inline tristate operator>=(const revision& a, const revision& b) +{ + return (a == b || !(a < b)); +} + +} // namespace svnxx +} // namespace subversion +} // namespace apache + +#endif // SVNXX_REVISION_HPP Propchange: subversion/trunk/subversion/bindings/cxx/include/svnxx/revision.hpp ------------------------------------------------------------------------------ svn:eol-style = native Modified: subversion/trunk/subversion/bindings/cxx/src/private.hpp URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/cxx/src/private.hpp?rev=1849831&r1=1849830&r2=1849831&view=diff ============================================================================== --- subversion/trunk/subversion/bindings/cxx/src/private.hpp (original) +++ subversion/trunk/subversion/bindings/cxx/src/private.hpp Fri Dec 28 09:33:29 2018 @@ -26,6 +26,7 @@ #include "private/depth-private.hpp" #include "private/exception-private.hpp" +#include "private/revision-private.hpp" #include "private/strings-private.hpp" #include "private/tristate-private.hpp" Added: subversion/trunk/subversion/bindings/cxx/src/private/revision-private.hpp URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/cxx/src/private/revision-private.hpp?rev=1849831&view=auto ============================================================================== --- subversion/trunk/subversion/bindings/cxx/src/private/revision-private.hpp (added) +++ subversion/trunk/subversion/bindings/cxx/src/private/revision-private.hpp Fri Dec 28 09:33:29 2018 @@ -0,0 +1,62 @@ +/** + * @copyright + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * @endcopyright + */ + +#ifndef SVNXX_PRIVATE_REVISION_HPP +#define SVNXX_PRIVATE_REVISION_HPP + +#include "svnxx/revision.hpp" + +#include "svn_types.h" +#include "svn_opt.h" + +namespace apache { +namespace subversion { +namespace svnxx { +namespace detail { + +/** + * Convert @a kind to an svn_opt_revision_kind. + */ +svn_opt_revision_kind convert(revision::kind kind); + +/** + * Convert @a kind to an svn::revision::kind. + */ +revision::kind convert(svn_opt_revision_kind kind); + +/** + * Convert @a rev to an svn_opt_revision_t. + */ +svn_opt_revision_t convert(const revision& rev); + +/** + * Convert @a rev to an svn::revision. + */ +revision convert(const svn_opt_revision_t& rev); + +} // namespace detail +} // namespace svnxx +} // namespace subversion +} // namespace apache + +#endif // SVNXX_PRIVATE_REVISION_HPP Propchange: subversion/trunk/subversion/bindings/cxx/src/private/revision-private.hpp ------------------------------------------------------------------------------ svn:eol-style = native Added: subversion/trunk/subversion/bindings/cxx/src/revision.cpp URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/cxx/src/revision.cpp?rev=1849831&view=auto ============================================================================== --- subversion/trunk/subversion/bindings/cxx/src/revision.cpp (added) +++ subversion/trunk/subversion/bindings/cxx/src/revision.cpp Fri Dec 28 09:33:29 2018 @@ -0,0 +1,165 @@ +/** + * @copyright + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * @endcopyright + */ + +#include <stdexcept> + +#include "private/revision-private.hpp" + +namespace apache { +namespace subversion { +namespace svnxx { +namespace detail { + +svn_opt_revision_kind convert(revision::kind kind) +{ +#ifdef SVN_DEBUG + switch (kind) + { + case revision::kind::unspecified: + if (kind != svn_opt_revision_unspecified) + throw std::range_error("convert svn::revision::kind::unspecified"); + break; + + case revision::kind::number: + if (kind != svn_opt_revision_number) + throw std::range_error("convert svn::revision::kind::number"); + break; + + case revision::kind::date: + if (kind != svn_opt_revision_date) + throw std::range_error("convert svn::revision::kind::date"); + break; + + case revision::kind::committed: + if (kind != svn_opt_revision_committed) + throw std::range_error("convert svn::revision::kind::committed"); + break; + + case revision::kind::base: + if (kind != svn_opt_revision_base) + throw std::range_error("convert svn::revision::kind::base"); + break; + + case revision::kind::working: + if (kind != svn_opt_revision_working) + throw std::range_error("convert svn::revision::kind::working"); + break; + + case revision::kind::head: + if (kind != svn_opt_revision_head) + throw std::range_error("convert svn::revision::kind::head"); + break; + + default: + throw std::range_error("unknown svn::revision::kind"); + } +#endif + return svn_opt_revision_kind(kind); +} + +revision::kind convert(svn_opt_revision_kind kind) +{ +#ifdef SVN_DEBUG + switch (kind) + { + case svn_opt_revision_unspecified: + if (kind != revision::kind::unspecified) + throw std::range_error("convert svn_opt_revision_unspecified"); + break; + + case svn_opt_revision_number: + if (kind != revision::kind::number) + throw std::range_error("convert svn_opt_revision_number"); + break; + + case svn_opt_revision_date: + if (kind != revision::kind::date) + throw std::range_error("convert svn_opt_revision_date"); + break; + + case svn_opt_revision_committed: + if (kind != revision::kind::committed) + throw std::range_error("convert svn_opt_revision_committed"); + break; + + case svn_opt_revision_base: + if (kind != revision::kind::base) + throw std::range_error("convert svn_opt_revision_base"); + break; + + case svn_opt_revision_working: + if (kind != revision::kind::working) + throw std::range_error("convert svn_opt_revision_working"); + break; + + case svn_opt_revision_head: + if (kind != revision::kind::head) + throw std::range_error("convert svn_opt_revision_head"); + break; + + default: + throw std::range_error("unknown svn_opt_revision_kind"); + } +#endif + return revision::kind(kind); +} + +svn_opt_revision_t convert(const revision& rev) +{ + svn_opt_revision_t result; + result.kind = convert(rev.get_kind()); + if (result.kind == svn_opt_revision_number) + result.value.number = svn_revnum_t(rev.get_number()); + else if (result.kind == svn_opt_revision_date) + { + // NOTE: We're assuming that the APR and C++ system_clock epochs + // are the same. This will be standardized in C++20. + using usec = revision::usec; + const auto usecs = (rev.get_date<usec>() - revision::time<usec>()); + result.value.date = usecs.count(); + } + return result; +} + +revision convert(const svn_opt_revision_t& rev) +{ + switch (rev.kind) + { + case svn_opt_revision_number: + return revision(revision::number(rev.value.number)); + case svn_opt_revision_date: + { + // NOTE: We're assuming that the APR and C++ system_clock epochs + // are the same. This will be standardized in C++20. + using usec = revision::usec; + return revision(revision::time<usec>(usec{rev.value.date})); + } + default: + return revision(convert(rev.kind)); + } +} + +} // namespace detail +} // namespace svnxx +} // namespace subversion +} // namespace apache Propchange: subversion/trunk/subversion/bindings/cxx/src/revision.cpp ------------------------------------------------------------------------------ svn:eol-style = native Added: subversion/trunk/subversion/bindings/cxx/tests/test_revision.cpp URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/cxx/tests/test_revision.cpp?rev=1849831&view=auto ============================================================================== --- subversion/trunk/subversion/bindings/cxx/tests/test_revision.cpp (added) +++ subversion/trunk/subversion/bindings/cxx/tests/test_revision.cpp Fri Dec 28 09:33:29 2018 @@ -0,0 +1,137 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + */ + +#include <boost/test/unit_test.hpp> + +#include <array> + +#include "../src/private/revision-private.hpp" + +namespace svn = ::apache::subversion::svnxx; +namespace detail = ::apache::subversion::svnxx::detail; + +BOOST_AUTO_TEST_SUITE(revision); + +BOOST_AUTO_TEST_CASE(convert_to_kind) +{ + using kind = svn::revision::kind; + BOOST_TEST((detail::convert(kind::unspecified) == svn_opt_revision_unspecified)); + BOOST_TEST((detail::convert(kind::number) == svn_opt_revision_number)); + BOOST_TEST((detail::convert(kind::date) == svn_opt_revision_date)); + BOOST_TEST((detail::convert(kind::committed) == svn_opt_revision_committed)); + BOOST_TEST((detail::convert(kind::previous) == svn_opt_revision_previous)); + BOOST_TEST((detail::convert(kind::base) == svn_opt_revision_base)); + BOOST_TEST((detail::convert(kind::working) == svn_opt_revision_working)); + BOOST_TEST((detail::convert(kind::head) == svn_opt_revision_head)); +} + +BOOST_AUTO_TEST_CASE(convert_from_kind) +{ + using kind = svn::revision::kind; + BOOST_TEST((detail::convert(svn_opt_revision_unspecified) == kind::unspecified)); + BOOST_TEST((detail::convert(svn_opt_revision_number) == kind::number)); + BOOST_TEST((detail::convert(svn_opt_revision_date) == kind::date)); + BOOST_TEST((detail::convert(svn_opt_revision_committed) == kind::committed)); + BOOST_TEST((detail::convert(svn_opt_revision_previous) == kind::previous)); + BOOST_TEST((detail::convert(svn_opt_revision_base) == kind::base)); + BOOST_TEST((detail::convert(svn_opt_revision_working) == kind::working)); + BOOST_TEST((detail::convert(svn_opt_revision_head) == kind::head)); +} + +BOOST_AUTO_TEST_CASE(roundtrip_conversions) +{ + using kind = svn::revision::kind; + using usec = svn::revision::usec; + + std::array<svn::revision, 11> data = { + svn::revision(), + svn::revision(kind::unspecified), + svn::revision(kind::committed), + svn::revision(kind::previous), + svn::revision(kind::base), + svn::revision(kind::working), + svn::revision(kind::head), + svn::revision(svn::revnum::invalid), + svn::revision(svn::revnum(7)), + svn::revision(svn::revision::time<usec>()), + svn::revision(svn::revision::time<usec>(usec{11})), + }; + + for (const auto& r : data) + BOOST_TEST((detail::convert(detail::convert(r)) == r)); +} + +BOOST_AUTO_TEST_CASE(preconditions) +{ + using kind = svn::revision::kind; + BOOST_CHECK_THROW(auto r = svn::revision(kind::number), std::invalid_argument); + BOOST_CHECK_THROW(auto r = svn::revision(kind::date), std::invalid_argument); +} + +BOOST_AUTO_TEST_CASE(postconditions_kind) +{ + using kind = svn::revision::kind; + using usec = svn::revision::usec; + + BOOST_TEST((svn::revision(kind::unspecified).get_kind() == kind::unspecified)); + BOOST_TEST((svn::revision(kind::committed) .get_kind() == kind::committed)); + BOOST_TEST((svn::revision(kind::previous) .get_kind() == kind::previous)); + BOOST_TEST((svn::revision(kind::base) .get_kind() == kind::base)); + BOOST_TEST((svn::revision(kind::working) .get_kind() == kind::working)); + BOOST_TEST((svn::revision(kind::head) .get_kind() == kind::head)); +} + +BOOST_AUTO_TEST_CASE(postconditions_default) +{ + using kind = svn::revision::kind; + using usec = svn::revision::usec; + + const auto r = svn::revision(); + BOOST_TEST((r.get_kind() == kind::unspecified)); + BOOST_CHECK_THROW(r.get_number(), std::logic_error); + BOOST_CHECK_THROW(r.get_date<usec>(), std::logic_error); +} + +BOOST_AUTO_TEST_CASE(postconditions_number) +{ + using kind = svn::revision::kind; + using usec = svn::revision::usec; + + const auto r = svn::revision(svn::revnum::invalid); + BOOST_TEST((r.get_kind() == kind::number)); + BOOST_TEST((r.get_number() == svn::revnum::invalid)); + BOOST_CHECK_THROW(r.get_date<usec>(), std::logic_error); +} + +BOOST_AUTO_TEST_CASE(postconditions_date) +{ + using kind = svn::revision::kind; + using usec = svn::revision::usec; + + const auto r = svn::revision(svn::revision::time<usec>()); + BOOST_TEST((r.get_kind() == kind::date)); + BOOST_TEST((r.get_date<usec>() == svn::revision::time<usec>())); + BOOST_CHECK_THROW(r.get_number(), std::logic_error); +} + +// TODO: Add tests for !=, <, >, <= and >= + +BOOST_AUTO_TEST_SUITE_END(); Propchange: subversion/trunk/subversion/bindings/cxx/tests/test_revision.cpp ------------------------------------------------------------------------------ svn:eol-style = native