From 6d78c3dcd662064ca91fa5a24063416b2c7c0612 Mon Sep 17 00:00:00 2001 From: "Dr. Colin Hirsch" Date: Thu, 5 Dec 2024 19:36:42 +0100 Subject: [PATCH] Improve test coverage. --- include/tao/pegtl/contrib/alphabet_rules.hpp | 69 +++++++++ src/test/pegtl/CMakeLists.txt | 2 + src/test/pegtl/action_add_guard.cpp | 26 +++- src/test/pegtl/action_add_state.cpp | 152 +++++++++++++++++++ src/test/pegtl/action_change_control.cpp | 56 +++++++ src/test/pegtl/buffer_cstream_input.cpp | 17 +++ src/test/pegtl/buffer_istream_input.cpp | 13 ++ src/test/pegtl/internal_type_traits.cpp | 83 +++++----- 8 files changed, 369 insertions(+), 49 deletions(-) create mode 100644 include/tao/pegtl/contrib/alphabet_rules.hpp create mode 100644 src/test/pegtl/action_add_state.cpp create mode 100644 src/test/pegtl/action_change_control.cpp diff --git a/include/tao/pegtl/contrib/alphabet_rules.hpp b/include/tao/pegtl/contrib/alphabet_rules.hpp new file mode 100644 index 000000000..cd40944bd --- /dev/null +++ b/include/tao/pegtl/contrib/alphabet_rules.hpp @@ -0,0 +1,69 @@ +// Copyright (c) 2024 Dr. Colin Hirsch and Daniel Frey +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt) + +#ifndef TAO_PEGTL_CONTRIB_ALPHABET_RULES_HPP +#define TAO_PEGTL_CONTRIB_ALPHABET_RULES_HPP + +#include "../ascii.hpp" +#include "../config.hpp" + +namespace TAO_PEGTL_NAMESPACE::alphabet::rules +{ + struct a : ascii::one< 'a' > {}; + struct b : ascii::one< 'b' > {}; + struct c : ascii::one< 'c' > {}; + struct d : ascii::one< 'd' > {}; + struct e : ascii::one< 'e' > {}; + struct f : ascii::one< 'f' > {}; + struct g : ascii::one< 'g' > {}; + struct h : ascii::one< 'h' > {}; + struct i : ascii::one< 'i' > {}; + struct j : ascii::one< 'j' > {}; + struct k : ascii::one< 'k' > {}; + struct l : ascii::one< 'l' > {}; + struct m : ascii::one< 'm' > {}; + struct n : ascii::one< 'n' > {}; + struct o : ascii::one< 'o' > {}; + struct p : ascii::one< 'p' > {}; + struct q : ascii::one< 'q' > {}; + struct r : ascii::one< 'r' > {}; + struct s : ascii::one< 's' > {}; + struct t : ascii::one< 't' > {}; + struct u : ascii::one< 'u' > {}; + struct v : ascii::one< 'v' > {}; + struct w : ascii::one< 'w' > {}; + struct x : ascii::one< 'x' > {}; + struct y : ascii::one< 'y' > {}; + struct z : ascii::one< 'z' > {}; + + struct A : ascii::one< 'A' > {}; // NOLINT(readability-identifier-naming) + struct B : ascii::one< 'B' > {}; // NOLINT(readability-identifier-naming) + struct C : ascii::one< 'C' > {}; // NOLINT(readability-identifier-naming) + struct D : ascii::one< 'D' > {}; // NOLINT(readability-identifier-naming) + struct E : ascii::one< 'E' > {}; // NOLINT(readability-identifier-naming) + struct F : ascii::one< 'F' > {}; // NOLINT(readability-identifier-naming) + struct G : ascii::one< 'G' > {}; // NOLINT(readability-identifier-naming) + struct H : ascii::one< 'H' > {}; // NOLINT(readability-identifier-naming) + struct I : ascii::one< 'I' > {}; // NOLINT(readability-identifier-naming,misc-confusable-identifiers) + struct J : ascii::one< 'J' > {}; // NOLINT(readability-identifier-naming) + struct K : ascii::one< 'K' > {}; // NOLINT(readability-identifier-naming) + struct L : ascii::one< 'L' > {}; // NOLINT(readability-identifier-naming) + struct M : ascii::one< 'M' > {}; // NOLINT(readability-identifier-naming) + struct N : ascii::one< 'N' > {}; // NOLINT(readability-identifier-naming) + struct O : ascii::one< 'O' > {}; // NOLINT(readability-identifier-naming) + struct P : ascii::one< 'P' > {}; // NOLINT(readability-identifier-naming) + struct Q : ascii::one< 'Q' > {}; // NOLINT(readability-identifier-naming) + struct R : ascii::one< 'R' > {}; // NOLINT(readability-identifier-naming) + struct S : ascii::one< 'S' > {}; // NOLINT(readability-identifier-naming) + struct T : ascii::one< 'T' > {}; // NOLINT(readability-identifier-naming) + struct U : ascii::one< 'U' > {}; // NOLINT(readability-identifier-naming) + struct V : ascii::one< 'V' > {}; // NOLINT(readability-identifier-naming) + struct W : ascii::one< 'W' > {}; // NOLINT(readability-identifier-naming) + struct X : ascii::one< 'X' > {}; // NOLINT(readability-identifier-naming) + struct Y : ascii::one< 'Y' > {}; // NOLINT(readability-identifier-naming) + struct Z : ascii::one< 'Z' > {}; // NOLINT(readability-identifier-naming) + +} // namespace TAO_PEGTL_NAMESPACE::alphabet::rules + +#endif diff --git a/src/test/pegtl/CMakeLists.txt b/src/test/pegtl/CMakeLists.txt index fee4675b2..fc390852e 100644 --- a/src/test/pegtl/CMakeLists.txt +++ b/src/test/pegtl/CMakeLists.txt @@ -2,11 +2,13 @@ cmake_minimum_required(VERSION 3.8...3.19) set(test_sources action_add_guard.cpp + action_add_state.cpp action_apply_1.cpp action_apply_2.cpp action_apply_3.cpp action_change_action_and_state.cpp action_change_action_and_states.cpp + action_change_control.cpp action_change_state.cpp action_change_states.cpp action_control_action.cpp diff --git a/src/test/pegtl/action_add_guard.cpp b/src/test/pegtl/action_add_guard.cpp index 967b024f6..2c5a711da 100644 --- a/src/test/pegtl/action_add_guard.cpp +++ b/src/test/pegtl/action_add_guard.cpp @@ -9,8 +9,12 @@ namespace TAO_PEGTL_NAMESPACE { - bool ctor = false; - bool dtor = false; + namespace + { + bool ctor = false; + bool dtor = false; + + } // namespace struct test_class1 { @@ -64,12 +68,22 @@ namespace TAO_PEGTL_NAMESPACE { ctor = false; dtor = false; + { + text_view_input< scan::lf > in( "a" ); + TAO_PEGTL_TEST_ASSERT( parse< test_grammar, test_action1 >( in ) ); - text_view_input< scan::lf > in( "a" ); - TAO_PEGTL_TEST_ASSERT( parse< test_grammar, test_action1 >( in ) ); + TAO_PEGTL_TEST_ASSERT( ctor == true ); + TAO_PEGTL_TEST_ASSERT( dtor == true ); + } + ctor = false; + dtor = false; + { + text_view_input< scan::lf > in( "0" ); + TAO_PEGTL_TEST_ASSERT( parse< test_grammar, test_action1 >( in ) ); - TAO_PEGTL_TEST_ASSERT( ctor == true ); - TAO_PEGTL_TEST_ASSERT( dtor == true ); + TAO_PEGTL_TEST_ASSERT( ctor == true ); + TAO_PEGTL_TEST_ASSERT( dtor == true ); + } } struct test_class2 diff --git a/src/test/pegtl/action_add_state.cpp b/src/test/pegtl/action_add_state.cpp new file mode 100644 index 000000000..bda062562 --- /dev/null +++ b/src/test/pegtl/action_add_state.cpp @@ -0,0 +1,152 @@ +// Copyright (c) 2024 Dr. Colin Hirsch and Daniel Frey +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt) + +#include "test.hpp" +#include "test_utility.hpp" + +#include +#include + +namespace TAO_PEGTL_NAMESPACE +{ + bool ctor = false; + bool dtor = false; + + struct state1 + { + state1() + { + TAO_PEGTL_TEST_ASSERT( !ctor ); + TAO_PEGTL_TEST_ASSERT( !dtor ); + ctor = true; + } + + ~state1() + { + TAO_PEGTL_TEST_ASSERT( ctor ); + TAO_PEGTL_TEST_ASSERT( !dtor ); + dtor = true; + } + + template< typename ParseInput > + void success( const ParseInput& in, std::size_t& st ) + { + TAO_PEGTL_TEST_ASSERT( ctor ); + TAO_PEGTL_TEST_ASSERT( !dtor ); + st = in.current_position().count; + } + + state1( state1&& ) = delete; + state1( const state1& ) = delete; + + void operator=( state1&& ) = delete; + void operator=( const state1&& ) = delete; + }; + + struct state2 + { + template< typename ParseInput > + state2( const ParseInput& in, const int ) + { + TAO_PEGTL_TEST_ASSERT( !ctor ); + TAO_PEGTL_TEST_ASSERT( !dtor ); + TAO_PEGTL_TEST_ASSERT( in.current_position().count == 1 ); + ctor = true; + } + + ~state2() + { + TAO_PEGTL_TEST_ASSERT( ctor ); + TAO_PEGTL_TEST_ASSERT( !dtor ); + dtor = true; + } + + state2( state2&& ) = delete; + state2( const state2& ) = delete; + + void operator=( state2&& ) = delete; + void operator=( const state2&& ) = delete; + }; + + using namespace alphabet::rules; + + struct grammar + : seq< a, sor< b, c >, d, eof > + {}; + + template< typename Rule > + struct action1 + : nothing< Rule > + {}; + + template<> + struct action1< sor< b, c > > + : add_state< state1 > + {}; + + template< typename Rule > + struct action2 + : nothing< Rule > + {}; + + template<> + struct action2< sor< b, c > > + : add_state< state2 > + {}; + + void unit_test() + { + // state1 parse success + { + ctor = false; + dtor = false; + std::size_t st = 0; + view_input<> in( "abd" ); + const bool b = parse< grammar, action1 >( in, st ); + TAO_PEGTL_TEST_ASSERT( b ); + TAO_PEGTL_TEST_ASSERT( ctor ); + TAO_PEGTL_TEST_ASSERT( dtor ); + TAO_PEGTL_TEST_ASSERT( st == 2 ); + } + // state1 parse failure + { + ctor = false; + dtor = false; + std::size_t st = 0; + view_input<> in( "ad" ); + const bool b = parse< grammar, action1 >( in, st ); + TAO_PEGTL_TEST_ASSERT( !b ); + TAO_PEGTL_TEST_ASSERT( ctor ); + TAO_PEGTL_TEST_ASSERT( dtor ); + TAO_PEGTL_TEST_ASSERT( st == 0 ); + } + // state2 parse success + { + ctor = false; + dtor = false; + const int i = 42; + view_input<> in( "abd" ); + const bool b = parse< grammar, action2 >( in, i ); + TAO_PEGTL_TEST_ASSERT( b ); + TAO_PEGTL_TEST_ASSERT( ctor ); + TAO_PEGTL_TEST_ASSERT( dtor ); + TAO_PEGTL_TEST_ASSERT( i == 42 ); + } + // state2 parse failure + { + ctor = false; + dtor = false; + const int i = 42; + view_input<> in( "ad" ); + const bool b = parse< grammar, action2 >( in, i ); + TAO_PEGTL_TEST_ASSERT( !b ); + TAO_PEGTL_TEST_ASSERT( ctor ); + TAO_PEGTL_TEST_ASSERT( dtor ); + TAO_PEGTL_TEST_ASSERT( i == 42 ); + } + } + +} // namespace TAO_PEGTL_NAMESPACE + +#include "main.hpp" diff --git a/src/test/pegtl/action_change_control.cpp b/src/test/pegtl/action_change_control.cpp new file mode 100644 index 000000000..88a8c8f85 --- /dev/null +++ b/src/test/pegtl/action_change_control.cpp @@ -0,0 +1,56 @@ +// Copyright (c) 2020-2024 Dr. Colin Hirsch and Daniel Frey +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt) + +#include + +#include "test.hpp" +#include "test_utility.hpp" + +#include + +namespace TAO_PEGTL_NAMESPACE +{ + template< template< typename... > class Control2 > + struct test_control + { + template< apply_mode A, + rewind_mode M, + template< typename... > class Action, + template< typename... > class Control, + typename ParseInput > + [[nodiscard]] static bool match( ParseInput& /*unused*/ ) noexcept + { + return std::is_same_v< Control< eof >, Control2< eof > >; + } + }; + + template< typename Rule > + struct normal2 + : normal< Rule > + {}; + + template< typename Rule > + struct action2 + : nothing< Rule > + {}; + + template<> + struct action2< seq< one< 'a' >, test_control< normal2 > > > + : change_control< normal2 > + {}; + + struct grammar + : must< test_control< normal >, seq< one< 'a' >, test_control< normal2 > >, eof > + {}; + + void unit_test() + { + view_input<> in( "a" ); + const bool b = parse< grammar, action2 >( in ); + TAO_PEGTL_TEST_ASSERT( b ); + } + +} // namespace TAO_PEGTL_NAMESPACE + +#include "main.hpp" diff --git a/src/test/pegtl/buffer_cstream_input.cpp b/src/test/pegtl/buffer_cstream_input.cpp index 1b99e4e2b..6dd29eed0 100644 --- a/src/test/pegtl/buffer_cstream_input.cpp +++ b/src/test/pegtl/buffer_cstream_input.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include "test.hpp" @@ -47,6 +48,22 @@ namespace TAO_PEGTL_NAMESPACE TAO_PEGTL_TEST_ASSERT( in.empty() ); std::fclose( stream ); } + { + std::FILE* stream = internal::read_file_open( filename ); + TAO_PEGTL_TEST_ASSERT( stream != nullptr ); + static_cstream_input< tao_buffer_eol, std::string, std::string > in( "filename", stream ); + TAO_PEGTL_TEST_ASSERT( parse< file_grammar >( in ) ); + TAO_PEGTL_TEST_ASSERT( in.empty() ); + std::fclose( stream ); + } + { + std::FILE* stream = internal::read_file_open( filename ); + TAO_PEGTL_TEST_ASSERT( stream != nullptr ); + dynamic_cstream_input< tao_buffer_eol, const char*, const char* > in( "filename", 500, 10, stream ); + TAO_PEGTL_TEST_ASSERT( parse< file_grammar >( in ) ); + TAO_PEGTL_TEST_ASSERT( in.empty() ); + std::fclose( stream ); + } } } // namespace TAO_PEGTL_NAMESPACE diff --git a/src/test/pegtl/buffer_istream_input.cpp b/src/test/pegtl/buffer_istream_input.cpp index 6205b963c..bfc8cc66d 100644 --- a/src/test/pegtl/buffer_istream_input.cpp +++ b/src/test/pegtl/buffer_istream_input.cpp @@ -4,6 +4,7 @@ #include #include +#include #include "test.hpp" @@ -49,6 +50,18 @@ namespace TAO_PEGTL_NAMESPACE TAO_PEGTL_TEST_ASSERT( parse< file_grammar >( in ) ); TAO_PEGTL_TEST_ASSERT( in.empty() ); } + { + std::ifstream stream( filename ); + static_istream_input< void, std::string, std::string > in( "filename", stream ); + TAO_PEGTL_TEST_ASSERT( parse< file_grammar >( in ) ); + TAO_PEGTL_TEST_ASSERT( in.empty() ); + } + { + std::ifstream stream( filename ); + dynamic_istream_input< void, const char*, const char* > in( "filename", 100, 90, stream ); + TAO_PEGTL_TEST_ASSERT( parse< file_grammar >( in ) ); + TAO_PEGTL_TEST_ASSERT( in.empty() ); + } } } // namespace TAO_PEGTL_NAMESPACE diff --git a/src/test/pegtl/internal_type_traits.cpp b/src/test/pegtl/internal_type_traits.cpp index 23fd31e0a..ccbf3af44 100644 --- a/src/test/pegtl/internal_type_traits.cpp +++ b/src/test/pegtl/internal_type_traits.cpp @@ -14,49 +14,46 @@ namespace TAO_PEGTL_NAMESPACE { }; - void unit_test() - { - static_assert( internal::is_simple_type_v< int > ); - static_assert( internal::is_simple_type_v< long > ); - static_assert( internal::is_simple_type_v< char32_t > ); - static_assert( internal::is_simple_type_v< std::byte > ); - static_assert( internal::is_simple_type_v< test_enum > ); - - static_assert( !internal::is_simple_type_v< int& > ); - static_assert( !internal::is_simple_type_v< long& > ); - static_assert( !internal::is_simple_type_v< char32_t& > ); - static_assert( !internal::is_simple_type_v< std::byte& > ); - static_assert( !internal::is_simple_type_v< test_enum& > ); - - static_assert( !internal::is_simple_type_v< int* > ); - static_assert( !internal::is_simple_type_v< long* > ); - static_assert( !internal::is_simple_type_v< char32_t* > ); - static_assert( !internal::is_simple_type_v< std::byte* > ); - static_assert( !internal::is_simple_type_v< test_enum* > ); - - static_assert( !internal::is_simple_type_v< void > ); - static_assert( !internal::is_simple_type_v< float > ); - static_assert( !internal::is_simple_type_v< std::string > ); - - static_assert( internal::is_simple_type_v< bool > ); // TODO? - - static_assert( internal::has_eol_char_rule< ascii::scan::lf > ); - static_assert( internal::has_eol_char_rule< ascii::scan::cr_crlf > ); - static_assert( !internal::has_eol_char_rule< ascii::lf > ); - static_assert( !internal::has_eol_char_rule< utf8::crlf > ); - - static_assert( internal::has_eol_rule< internal::input_with_lines< ascii::any7, internal::view_input< char > > > ); - static_assert( !internal::has_eol_rule< internal::input_with_lines< void, internal::view_input< char > > > ); - static_assert( !internal::has_eol_rule< internal::view_input< char > > ); - - static_assert( internal::has_start< argv_input<> > ); - static_assert( internal::has_start< view_input<> > ); - static_assert( internal::has_start< file_input<> > ); - static_assert( internal::has_start< read_input<> > ); - static_assert( internal::has_start< mmap_input<> > ); - - static_assert( !internal::has_start< base_input<> > ); - } + static_assert( internal::is_simple_type_v< int > ); + static_assert( internal::is_simple_type_v< long > ); + static_assert( internal::is_simple_type_v< char32_t > ); + static_assert( internal::is_simple_type_v< std::byte > ); + static_assert( internal::is_simple_type_v< test_enum > ); + + static_assert( !internal::is_simple_type_v< int& > ); + static_assert( !internal::is_simple_type_v< long& > ); + static_assert( !internal::is_simple_type_v< char32_t& > ); + static_assert( !internal::is_simple_type_v< std::byte& > ); + static_assert( !internal::is_simple_type_v< test_enum& > ); + + static_assert( !internal::is_simple_type_v< int* > ); + static_assert( !internal::is_simple_type_v< long* > ); + static_assert( !internal::is_simple_type_v< char32_t* > ); + static_assert( !internal::is_simple_type_v< std::byte* > ); + static_assert( !internal::is_simple_type_v< test_enum* > ); + + static_assert( !internal::is_simple_type_v< void > ); + static_assert( !internal::is_simple_type_v< float > ); + static_assert( !internal::is_simple_type_v< std::string > ); + + static_assert( internal::is_simple_type_v< bool > ); // TODO? + + static_assert( internal::has_eol_char_rule< ascii::scan::lf > ); + static_assert( internal::has_eol_char_rule< ascii::scan::cr_crlf > ); + static_assert( !internal::has_eol_char_rule< ascii::lf > ); + static_assert( !internal::has_eol_char_rule< utf8::crlf > ); + + static_assert( internal::has_eol_rule< internal::input_with_lines< ascii::any7, internal::view_input< char > > > ); + static_assert( !internal::has_eol_rule< internal::input_with_lines< void, internal::view_input< char > > > ); + static_assert( !internal::has_eol_rule< internal::view_input< char > > ); + + static_assert( internal::has_start< argv_input<> > ); + static_assert( internal::has_start< view_input<> > ); + static_assert( internal::has_start< file_input<> > ); + static_assert( internal::has_start< read_input<> > ); + static_assert( internal::has_start< mmap_input<> > ); + + static_assert( !internal::has_start< base_input<> > ); } // namespace TAO_PEGTL_NAMESPACE