Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r70565 - in trunk/tools/quickbook: src test/unit
From: dnljms_at_[hidden]
Date: 2011-03-26 07:13:09


Author: danieljames
Date: 2011-03-26 07:13:07 EDT (Sat, 26 Mar 2011)
New Revision: 70565
URL: http://svn.boost.org/trac/boost/changeset/70565

Log:
Quickbook: Iterator tests. Equality operator for values.

The equality operator is pretty inefficient. Just for testing really.
Added:
   trunk/tools/quickbook/test/unit/iterator_tests.cpp (contents, props changed)
Text files modified:
   trunk/tools/quickbook/src/doc_info_grammar.cpp | 10
   trunk/tools/quickbook/src/values.cpp | 204 +++++++++++++++++++++++++++++++--------
   trunk/tools/quickbook/src/values.hpp | 6 +
   trunk/tools/quickbook/test/unit/Jamfile.v2 | 1
   trunk/tools/quickbook/test/unit/values_test.cpp | 29 +++++
   5 files changed, 203 insertions(+), 47 deletions(-)

Modified: trunk/tools/quickbook/src/doc_info_grammar.cpp
==============================================================================
--- trunk/tools/quickbook/src/doc_info_grammar.cpp (original)
+++ trunk/tools/quickbook/src/doc_info_grammar.cpp 2011-03-26 07:13:07 EDT (Sat, 26 Mar 2011)
@@ -248,11 +248,11 @@
                     [cl::chset<>("0-9a-fA-F")]
                                             [actions.escape_unicode]
             | ("'''" >> !eol)
- >> actions.values.save()
- [ (*(cl::anychar_p - "'''"))
- [actions.values.entry(ph::arg1, ph::arg2, phrase_tags::escape)]
- >> cl::str_p("'''") [actions.element]
- ]
+ >> actions.values.save()
+ [ (*(cl::anychar_p - "'''"))
+ [actions.values.entry(ph::arg1, ph::arg2, phrase_tags::escape)]
+ >> cl::str_p("'''") [actions.element]
+ ]
             | cl::anychar_p [actions.plain_char]
             ;
     }

Modified: trunk/tools/quickbook/src/values.cpp
==============================================================================
--- trunk/tools/quickbook/src/values.cpp (original)
+++ trunk/tools/quickbook/src/values.cpp 2011-03-26 07:13:07 EDT (Sat, 26 Mar 2011)
@@ -12,7 +12,7 @@
 #include <boost/lexical_cast.hpp>
 
 #define UNDEFINED_ERROR() \
- throw value_error( \
+ throw value_undefined_method( \
         std::string(BOOST_CURRENT_FUNCTION) +\
         " not defined for " + \
         this->type_name() + \
@@ -24,9 +24,17 @@
     ////////////////////////////////////////////////////////////////////////////
     // Value Error
     
+ struct value_undefined_method : value_error
+ {
+ value_undefined_method(std::string const&);
+ };
+
     value_error::value_error(std::string const& x)
         : std::logic_error(x) {}
-
+
+ value_undefined_method::value_undefined_method(std::string const& x)
+ : value_error(x) {}
+
     ////////////////////////////////////////////////////////////////////////////
     // Node
 
@@ -45,16 +53,50 @@
         int value_node::get_int() const { UNDEFINED_ERROR(); }
         std::string value_node::get_quickbook() const { UNDEFINED_ERROR(); }
         value_node::qbk_range value_node::get_quickbook_range() const { UNDEFINED_ERROR(); }
- std::string value_node::get_boostbook() const { UNDEFINED_ERROR(); }
- value_node* value_node::get_list() const { UNDEFINED_ERROR(); }
+ std::string value_node::get_boostbook() const { UNDEFINED_ERROR(); }
+ value_node* value_node::get_list() const { UNDEFINED_ERROR(); }
 
         bool value_node::empty() const { return false; }
         bool value_node::check() const { return true; }
         bool value_node::is_list() const { return false; }
         bool value_node::is_string() const { return false; }
+ bool value_node::equals(value_node*) const { UNDEFINED_ERROR(); }
     }
 
     ////////////////////////////////////////////////////////////////////////////
+ // List end value
+ //
+ // A special value for marking the end of lists.
+
+ namespace detail
+ {
+ struct value_list_end_impl : public value_node
+ {
+ static value_list_end_impl instance;
+ private:
+ value_list_end_impl()
+ : value_node(value::default_tag)
+ {
+ intrusive_ptr_add_ref(&instance);
+ next_ = this;
+ }
+
+ virtual char const* type_name() const { return "list end"; }
+ virtual value_node* clone() const { UNDEFINED_ERROR(); }
+
+ virtual bool equals(value_node* other) const
+ { return this == other; }
+
+ bool empty() const { UNDEFINED_ERROR(); }
+ bool check() const { UNDEFINED_ERROR(); }
+ bool is_list() const { UNDEFINED_ERROR(); }
+ bool is_string() const { UNDEFINED_ERROR(); }
+ };
+
+ value_list_end_impl value_list_end_impl::instance;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
     // Empty/nil values
     //
     // (nil is just a special case of empty, don't be mislead by the name
@@ -81,6 +123,9 @@
 
             virtual bool check() const
                 { return false; }
+
+ virtual bool equals(value_node* other) const
+ { return !other->check(); }
             
             friend value quickbook::empty_value(value::tag_type);
         };
@@ -93,9 +138,10 @@
                 : value_empty_impl(value::default_tag)
             {
                 intrusive_ptr_add_ref(&instance);
+ next_ = &value_list_end_impl::instance;
             }
         };
-
+
         value_nil_impl value_nil_impl::instance;
 
         value_node* value_empty_impl::new_(value::tag_type t) {
@@ -112,6 +158,11 @@
         }
     }
 
+ value empty_value(value::tag_type t)
+ {
+ return value(detail::value_empty_impl::new_(t));
+ }
+
     ////////////////////////////////////////////////////////////////////////////
     // value_counted
 
@@ -205,20 +256,6 @@
     }
 
     ////////////////////////////////////////////////////////////////////////////
- // Iterator
-
- namespace detail
- {
- value::iterator::iterator()
- : ptr_(&value_nil_impl::instance) {}
- }
-
- value empty_value(value::tag_type t)
- {
- return value(detail::value_empty_impl::new_(t));
- }
-
- ////////////////////////////////////////////////////////////////////////////
     // Integers
 
     namespace detail
@@ -234,7 +271,8 @@
             virtual std::string get_quickbook() const;
             virtual std::string get_boostbook() const;
             virtual bool empty() const;
-
+ virtual bool equals(value_node*) const;
+
             int value_;
         };
 
@@ -267,6 +305,15 @@
         {
             return false;
         }
+
+ bool value_int_impl::equals(value_node* other) const {
+ try {
+ return value_ == other->get_int();
+ }
+ catch(value_undefined_method&) {
+ return false;
+ }
+ }
     }
 
     value int_value(int v, value::tag_type t)
@@ -291,7 +338,8 @@
             virtual std::string get_boostbook() const;
             virtual bool is_string() const;
             virtual bool empty() const;
-
+ virtual bool equals(value_node*) const;
+
             std::string value_;
         };
     
@@ -313,6 +361,7 @@
             qbk_range get_quickbook_range() const;
             virtual bool is_string() const;
             virtual bool empty() const;
+ virtual bool equals(value_node*) const;
     
             std::string value_;
             file_position position_;
@@ -333,7 +382,8 @@
             qbk_range get_quickbook_range() const;
             virtual bool is_string() const;
             virtual bool empty() const;
-
+ virtual bool equals(value_node*) const;
+
             quickbook::iterator begin_;
             quickbook::iterator end_;
         };
@@ -359,6 +409,7 @@
             virtual std::string get_boostbook() const;
             virtual bool is_string() const;
             virtual bool empty() const;
+ virtual bool equals(value_node*) const;
 
             std::string qbk_value_;
             std::string bbk_value_;
@@ -399,6 +450,15 @@
         bool value_string_impl::empty() const
             { return value_.empty(); }
 
+ bool value_string_impl::equals(value_node* other) const {
+ try {
+ return value_ == other->get_boostbook();
+ }
+ catch(value_undefined_method&) {
+ return false;
+ }
+ }
+
         // value_qbk_string_impl
     
         value_qbk_string_impl::value_qbk_string_impl(
@@ -442,7 +502,16 @@
 
         bool value_qbk_string_impl::empty() const
             { return value_.empty(); }
-
+
+ bool value_qbk_string_impl::equals(value_node* other) const {
+ try {
+ return value_ == other->get_quickbook();
+ }
+ catch(value_undefined_method&) {
+ return false;
+ }
+ }
+
         // value_qbk_ref_impl
     
         value_qbk_ref_impl::value_qbk_ref_impl(
@@ -481,6 +550,15 @@
         bool value_qbk_ref_impl::empty() const
             { return begin_ == end_; }
     
+ bool value_qbk_ref_impl::equals(value_node* other) const {
+ try {
+ return this->get_quickbook() == other->get_quickbook();
+ }
+ catch(value_undefined_method&) {
+ return false;
+ }
+ }
+
         // value_qbk_bbk_impl
     
         value_qbk_bbk_impl::value_qbk_bbk_impl(
@@ -549,6 +627,20 @@
         // Should this test the quickbook, the boostbook or both?
         bool value_qbk_bbk_impl::empty() const
             { return bbk_value_.empty(); }
+
+ bool value_qbk_bbk_impl::equals(value_node* other) const {
+ try {
+ return this->get_quickbook() == other->get_quickbook();
+ }
+ catch(value_undefined_method&) {}
+
+ try {
+ return this->get_boostbook() == other->get_boostbook();
+ }
+ catch(value_undefined_method&) {}
+
+ return false;
+ }
     }
 
     value qbk_value(iterator x, iterator y, value::tag_type t)
@@ -594,7 +686,7 @@
 
         value_node** list_ref_back(value_node** back)
         {
- while(*back != &value_nil_impl::instance) {
+ while(*back != &value_list_end_impl::instance) {
                 intrusive_ptr_add_ref(*back);
                 back = &(*back)->next_;
             }
@@ -604,7 +696,7 @@
 
         void list_ref(value_node* ptr)
         {
- while(ptr != &value_nil_impl::instance) {
+ while(ptr != &value_list_end_impl::instance) {
                 intrusive_ptr_add_ref(ptr);
                 ptr = ptr->next_;
             }
@@ -612,7 +704,7 @@
 
         void list_unref(value_node* ptr)
         {
- while(ptr != &value_nil_impl::instance) {
+ while(ptr != &value_list_end_impl::instance) {
                 value_node* next = ptr->next_;
                 intrusive_ptr_release(ptr);
                 ptr = next;
@@ -621,7 +713,7 @@
 
         value_node** merge_sort(value_node** l)
         {
- if(*l == &value_nil_impl::instance)
+ if(*l == &value_list_end_impl::instance)
                 return l;
             else
                 return merge_sort(l, 9999);
@@ -631,7 +723,7 @@
         {
             value_node** p = &(*l)->next_;
             for(int count = 0;
- count < recurse_limit && *p != &value_nil_impl::instance;
+ count < recurse_limit && *p != &value_list_end_impl::instance;
                 ++count)
             {
                 p = merge(l, p, merge_sort(p, count));
@@ -676,7 +768,7 @@
             *first = *second;
             *second = *third;
             *third = tmp;
- //if(*second != &value_nil_impl::instance) back = second;
+ //if(*second != &value_list_end_impl::instance) back = second;
         }
     }
     }
@@ -699,19 +791,20 @@
             virtual value_node* clone() const;
             virtual value_node* store();
             virtual bool empty() const;
+ virtual bool equals(value_node*) const;
+
             virtual bool is_list() const;
-
             virtual value_node* get_list() const;
     
             value_node* head_;
         };
-
+
         value_list_impl::value_list_impl(value::tag_type tag)
- : value_node(tag), head_(&value_nil_impl::instance)
+ : value_node(tag), head_(&value_list_end_impl::instance)
         {}
     
         value_list_impl::value_list_impl(value_list_builder& builder,
- value::tag_type tag)
+ value::tag_type tag)
             : value_node(tag), head_(builder.release())
         {
         }
@@ -738,7 +831,7 @@
             boost::intrusive_ptr<value_node> new_node;
 
             for(;;) {
- if(pos == &value_nil_impl::instance)
+ if(pos == &value_list_end_impl::instance)
                     return this;
                 new_node = pos->store();
                 if(new_node.get() != pos) break;
@@ -755,16 +848,15 @@
             build.append(new_node.get());
             pos2 = pos2->next_;
 
- for(;pos2 != &value_nil_impl::instance; pos2 = pos2->next_)
+ for(;pos2 != &value_list_end_impl::instance; pos2 = pos2->next_)
                 build.append(pos2->store());
 
             return new value_list_impl(build, tag_);
         }
 
-
         bool value_list_impl::empty() const
         {
- return head_ == &value_nil_impl::instance;
+ return head_ == &value_list_end_impl::instance;
         }
     
         bool value_list_impl::is_list() const
@@ -776,6 +868,25 @@
         {
             return head_;
         }
+
+ bool value_list_impl::equals(value_node* other) const {
+ value_node* x1;
+
+ try {
+ x1 = other->get_list();
+ }
+ catch(value_undefined_method&) {
+ return false;
+ }
+
+ for(value_node *x2 = head_; x1 != x2; x1 = x1->next_, x2 = x2->next_)
+ {
+ if (x2 == &value_list_end_impl::instance ||
+ !x1->equals(x2)) return false;
+ }
+
+ return true;
+ }
     }
 
     //////////////////////////////////////////////////////////////////////////
@@ -786,7 +897,7 @@
         // value_list_builder
     
         value_list_builder::value_list_builder()
- : head_(&value_nil_impl::instance)
+ : head_(&value_list_end_impl::instance)
             , back_(&head_)
         {}
 
@@ -808,9 +919,9 @@
         }
 
         value_node* value_list_builder::release() {
- value_node* r = head_;
- head_ = &value_nil_impl::instance;
- back_ = &head_;
+ value_node* r = head_;
+ head_ = &value_list_end_impl::instance;
+ back_ = &head_;
             return r;
         }
     
@@ -826,7 +937,7 @@
         void value_list_builder::sort()
         {
             back_ = merge_sort(&head_);
- assert(*back_ == &value_nil_impl::instance);
+ assert(*back_ == &value_list_end_impl::instance);
         }
     }
 
@@ -900,4 +1011,13 @@
     {
         current.sort();
     }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Iterator
+
+ namespace detail
+ {
+ value::iterator::iterator()
+ : ptr_(&value_list_end_impl::instance) {}
+ }
 }

Modified: trunk/tools/quickbook/src/values.hpp
==============================================================================
--- trunk/tools/quickbook/src/values.hpp (original)
+++ trunk/tools/quickbook/src/values.hpp 2011-03-26 07:13:07 EDT (Sat, 26 Mar 2011)
@@ -61,6 +61,7 @@
             virtual bool empty() const;
             virtual bool is_list() const;
             virtual bool is_string() const;
+ virtual bool equals(value_node*) const;
 
             virtual value_node* get_list() const;
             
@@ -122,6 +123,11 @@
             int get_int() const
             { return value_->get_int(); }
 
+ // Equality is pretty inefficient. Not really designed for anything
+ // more than testing purposes.
+ friend bool operator==(value_base const& x, value_base const& y)
+ { return x.value_->equals(y.value_); }
+
         protected:
             value_node* value_;
 

Modified: trunk/tools/quickbook/test/unit/Jamfile.v2
==============================================================================
--- trunk/tools/quickbook/test/unit/Jamfile.v2 (original)
+++ trunk/tools/quickbook/test/unit/Jamfile.v2 2011-03-26 07:13:07 EDT (Sat, 26 Mar 2011)
@@ -6,3 +6,4 @@
 
 run values_test.cpp ../../src/values.cpp ;
 run post_process_test.cpp ../../src/post_process.cpp ;
+run iterator_tests.cpp ../../src/values.cpp ;

Added: trunk/tools/quickbook/test/unit/iterator_tests.cpp
==============================================================================
--- (empty file)
+++ trunk/tools/quickbook/test/unit/iterator_tests.cpp 2011-03-26 07:13:07 EDT (Sat, 26 Mar 2011)
@@ -0,0 +1,71 @@
+/*=============================================================================
+ Copyright (c) 2011 Daniel James
+
+ Use, modification and distribution is subject to 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)
+=============================================================================*/
+
+// Use boost's iterator concept tests for our iterators.
+
+#include "fwd.hpp"
+#include "values.hpp"
+#include <boost/iterator/new_iterator_tests.hpp>
+#include <boost/iterator/iterator_concepts.hpp>
+#include <boost/concept_check.hpp>
+
+void iterator_concept_checks()
+{
+ typedef quickbook::iterator Iter;
+ boost::function_requires< boost::ForwardIterator<Iter> >();
+ boost::function_requires< boost_concepts::ReadableIteratorConcept<Iter> >();
+ boost::function_requires< boost_concepts::LvalueIteratorConcept<Iter> >();
+ boost::function_requires< boost_concepts::ForwardTraversalConcept<Iter> >();
+}
+
+void value_iterator_concept_checks()
+{
+ typedef quickbook::value::iterator Iter;
+ boost::function_requires< boost::ForwardIterator<Iter> >();
+ boost::function_requires< boost_concepts::ReadableIteratorConcept<Iter> >();
+ boost::function_requires< boost_concepts::ForwardTraversalConcept<Iter> >();
+}
+
+void iterator_runtime_checks()
+{
+ std::string x = "Hello World";
+
+ quickbook::iterator i1(x.begin(), quickbook::file_position(10, 5));
+ quickbook::iterator i2(++x.begin(), quickbook::file_position(10, 6));
+
+ boost::forward_readable_iterator_test(i1, i2, 'H', 'e');
+ boost::constant_lvalue_iterator_test(i1, 'H');
+}
+
+void value_iterator_runtime_checks()
+{
+ quickbook::value v1 = quickbook::bbk_value("a", 10);
+ quickbook::value v2 = quickbook::int_value(25, 32);
+
+ quickbook::value_builder b;
+ b.insert(v1);
+ b.insert(v2);
+ quickbook::value x = b.release();
+
+ quickbook::value::iterator i1 = x.begin();
+ quickbook::value::iterator i2 = ++x.begin();
+
+ boost::forward_readable_iterator_test(i1, i2, v1, v2);
+}
+
+int main()
+{
+ // I know I don't have to run the concept checks.
+ // I'm a bit irrational like that.
+ iterator_concept_checks();
+ value_iterator_concept_checks();
+ iterator_runtime_checks();
+ value_iterator_runtime_checks();
+
+ return boost::report_errors();
+}

Modified: trunk/tools/quickbook/test/unit/values_test.cpp
==============================================================================
--- trunk/tools/quickbook/test/unit/values_test.cpp (original)
+++ trunk/tools/quickbook/test/unit/values_test.cpp 2011-03-26 07:13:07 EDT (Sat, 26 Mar 2011)
@@ -11,6 +11,7 @@
 
 #include <boost/detail/lightweight_test.hpp>
 #include <boost/range/algorithm/equal.hpp>
+#include <vector>
 #include "values.hpp"
 
 void empty_tests()
@@ -131,6 +132,33 @@
     store_test2_check(q);
 }
 
+void equality_tests()
+{
+ std::vector<quickbook::value> distinct_values;
+
+ quickbook::value_builder builder;
+ quickbook::value nil;
+
+ // 0: nil
+ distinct_values.push_back(nil);
+
+ // 1: []
+ distinct_values.push_back(builder.release());
+
+ // 2: [nil]
+ builder.insert(nil);
+ distinct_values.push_back(builder.release());
+
+ for(int i = 0; i < distinct_values.size(); ++i)
+ for(int j = 0; j < distinct_values.size(); ++j)
+ if ((i == j) != (distinct_values[i] == distinct_values[j]))
+ {
+ BOOST_ERROR("Value mismatch.");
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM
+ << "\tat " << i << ", " << j << std::endl;
+ }
+}
+
 int main()
 {
     empty_tests();
@@ -139,6 +167,7 @@
     multiple_list_test();
     store_test1();
     store_test2();
+ equality_tests();
 
     return boost::report_errors();
 }


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk