Changelog
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project
adheres to Semantic Versioning.
Added
[cmake]
Presets for development and release builds on Clang, GCC, and MSVC
[core::functional]
added Collector
concept
[core::vector]
added Vector::collect()
method
Changed
- Substantial reworks to
core::memory
, core::slice
, and core::vector
[test::shell]
Renamed namespace from test::cli
Deprecated
Removed
core::bit_vector
, due to having no callers and adding substantially to the refactoring burden
Fixed
Security
Released on October 22, 2022.
Release notes
This release was tagged in order to transition off of GitLab and on to self-hosted storage. A
large amount of changes were made, including the removal of all libraries besides core
and test
(which used to be called testing
).
From this point on, the changelog will look different. Where there used to be a rigid rule in place
of adding one or more changelog entries per merge, now only noteworthy changes will be recorded.
Another change from this point onwards is that the old GitLab links may no longer work. When
possible, they will be replaced with links to afterlight.dev
, where Crucible is now being hosted.
Added
- A formatter for
std::type_info
- Formatters for C
char
and wchar_t
strings with dynamic sizes
core::memory
namespace for dealing with low-level memory management
Buffer
type for managing object lifetimes inside of raw memory
HeapAllocator
type for providing an interface to allocating heap memory
GenericStorage
and HeapStorage
types for managing memory from different sources
RecordFormatter
now has two versions of a method called add_synthetic_field
- These methods are used to add extra information that doesn't come from a physical member
core::vector::Vector
(which used to be core::array::Array
) can now be appended to using its push()
method
Changed
- Formatters for STL containers and C arrays are now multiline-capable
core::array
became core::vector
, and core::array::Array
became core::vector::Vector
core::bit_array
was merged into core::vector
, and core::bit_array::BitArray
became core::vector::BitVector
- The backing for both vectors and bit vectors was changed from
buffer::Buffer
to memory::HeapStorage
- All functionality from
unix
, windows
, and process
was consolidated and unified into core
- Many, many other changes, too many to document here; see the release notes
Removed
core::buffer
is gone since it no longer has any callers
Fixed
Security
Released on July 03, 2022.
Added
Build system
- All executable and library targets now receive preprocessor definitions describing the target they're being compiled for
- On Unix-like systems, the symbol
CRUCIBLE_UNIX
is defined in all header and source files
- On Windows-like systems, the symbol
CRUCIBLE_WINDOWS
is defined in all header and source files
- On all targets, the symbol
CRUCIBLE_ROOT
is defined to the path to the root of the repository
core
library
- A library-level
core.hpp
header that #include
s all other core
headers
- A new namespace called
fallible
- Provides a very similar type to
either::Either
, but with better semantics and more specific names
- Also provides analogues for
either::Lhs
and either::Rhs
called fallible::Failure
and fallible::Success
- Also also provides a type called
Error
that serves as a variadic error type container
- A new namespace called
arrays
- Provides two new types:
Array
, which owns a dynamically allocated buffer; and Slice
, which views a subsection of an Array
- Also provides two overloads of a function called
make_array()
, which constructs an Array
from a C array of static or dynamic size
- A new overload of
format::format_carray()
that accepts a size
argument
- A new API for formatting classes and structs:
format_record()
and build_fields()
- A new type,
format::Context
, supplies formatting parameters and can be made with format::build_context()
format_record()
is a utility function that is called from T::format()
for any T
build_fields()
is used to obtain a builder object that collects all of the fields in the object into a string
- A new API for working with packed bit arrays called
bitarray
- A class called
BitArray
that owns its storage
- Another class called
BitSlice
that borrows a range of storage from a BitArray
- A new API for typed memory buffers called
buffer
, containing:
- A template class called
Buffer
that holds a pointer and a size (and auto-frees the pointer on destruction)
- Free functions
make_buffer_by_copy()
and make_buffer_by_move()
for creating a Buffer
from a pointer and size
array
, bit_array
, and buffer
can now all be constructed using a std::initializer_list
array
and bit_array
can now be constructed using a C-style array (and buffer
always could be)
make_buffer_by_move()
changed to do an element-wise move rather than steal a pointer
buffer::Accumulator
added to handle building up a Buffer
procedurally rather than using a std::vector
or raw array
- A formatter for
std::variant
grok
library
- A new library that will (eventually) replace the
parsing
library
meta
library
- A new library for communicating meta-level information (like libc capabilities) from the build system to the source code
- Runtime capabilities (mainly of the C library) can be checked using the
CRUCIBLE_META_CAPABILITY_*
macros in the capability.hpp
header
process
library
- This is a new library that deals with things related to the process that Crucible is running inside of
- So far, there is one namespace called
backtrace
, which deals with getting backtraces in a cross-platform way:
- The
take_detailed_snapshot()
function captures as much debug information as possible in DetailedStackFrame
objects
- The
take_simple_snapshot()
function captures only function names in SimpleStackFrame
objects
- The
terminate_handler()
function can be registered as a terminate handler using std::set_terminate()
to print a nice crash report
- There is also the usual
result
namespace, with two error types so far:
EmptyBacktrace
indicates that the stack walking mechanism found 0 frames above the caller in the current thread's call stack
MissingDebugInformation
indicates that a detailed snapshot couldn't be performed because there was no debug information found
testing
library
- A library-level
testing.hpp
header that #include
s all other testing
headers
- Two new macros:
EXPECT_FAILURE()
and EXPECT_SUCCESS()
, which test the state of a fallible::Result
object
- Test suites now have names that are printed by the reporters on output
unix
library
- A library-level
unix.hpp
header that #include
s all other unix
headers
- A new namespace called
backtrace
- Provides a function called
snapshot()
which takes a snapshot of the current call stack
- Also provides a simple type called
Frame
which holds the symbol associated with each frame of the call stack
windows
library
- A library-level
windows.hpp
header that #incude
s all other windows
headers
- A new namespace called
backtrace
- Provides a function called
snapshot()
which takes a snapshot of the current call stack
- Also provides a simple type called
Frame
which holds a semantic description of one frame of the call stack
Changed
General
- Combined the
boba
library with the vm
library, then renamed it to bolt
- Changed the supported Linux variant from Arch on amd64 to Ubuntu on amd64 in the README
- Clarified the supported versions of macOS and Windows in the README
- Convert all uses of
core::either
to use core::fallible
instead
- Exception:
parsing
still uses core::either
, because it needs more work to support the change
- All macro names across all targets have been standardized to the same naming convention
- All structs and classes now use the new
format()
API (with format::Context
)
- Big lambdas refactored into named functions
Build system
- Unified naming of all CMake modules, functions, and variables to make it obvious when something is part of Crucible
- Modules are named with the convention
CrucibleXyz.cmake
- Functions are named with the convention
crucible_xyz()
- Variables are named with the convention
CRUCIBLE_XYZ
- Hid some low-level cache variables behind new CMake functions
crucible_configure_language_standards()
handles setting language flags
crucible_configure_output_directory()
handles setting the output directory of final artifacts
crucible_configure_shared_library_exports()
handles setting flags for how shared library exports are handled
- Handle platform-specific libraries in the
CMakeLists.txt
for those libraries
core
library
- All
format
functions now take T const &
instead of T &&
, because formatters should never change the thing they're formatting
arrays::Array
and arrays::Slice
now use the new formatting API
core::assert
has better formatting for its messages now
format::format_pointer()
now requires a formatting context so it can render a pointed-to record properly
fallible::Failure
, fallible::Success
, and fallible::Result
now behave more like a true sum type (and by extension, functor and monad)
- Renamed
core::fallible
to core::result
- Renamed
core::bitarray
to core::bit_array
array::Array
and bit_array::BitArray
are now backed by buffer::Buffer
instead of raw memory
format::format_record()
now has a simpler API
testing
library
testing::cli::execute()
now sets the terminate handler to process::backtrace::terminate_handler()
, which prints a crash report
testing::expect
has better formatting for its messages now
testing::console_reporter
has totally redone reporting for better readability
- Failures are now collected and displayed at the end, rather than printed inline with the tests
- Instead of indenting to show hierarchy, section headers with underlining and colors are used to flatten the output and make it easier to read
- The formatting for the test summary is slightly different
Removed
- The
bobadump
executable is totally gone, because boba
has been rolled into the bolt
library
- The
os
library is gone, because its only user was bobadump
(which was also removed)
- The
core::resource_warden
namespace is gone, because it's very easy to get the same functionality without it
- The
parsing
library is removed and will be replaced with grok
- The
bolt
library was emptied out and will be remade once grok
is ready
- The
core::format::build_fields()
function is gone (not needed any more)
Fixed
- Check the target compatibility after setting the C++ standard (so that
static_assert
works properly)
- Make sure to save the
CMAKE_*_OUTPUT_DIRECTORY
variables to the CMake cache
- Fixed compilation errors and failing tests when building on Linux
core::fallible::Result::bind_failure()
and core::fallible::Result::bind_success()
now perform a real >>=
operation
- Bug in the macro expansion of
ASSERT()
which made it not compile (comparisons were unaffected)
Released on February 05, 2022.
Added
parsing
library
- A new combinator called
Map
and associated factory function make_map()
- Accepts a parser and a function and transforms the result of the parser using the function
- A new combinator called
Bind
and associated factory function make_bind()
- Uses the result of one parser to build a new parser, then applies the new parser
- A new combinator called
Tee
and associated factory function make_tee()
- Similar to
Bind
, but keeps the output of both parsers and returns it in a std::pair
- Several new factory functions and types in the
bytes
namespace (used to be the bits
namespace):
Endianness
, an enumeration used to distinguish big-endian and little-endian parsers from one another
U8Le
, U16Le
, U32Le
, U64Be
, U8Be
, U16Be
, U32Be
, and U64Be
: parsers for the appropriate type and endianness
make_exact()
and make_take()
: factory functions for creating Exact
and Take
parsers
make_u8_le()
, make_u16_le()
, make_u32_le()
, make_u64_le()
: factory functions for little-endian unsigned integer parsers
make_u8_be()
, make_u16_be()
, make_u32_be()
, make_u64_be()
: factory functions for big-endian unsigned integer parsers
Changed
Build system
- Disabled the
C4180
compiler warning on MSVC due to not being helpful and causing the build to fail
bobadump
executable
- Updated output to correspond with new Boba format
boba
library
- Total overhaul of the file format and internals
- The schema block is gone; instead we have a special container metadata section
- The
from_bytes()
API is exactly the same, but the Container
type is now a simple record containing a vector of headers
- New namespace:
container
- Contains simple record types for both individual block headers and the container as a whole
- New namespace:
read
- The
from_bytes()
function was moved here
parsing
library
- The meaning of the
Into
parser combinator has changed
Into<T>
now converts the result of its wrapped parser into a T
using one of T
's constructors
- The
bits
namespace has been renamed to bytes
, and also renamed the contents:
- Renamed
BitsState
type to State
- Renamed
ByteSequence
parser to Exact
- Renamed
SizedByteSequence
parser to Take
- Combined
BigEndianUnsignedInteger
and LittleEndianUnsignedInteger
parsers into UnsignedInteger
Removed
boba
library
- The
metadata
namespace is gone; see the new container
and read
namespaces for equivalent functionality
parsing
library
- The
>>
operator is no longer overloaded to construct an instance of Into
Fixed
bobadump
executable
- Tests were not passing on windows due to
\r\n
line endings not being handled correctly in the test script
parsing
library
- Compilation errors on macOS due to mis-ordered class fields and missing constructors
Released on January 01, 2022.
Added
bobadump
executable
- New executable for dumping Boba files
- No options; just use
crucible-bobadump BOBA_FILE
- Prints the schema header (but not the schema entries) and each user header
core
library
- New formatter for primitive integer types called
format_integral()
- Will work on anything for which
std::is_integral
evaluates to true
- New abstract method in
AbstractError
called describe()
- In contrast to
format()
, which is intended for developers, describe()
is intended for end users
either::Either
got new methods bind_lhs()
and bind_rhs()
- Maps a value to a whole new
Either
instance
- This is in contrast to
map_lhs()
and map_rhs()
, which map a value to another value
- Can be used to chain
Either
-returning functions together
os
library
- New library for abstracting over "operating-system-y" things
- Automatically switches between
unix
and windows
as a backend depending on the compilation target
- The
fs
namespace has platform-agnostic wrapper functions for all of the utilities in unix::fs
and windows::fs
Build system
- Support for Python test drivers via
add_crucible_python_test()
(intended mainly for testing executables)
General
- Added information about Python tests to the readme
- Added information about supported compilation targets to the readme
Changed
bobadump
executable
- Renamed from
boba-dump
to just bobadump
core
library
either::LHS
and either::RHS
renamed to either::Lhs
and either::Rhs
for readability
os
library
- The Windows implementation of the
fs
namespace now uses the bind_lhs()
and bind_rhs()
APIs of core::either::Either
Build system
- Silenced the message from
find_package
, which could be really long and was basically just noise
General
- All uses of
Result
have been changed to Either
to remove duplicated code
- Better end-user error messages across the board
- Uses of "Boba" as a word standardized on camel-case, not uppercase (
BOBA
) or lowercase (boba
)
Removed
- The
core::result
namespace has been completely removed; use core::either
instead
Fixed
parsing
library
- Compilation error on MSVC due to signed/unsigned comparison mismatch
unix
library
- Errors now have their details reported properly (we see the
errno
message)
windows
library
- Errors now have their details reported properly (we see the
GetLastError()
message)
Released on December 04, 2021.
Added
New libraries
boba
, the reference implementation of the BOBA (Bunch Of Big Arrays) file format
boba
library
- The new
errors
namespace:
- The main error class
BobaError
- The
ParsingFailed
error variant for when loading a BOBA container fails
- A type alias
BobaResult
for core::result::Result
- The new
metadata
namespace:
- A POD type called
Header
for keeping the (almost) raw information about each block header
- A type called
Schema
that wraps the very first Header
of a container, providing information about the rest of the contents
- A type called
Container
that holds all block headers and provides iterator access to them, as well as the schema
- A function called
from_bytes()
which deserializes a byte stream into a Container
core
library
- The
format
namespace:
- Lots of functions for formatting anything you can think of: STL containers, plain arrays, C strings, pointers...
- A
format_anything()
function which intelligently selects a formatter based on a compile-time type check
- Lots of new
ASSERT
macros, for parity with the EXPECT
API
- The
errors
namespace:
- An abstract base class called
AbstractError
, intended to be used for the Failure
alternative of Result
instances
- Support for
std::tuple
in format::format_anything()
constexpr
comparison operators for none::None
parsing
library
- A new combinator called
SequenceOf
- Used to parse an exact number of repetitions of a single structure
- Fails if there aren't enough occurrences (but it's fine to have more)
- Has an associated error called
SequenceOfError
- The
errors
namespace:
- Error variants
AmbiguousMatch
, UnexpectedInput
, and UnexpectedEndOfInput
- The main error class
ParsingError
and a Result
alias named ParsingResult
- A new combinator called
Tuple
- Used to parse a heterogeneous sequence of substructures
- No combinator operator; use
combinators::make_tuple()
- New factory functions for each combinator:
make_one_of()
, make_pair()
, make_into()
, and make_sequence_of()
unix
library
- The
errors
namespace:
- The
HostError
type, which is moved from the old errno_error::ErrnoError
type
- Error variants moved from the
fs
namespace
- The main error class
UnixError
and a Result
alias named UnixError
windows
library
- The
errors
namespace:
- The
HostError
, which is moved from the old windows_error::WindowsError
type
- Error variants moved from the
fs
and transcoding
namespaces
- The main error class
WindowsError
and a Result
alias named WindowsResult
testing
library
- Self tests (at least, for the parts that can be isolated and tested!)
Changed
ASSERT
, EXPECT
, and Result
now use the format_anything()
function to render objects
- All error handling is now done using a combination of
core::errors::AbstractError
and core::result::Result
- Each library now has an
errors
namespace in which it defines its own specializations of these types
core
library
none::None
now formats as "None"
instead of "None {}"
parsing
library
AndThen
combinator renamed to Pair
(as a special case of Tuple
)
Removed
ASSERT_NOT_NULL
is gone; use ASSERT_NE(thing, nullptr)
- The
parsing::result
, unix::errno_error
, and windows::windows_error
namespaces are all gone
- See the
errors
namespaces in each library for a standardized replacement
Released on November 06, 2021.
Added
core
library
- A new namespace called
assert
, containing functions for implementing the ASSERT
macro family
- In the
assert
namespace:
- A pair of new macros called
ASSERT
and ASSERT_NOT_NULL
, which terminate the program with a message if the assertion does not pass
- A template function called
fail
, which implements the assertion failure mechanism
- A new namespace called
either
, containing the Either
type for holding one of two types of value
- In the
either
namespace:
- A tag type called
PreventSelectionForCopyAndMove
used internally
- A pair of templates called
LHS
and RHS
which distinguish the alternatives of an Either
- A template called
Either
which can hold one of two values, which can have different types
- A pair of functions called
make_lhs()
and make_rhs()
, which can be used to create LHS
and RHS
instances to pass to an Either
parsing
library
- In the
bits
namespace:
- A new parser called
SizedByteSequence
which extracts a specific number of bytes from the input
- In the
combinators
namespace:
- A new combinator called
Into
, which functions like AndThen
but dynamically constructs the second parser based on the result of the first parser
- Two new errors called
AndThenError
and IntoError
, which serve as error types for the AndThen
and Into
combinators
- In the
combinators::operators
namespace:
- An overloaded
>>
operator, which builds Into
instances from a parser and a function
testing
library
- In the
expect
namespace:
- A pair of new macros called
EXPECT_CONTAINER_EQ
and EXPECT_CONTAINER_NE
, which check for (in)equality between two iterables
- In the
abstract_reporter
namespace:
- The
AbstractReporter
class now has default do-nothing implementations for all of its virtual methods
- Two new hook methods for
AbstractReporter
: handle_group_start()
and handle_group_end()
, which get the name of the group
- In the
reporter
namespace:
- Forwarding methods for the
handle_group_start()
and handle_group_end()
hooks
- In the
console_reporter
namespace:
- An implementation of
handle_group_start
that prints the group name
Changed
testing
library
- Scenarios and fixtures now both accept a tag argument before the name, which groups the fixtures and scenarios together
- Tags can be filtered on the command line with the
-t
or --tag
option
- Fixtures will only be run for the scenarios that have the same tag
BeforeAll
and AfterAll
fixtures will only run if their tag isn't being filtered out
- Output rendering is much clearer
- A count of total scenarios run is now printed
- Fixtures are now printed at the same level as scenarios instead of inside them
- Fixtures receive a pass/fail note (when they would be printed anyways)
- Added icons for each keyword to make distinguishing them a little clearer
- Removed all white and bright white to make reading output on a white background easier
- "Tags" renamed to "Groups"
- The option in the CLI runner has been changed from
-t/--tag
to -g/--group
- Groups are now used as "containers" for scenarios
- There are now two loops: one over each group, and another over each scenario within the group
BeforeAll
and AfterAll
fixtures now run only within their group, not at the start or end of the whole suite
- The console reporter will show groups as the main heading now, with scenarios and fixtures underneath
unix
library
test_fs
now uses the fixture mechanism to create and delete its file structure
General
- Turned all instances of
std::u8string
, std::u8string_view
, char8_t
, and u8""
literals back into their legacy versions due to bad support
- Standardized constructor syntax (
{}
unless ()
is semantically required)
parsing
library
- The
bits::ByteSequence
and text::CharacterSequence
parsers now make a deep copy of their sequences
- The
bits::ByteSequence
parser has been renamed to bits::ExactByteSequence
Fixed
- Compilation error on AppleClang:
no viable constructor or deduction guide
in core::assert::fail()
Released on October 02, 2021.
Added
New libraries
vm
library for the virtual machine implementation
parsing
library for parser combinators
parsing
library features
bits
namespace containing primitives for parsing binary data
FixedWidthUnsignedIntegerType
concept, which constrains to one of the std::uintN_t
types
ByteSequenceMismatch
basic error type
UnexpectedEndOfInput
basic error type
BitsError
composite error type
BitsState
type specialized for binary data
ByteSequence
parser which matches an exact sequence of bytes
LittleEndianUnsignedInteger
parser template
BigEndianUnsignedInteger
parser template
combinators
namespace containing types for combining simple parsers into more complex parsers
BothMatch
error template
NeitherMatch
error template
OneOfError
composite error type
OneOf
parser combinator, which matches exclusively one or the other of the child parsers
AndThen
parser combinator, which matches one parser followed by another parser and returns both results
operators
namespace containing tools for building combinator trees
operator^
, which combines two parsers using the OneOf
combinator
operator&
, which combines two parsers using the AndThen
combinator
result
namespace containing utility types for the outcomes of individual parsers
Reject
template for holding information about a rejected parse
Accept
template for holding information about an accepted parse
reject
function for building a Reject
wrapped in a core::result::Failure
accept
function for building an Accept
wrapped in a core::result::Success
text
namespace containing primitives for parsing UTF-8 data
CharacterSequenceMismatch
basic error type
TextError
composite error type
TextState
type specialized for UTF-8 data
CharacterSequence
parser which matches an exact sequence of characters
testing
library features
- New namespace:
fixture
for types related to test fixtures
- In the
fixture
namespace:
FixtureFunction
alias for the type of a fixture function
FixtureVariant
template type which serves as a base class for each kind of fixture
BeforeAll
, AfterAll
, BeforeEach
, and AfterEach
tag types which differentiate each kind of fixture
- The
Fixture
type itself, which abstracts over all of these details
- In the
FixtureVariant
type:
- A constructor accepting a
FixtureFunction
- A getter method called
get_name()
which returns the name of the fixture variant based on which derived class calls it
- A method named
execute()
which runs the fixture and returns an outcome, just like a scenario
- In the
BeforeAll
, AfterAll
, BeforeEach
, and AfterEach
types:
- A constant string field containing the name of the variant for reporting purposes
- In the
Fixture
type:
- A constructor which accepts a name and a fixture variant
- A template method called
has_variant()
which checks what kind of fixture this is
- A method called
get_variant_name()
which forwards to get_name()
on the underlying variant
- A getter method called
get_name()
which retrieves the fixture's name
- A method called
execute()
which forwards to execute()
on the underlying variant
- In the
suite
namespace:
- Four new macros which define fixtures in the same way as scenarios:
BEFORE_ALL
, AFTER_ALL
, BEFORE_EACH
, and AFTER_EACH
- A new type called
FixtureRegistrar
which is used by the new macros to add fixtures to the suite
- In the
FixtureRegistrar
type:
- A constructor that forwards to
add_fixture()
on the suite
- In the
Suite
singleton:
- A method called
add_fixture()
which registers a new fixture in the suite
- In
reporter::Reporter
, abstract_reporter::AbstractReporter
, and console_reporter::ConsoleReporter
:
- Two new methods called
handle_fixture_start()
and handle_fixture_end()
which are called before and after each fixture
- Another new method called
set_show_fixtures()
which toggles how much information is reported about fixtures
- In the
expect
namespace:
- A new template function called
fail_comparison()
, which is exactly like fail()
but formats its output specifically as a comparison failure
Changed
Build system
- Upgrade the C++ version to C++20
- Renamed the
test
library to testing
to better fit with other library names (specifically parsing
)
testing
library features
- Print a special message when there are no tests in a test suite
- Tests can now accept a
--show-fixtures
argument on the command line which causes the reporter to print more information about which fixtures run and when
- The
SCENARIO
macro and ScenarioRegistrar
type have been moved to the suite
namespace
- The console reporter will now display a count of total fixture invocations in the suite summary
- All reporters now require a third argument,
fixture_count
, to the handle_suite_end()
method
- The
EXPECT
family of macros now print much more detailed information when a test fails
- In the
expect
namespace:
- The
fail
function now takes more arguments and has been made into a template based on the type of value being EXPECT
ed
Fixed
parsing
library
- Compilation
cast truncates constant value
warning on MSVC
testing
library
- Disallow copying and moving the Suite singleton
- Incorrect include guard symbols
- Compilation warning on AppleClang:
[[nodiscard]]
on a function returning void
Build system
- Give a nice message from CMake instead of weird errors when trying to build for non-64-bit systems
Released on September 04, 2021.
Added
New libraries
core
library for fundamental types and functions used by everything else
test
library for testing infrastructure
unix
library for wrapping Unix-like APIs
windows
library for wrapping Windows APIs
core
library features
core::constant_error
namespace, containing a ConstantError
template for errors with a constant message
core::error_chain
namespace, containing the ErrorChain
class for building complex error types
core::none
namespace, containing the None
type to use as a placeholder
core::resource_warden
namespace, containing a class template for cleaning up raw resources on scope exit
core::result
namespace, containing facilities for operations that can fail
test
library features
test::abstract_reporter
namespace, containing the AbstractReporter
interface
test::cli
namespace, containing a function execute()
that can be called from main()
test::console_reporter
namespace, containing a reporter that writes to stdout
test::expect
namespace, containing macros to express test assertions
test::outcome
namespace, containing types representing scenario outcomes
test::reporter
namespace, containing factories for specific reporters and also a wrapper type
test::scenario
namespace, containing the Scenario
type for representing a single test scenario
test::suite
namespace, containing the Suite
singleton used to hold all of the tests in a suite
unix
library features
unix::errno_error
namespace, containing utilities for working with errno
unix::fs
namespace, containing wrappers for filesystem APIs on Unix-like systems
windows
library features
windows::fs
namespace, containing wrappers for filesystem APIs on Windows
windows::transcoding
namespace, containing functions for transcoding UTF8 with UTF16 for Windows APIs
windows::windows_error
namespace, containing functions and a type for reading and formatting Windows errors
Build system features
AddCrucibleExecutable
module, which provides a wrapper for add_executable()
AddCrucibleLibrary
module, which provides a wrapper for add_library()
AddCrucibleTest
module, which provides a wrapper for add_test()
EnableCompilerWarnings
module, which provides a function that enables common compiler warning flags
EnableRuntimeSanitizers
module, which provides a function that enables ASAN, TSAN, and UBSAN based on options
- Write all final build outputs (executables and libraries) to
${PROJECT_BINARY_DIR}/artifacts
- Automatically export all symbols from all libraries when building Windows DLLs
Repository features
- Build dependencies in the README
- Build instructions in the README
- Test instructions in the README
- Attribution in the README
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project
adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
### Added
* `[cmake]` Presets for development and release builds on Clang, GCC, and MSVC
* `[core::functional]` added `Collector` concept
* `[core::vector]` added `Vector::collect()` method
### Changed
* Substantial reworks to `core::memory`, `core::slice`, and `core::vector`
* `[test::shell]` Renamed namespace from `test::cli`
### Deprecated
### Removed
* `core::bit_vector`, due to having no callers and adding substantially to the refactoring burden
### Fixed
### Security
## [0.8.0]
Released on October 22, 2022.
### Release notes
This release was tagged in order to transition off of GitLab and on to self-hosted storage. A
large amount of changes were made, including the removal of all libraries besides `core` and `test`
(which used to be called `testing`).
From this point on, the changelog will look different. Where there used to be a rigid rule in place
of adding one or more changelog entries per merge, now only noteworthy changes will be recorded.
Another change from this point onwards is that the old GitLab links may no longer work. When
possible, they will be replaced with links to `afterlight.dev`, where Crucible is now being hosted.
### Added
* A formatter for `std::type_info`
* Formatters for C `char` and `wchar_t` strings with dynamic sizes
* `core::memory` namespace for dealing with low-level memory management
* `Buffer` type for managing object lifetimes inside of raw memory
* `HeapAllocator` type for providing an interface to allocating heap memory
* `GenericStorage` and `HeapStorage` types for managing memory from different sources
* `RecordFormatter` now has two versions of a method called `add_synthetic_field`
* These methods are used to add extra information that doesn't come from a physical member
* `core::vector::Vector` (which used to be `core::array::Array`) can now be appended to using its `push()` method
### Changed
* Formatters for STL containers and C arrays are now multiline-capable
* `core::array` became `core::vector`, and `core::array::Array` became `core::vector::Vector`
* `core::bit_array` was merged into `core::vector`, and `core::bit_array::BitArray` became `core::vector::BitVector`
* The backing for both vectors and bit vectors was changed from `buffer::Buffer` to `memory::HeapStorage`
* All functionality from `unix`, `windows`, and `process` was consolidated and unified into `core`
* Many, many other changes, too many to document here; see the release notes
### Removed
* `core::buffer` is gone since it no longer has any callers
### Fixed
### Security
## [0.7.0]
Released on July 03, 2022.
### Added
#### Build system
* All executable and library targets now receive preprocessor definitions describing the target they're being compiled for
* On Unix-like systems, the symbol `CRUCIBLE_UNIX` is defined in all header and source files
* On Windows-like systems, the symbol `CRUCIBLE_WINDOWS` is defined in all header and source files
* On all targets, the symbol `CRUCIBLE_ROOT` is defined to the path to the root of the repository
#### `core` library
* A library-level `core.hpp` header that `#include`s all other `core` headers
* A new namespace called `fallible`
* Provides a very similar type to `either::Either`, but with better semantics and more specific names
* Also provides analogues for `either::Lhs` and `either::Rhs` called `fallible::Failure` and `fallible::Success`
* _Also_ also provides a type called `Error` that serves as a variadic error type container
* A new namespace called `arrays`
* Provides two new types: `Array`, which owns a dynamically allocated buffer; and `Slice`, which views a subsection of an `Array`
* Also provides two overloads of a function called `make_array()`, which constructs an `Array` from a C array of static or dynamic size
* A new overload of `format::format_carray()` that accepts a `size` argument
* A new API for formatting classes and structs: `format_record()` and `build_fields()`
* A new type, `format::Context`, supplies formatting parameters and can be made with `format::build_context()`
* `format_record()` is a utility function that is called from `T::format()` for any `T`
* `build_fields()` is used to obtain a builder object that collects all of the fields in the object into a string
* A new API for working with packed bit arrays called `bitarray`
* A class called `BitArray` that owns its storage
* Another class called `BitSlice` that borrows a range of storage from a `BitArray`
* A new API for typed memory buffers called `buffer`, containing:
* A template class called `Buffer` that holds a pointer and a size (and auto-frees the pointer on destruction)
* Free functions `make_buffer_by_copy()` and `make_buffer_by_move()` for creating a `Buffer` from a pointer and size
* `array`, `bit_array`, and `buffer` can now all be constructed using a `std::initializer_list`
* `array` and `bit_array` can now be constructed using a C-style array (and `buffer` always could be)
* `make_buffer_by_move()` changed to do an element-wise move rather than steal a pointer
* `buffer::Accumulator` added to handle building up a `Buffer` procedurally rather than using a `std::vector` or raw array
* A formatter for `std::variant`
#### `grok` library
* A new library that will (eventually) replace the `parsing` library
#### `meta` library
* A new library for communicating meta-level information (like libc capabilities) from the build system to the source code
* Runtime capabilities (mainly of the C library) can be checked using the `CRUCIBLE_META_CAPABILITY_*` macros in the `capability.hpp` header
#### `process` library
* This is a new library that deals with things related to the process that Crucible is running inside of
* So far, there is one namespace called `backtrace`, which deals with getting backtraces in a cross-platform way:
* The `take_detailed_snapshot()` function captures as much debug information as possible in `DetailedStackFrame` objects
* The `take_simple_snapshot()` function captures only function names in `SimpleStackFrame` objects
* The `terminate_handler()` function can be registered as a terminate handler using `std::set_terminate()` to print a nice crash report
* There is also the usual `result` namespace, with two error types so far:
* `EmptyBacktrace` indicates that the stack walking mechanism found 0 frames above the caller in the current thread's call stack
* `MissingDebugInformation` indicates that a detailed snapshot couldn't be performed because there was no debug information found
#### `testing` library
* A library-level `testing.hpp` header that `#include`s all other `testing` headers
* Two new macros: `EXPECT_FAILURE()` and `EXPECT_SUCCESS()`, which test the state of a `fallible::Result` object
* Test suites now have names that are printed by the reporters on output
#### `unix` library
* A library-level `unix.hpp` header that `#include`s all other `unix` headers
* A new namespace called `backtrace`
* Provides a function called `snapshot()` which takes a snapshot of the current call stack
* Also provides a simple type called `Frame` which holds the symbol associated with each frame of the call stack
#### `windows` library
* A library-level `windows.hpp` header that `#incude`s all other `windows` headers
* A new namespace called `backtrace`
* Provides a function called `snapshot()` which takes a snapshot of the current call stack
* Also provides a simple type called `Frame` which holds a semantic description of one frame of the call stack
### Changed
#### General
* Combined the `boba` library with the `vm` library, then renamed it to `bolt`
* Changed the supported Linux variant from Arch on amd64 to Ubuntu on amd64 in the README
* Clarified the supported versions of macOS and Windows in the README
* Convert all uses of `core::either` to use `core::fallible` instead
* Exception: `parsing` still uses `core::either`, because it needs more work to support the change
* All macro names across all targets have been standardized to the same naming convention
* All structs and classes now use the new `format()` API (with `format::Context`)
* Big lambdas refactored into named functions
#### Build system
* Unified naming of all CMake modules, functions, and variables to make it obvious when something is part of Crucible
* Modules are named with the convention `CrucibleXyz.cmake`
* Functions are named with the convention `crucible_xyz()`
* Variables are named with the convention `CRUCIBLE_XYZ`
* Hid some low-level cache variables behind new CMake functions
* `crucible_configure_language_standards()` handles setting language flags
* `crucible_configure_output_directory()` handles setting the output directory of final artifacts
* `crucible_configure_shared_library_exports()` handles setting flags for how shared library exports are handled
* Handle platform-specific libraries in the `CMakeLists.txt` for those libraries
#### `core` library
* All `format` functions now take `T const &` instead of `T &&`, because formatters should never change the thing they're formatting
* `arrays::Array` and `arrays::Slice` now use the new formatting API
* `core::assert` has better formatting for its messages now
* `format::format_pointer()` now requires a formatting context so it can render a pointed-to record properly
* `fallible::Failure`, `fallible::Success`, and `fallible::Result` now behave more like a true sum type (and by extension, functor and monad)
* Renamed `core::fallible` to `core::result`
* Renamed `core::bitarray` to `core::bit_array`
* `array::Array` and `bit_array::BitArray` are now backed by `buffer::Buffer` instead of raw memory
* `format::format_record()` now has a simpler API
#### `testing` library
* `testing::cli::execute()` now sets the terminate handler to `process::backtrace::terminate_handler()`, which prints a crash report
* `testing::expect` has better formatting for its messages now
* `testing::console_reporter` has totally redone reporting for better readability
* Failures are now collected and displayed at the end, rather than printed inline with the tests
* Instead of indenting to show hierarchy, section headers with underlining and colors are used to flatten the output and make it easier to read
* The formatting for the test summary is slightly different
### Removed
* The `bobadump` executable is totally gone, because `boba` has been rolled into the `bolt` library
* The `os` library is gone, because its only user was `bobadump` (which was also removed)
* The `core::resource_warden` namespace is gone, because it's very easy to get the same functionality without it
* The `parsing` library is removed and will be replaced with `grok`
* The `bolt` library was emptied out and will be remade once `grok` is ready
* The `core::format::build_fields()` function is gone (not needed any more)
### Fixed
* Check the target compatibility _after_ setting the C++ standard (so that `static_assert` works properly)
* Make sure to save the `CMAKE_*_OUTPUT_DIRECTORY` variables to the CMake cache
* Fixed compilation errors and failing tests when building on Linux
* `core::fallible::Result::bind_failure()` and `core::fallible::Result::bind_success()` now perform a real `>>=` operation
* Bug in the macro expansion of `ASSERT()` which made it not compile (comparisons were unaffected)
## [0.6.0]
Released on February 05, 2022.
### Added
#### `parsing` library
* A new combinator called `Map` and associated factory function `make_map()`
* Accepts a parser and a function and transforms the result of the parser using the function
* A new combinator called `Bind` and associated factory function `make_bind()`
* Uses the result of one parser to build a new parser, then applies the new parser
* A new combinator called `Tee` and associated factory function `make_tee()`
* Similar to `Bind`, but keeps the output of both parsers and returns it in a `std::pair`
* Several new factory functions and types in the `bytes` namespace (used to be the `bits` namespace):
* `Endianness`, an enumeration used to distinguish big-endian and little-endian parsers from one another
* `U8Le`, `U16Le`, `U32Le`, `U64Be`, `U8Be`, `U16Be`, `U32Be`, and `U64Be`: parsers for the appropriate type and endianness
* `make_exact()` and `make_take()`: factory functions for creating `Exact` and `Take` parsers
* `make_u8_le()`, `make_u16_le()`, `make_u32_le()`, `make_u64_le()`: factory functions for little-endian unsigned integer parsers
* `make_u8_be()`, `make_u16_be()`, `make_u32_be()`, `make_u64_be()`: factory functions for big-endian unsigned integer parsers
### Changed
#### Build system
* Disabled the [`C4180`] compiler warning on MSVC due to not being helpful and causing the build to fail
#### `bobadump` executable
* Updated output to correspond with new Boba format
#### `boba` library
* Total overhaul of the file format and internals
* The schema block is gone; instead we have a special container metadata section
* The `from_bytes()` API is exactly the same, but the `Container` type is now a simple record containing a vector of headers
* New namespace: `container`
* Contains simple record types for both individual block headers and the container as a whole
* New namespace: `read`
* The `from_bytes()` function was moved here
#### `parsing` library
* The meaning of the `Into` parser combinator has changed
* `Into<T>` now converts the result of its wrapped parser into a `T` using one of `T`'s constructors
* The `bits` namespace has been renamed to `bytes`, and also renamed the contents:
* Renamed `BitsState` type to `State`
* Renamed `ByteSequence` parser to `Exact`
* Renamed `SizedByteSequence` parser to `Take`
* Combined `BigEndianUnsignedInteger` and `LittleEndianUnsignedInteger` parsers into `UnsignedInteger`
### Removed
#### `boba` library
* The `metadata` namespace is gone; see the new `container` and `read` namespaces for equivalent functionality
#### `parsing` library
* The `>>` operator is no longer overloaded to construct an instance of `Into`
* Use `make_into()` instead
### Fixed
#### `bobadump` executable
* Tests were not passing on windows due to `\r\n` line endings not being handled correctly in the test script
#### `parsing` library
* Compilation errors on macOS due to mis-ordered class fields and missing constructors
## [0.5.0]
Released on January 01, 2022.
### Added
#### `bobadump` executable
* New executable for dumping Boba files
* No options; just use `crucible-bobadump BOBA_FILE`
* Prints the schema header (but not the schema entries) and each user header
#### `core` library
* New formatter for primitive integer types called `format_integral()`
* Will work on anything for which `std::is_integral` evaluates to `true`
* New abstract method in `AbstractError` called `describe()`
* In contrast to `format()`, which is intended for developers, `describe()` is intended for end users
* `either::Either` got new methods `bind_lhs()` and `bind_rhs()`
* Maps a value to a whole new `Either` instance
* This is in contrast to `map_lhs()` and `map_rhs()`, which map a value to another value
* Can be used to chain `Either`-returning functions together
#### `os` library
* New library for abstracting over "operating-system-y" things
* Automatically switches between `unix` and `windows` as a backend depending on the compilation target
* The `fs` namespace has platform-agnostic wrapper functions for all of the utilities in `unix::fs` and `windows::fs`
#### Build system
* Support for Python test drivers via `add_crucible_python_test()` (intended mainly for testing executables)
#### General
* Added information about Python tests to the readme
* Added information about supported compilation targets to the readme
### Changed
#### `bobadump` executable
* Renamed from `boba-dump` to just `bobadump`
#### `core` library
* `either::LHS` and `either::RHS` renamed to `either::Lhs` and `either::Rhs` for readability
#### `os` library
* The Windows implementation of the `fs` namespace now uses the `bind_lhs()` and `bind_rhs()` APIs of `core::either::Either`
#### Build system
* Silenced the message from `find_package`, which could be really long and was basically just noise
#### General
* All uses of `Result` have been changed to `Either` to remove duplicated code
* Better end-user error messages across the board
* Uses of "Boba" as a word standardized on camel-case, not uppercase (`BOBA`) or lowercase (`boba`)
### Removed
* The `core::result` namespace has been completely removed; use `core::either` instead
### Fixed
#### `parsing` library
* Compilation error on MSVC due to signed/unsigned comparison mismatch
#### `unix` library
* Errors now have their details reported properly (we see the `errno` message)
#### `windows` library
* Errors now have their details reported properly (we see the `GetLastError()` message)
## [0.4.0]
Released on December 04, 2021.
### Added
#### New libraries
* `boba`, the reference implementation of the BOBA (Bunch Of Big Arrays) file format
#### `boba` library
* The new `errors` namespace:
* The main error class `BobaError`
* The `ParsingFailed` error variant for when loading a BOBA container fails
* A type alias `BobaResult` for `core::result::Result`
* The new `metadata` namespace:
* A POD type called `Header` for keeping the (almost) raw information about each block header
* A type called `Schema` that wraps the very first `Header` of a container, providing information about the rest of the contents
* A type called `Container` that holds all block headers and provides iterator access to them, as well as the schema
* A function called `from_bytes()` which deserializes a byte stream into a `Container`
#### `core` library
* The `format` namespace:
* Lots of functions for formatting anything you can think of: STL containers, plain arrays, C strings, pointers...
* A `format_anything()` function which intelligently selects a formatter based on a compile-time type check
* Lots of new `ASSERT` macros, for parity with the `EXPECT` API
* The `errors` namespace:
* An abstract base class called `AbstractError`, intended to be used for the `Failure` alternative of `Result` instances
* Support for `std::tuple` in `format::format_anything()`
* `constexpr` comparison operators for `none::None`
#### `parsing` library
* A new combinator called `SequenceOf`
* Used to parse an exact number of repetitions of a single structure
* Fails if there aren't enough occurrences (but it's fine to have more)
* Has an associated error called `SequenceOfError`
* The `errors` namespace:
* Error variants `AmbiguousMatch`, `UnexpectedInput`, and `UnexpectedEndOfInput`
* The main error class `ParsingError` and a `Result` alias named `ParsingResult`
* A new combinator called `Tuple`
* Used to parse a heterogeneous sequence of substructures
* No combinator operator; use `combinators::make_tuple()`
* New factory functions for each combinator: `make_one_of()`, `make_pair()`, `make_into()`, and `make_sequence_of()`
#### `unix` library
* The `errors` namespace:
* The `HostError` type, which is moved from the old `errno_error::ErrnoError` type
* Error variants moved from the `fs` namespace
* The main error class `UnixError` and a `Result` alias named `UnixError`
#### `windows` library
* The `errors` namespace:
* The `HostError`, which is moved from the old `windows_error::WindowsError` type
* Error variants moved from the `fs` and `transcoding` namespaces
* The main error class `WindowsError` and a `Result` alias named `WindowsResult`
#### `testing` library
* Self tests (at least, for the parts that can be isolated and tested!)
### Changed
* `ASSERT`, `EXPECT`, and `Result` now use the `format_anything()` function to render objects
* All error handling is now done using a combination of `core::errors::AbstractError` and `core::result::Result`
* Each library now has an `errors` namespace in which it defines its own specializations of these types
#### `core` library
* `none::None` now formats as `"None"` instead of `"None {}"`
#### `parsing` library
* `AndThen` combinator renamed to `Pair` (as a special case of `Tuple`)
### Removed
* `ASSERT_NOT_NULL` is gone; use `ASSERT_NE(thing, nullptr)`
* The `parsing::result`, `unix::errno_error`, and `windows::windows_error` namespaces are all gone
* See the `errors` namespaces in each library for a standardized replacement
## [0.3.0]
Released on November 06, 2021.
### Added
#### `core` library
* A new namespace called `assert`, containing functions for implementing the `ASSERT` macro family
* In the `assert` namespace:
* A pair of new macros called `ASSERT` and `ASSERT_NOT_NULL`, which terminate the program with a message if the assertion does not pass
* A template function called `fail`, which implements the assertion failure mechanism
* A new namespace called `either`, containing the `Either` type for holding one of two types of value
* In the `either` namespace:
* A tag type called `PreventSelectionForCopyAndMove` used internally
* A pair of templates called `LHS` and `RHS` which distinguish the alternatives of an `Either`
* A template called `Either` which can hold one of two values, which can have different types
* A pair of functions called `make_lhs()` and `make_rhs()`, which can be used to create `LHS` and `RHS` instances to pass to an `Either`
#### `parsing` library
* In the `bits` namespace:
* A new parser called `SizedByteSequence` which extracts a specific number of bytes from the input
* In the `combinators` namespace:
* A new combinator called `Into`, which functions like `AndThen` but dynamically constructs the second parser based on the result of the first parser
* Two new errors called `AndThenError` and `IntoError`, which serve as error types for the `AndThen` and `Into` combinators
* In the `combinators::operators` namespace:
* An overloaded `>>` operator, which builds `Into` instances from a parser and a function
#### `testing` library
* In the `expect` namespace:
* A pair of new macros called `EXPECT_CONTAINER_EQ` and `EXPECT_CONTAINER_NE`, which check for (in)equality between two iterables
* In the `abstract_reporter` namespace:
* The `AbstractReporter` class now has default do-nothing implementations for all of its virtual methods
* Two new hook methods for `AbstractReporter`: `handle_group_start()` and `handle_group_end()`, which get the name of the group
* In the `reporter` namespace:
* Forwarding methods for the `handle_group_start()` and `handle_group_end()` hooks
* In the `console_reporter` namespace:
* An implementation of `handle_group_start` that prints the group name
### Changed
#### `testing` library
* Scenarios and fixtures now both accept a tag argument before the name, which groups the fixtures and scenarios together
* Tags can be filtered on the command line with the `-t` or `--tag` option
* Fixtures will only be run for the scenarios that have the same tag
* `BeforeAll` and `AfterAll` fixtures will only run if their tag isn't being filtered out
* Output rendering is much clearer
* A count of total scenarios run is now printed
* Fixtures are now printed at the same level as scenarios instead of inside them
* Fixtures receive a pass/fail note (when they would be printed anyways)
* Added icons for each keyword to make distinguishing them a little clearer
* Removed all white and bright white to make reading output on a white background easier
* "Tags" renamed to "Groups"
* The option in the CLI runner has been changed from `-t/--tag` to `-g/--group`
* Groups are now used as "containers" for scenarios
* There are now two loops: one over each group, and another over each scenario within the group
* `BeforeAll` and `AfterAll` fixtures now run only within their group, not at the start or end of the whole suite
* The console reporter will show groups as the main heading now, with scenarios and fixtures underneath
#### `unix` library
* `test_fs` now uses the fixture mechanism to create and delete its file structure
#### General
* Turned all instances of `std::u8string`, `std::u8string_view`, `char8_t`, and `u8""` literals back into their legacy versions due to bad support
* Standardized constructor syntax (`{}` unless `()` is semantically required)
#### `parsing` library
* The `bits::ByteSequence` and `text::CharacterSequence` parsers now make a deep copy of their sequences
* The `bits::ByteSequence` parser has been renamed to `bits::ExactByteSequence`
### Fixed
* Compilation error on AppleClang: `no viable constructor or deduction guide` in `core::assert::fail()`
## [0.2.0]
Released on October 02, 2021.
### Added
#### New libraries
* `vm` library for the virtual machine implementation
* `parsing` library for parser combinators
#### `parsing` library features
* `bits` namespace containing primitives for parsing binary data
* `FixedWidthUnsignedIntegerType` concept, which constrains to one of the `std::uintN_t` types
* `ByteSequenceMismatch` basic error type
* `UnexpectedEndOfInput` basic error type
* `BitsError` composite error type
* `BitsState` type specialized for binary data
* `ByteSequence` parser which matches an exact sequence of bytes
* `LittleEndianUnsignedInteger` parser template
* `BigEndianUnsignedInteger` parser template
* `combinators` namespace containing types for combining simple parsers into more complex parsers
* `BothMatch` error template
* `NeitherMatch` error template
* `OneOfError` composite error type
* `OneOf` parser combinator, which matches exclusively one or the other of the child parsers
* `AndThen` parser combinator, which matches one parser followed by another parser and returns both results
* `operators` namespace containing tools for building combinator trees
* `operator^`, which combines two parsers using the `OneOf` combinator
* `operator&`, which combines two parsers using the `AndThen` combinator
* `result` namespace containing utility types for the outcomes of individual parsers
* `Reject` template for holding information about a rejected parse
* `Accept` template for holding information about an accepted parse
* `reject` function for building a `Reject` wrapped in a `core::result::Failure`
* `accept` function for building an `Accept` wrapped in a `core::result::Success`
* `text` namespace containing primitives for parsing UTF-8 data
* `CharacterSequenceMismatch` basic error type
* `TextError` composite error type
* `TextState` type specialized for UTF-8 data
* `CharacterSequence` parser which matches an exact sequence of characters
#### `testing` library features
* New namespace: `fixture` for types related to test fixtures
* In the `fixture` namespace:
* `FixtureFunction` alias for the type of a fixture function
* `FixtureVariant` template type which serves as a base class for each kind of fixture
* `BeforeAll`, `AfterAll`, `BeforeEach`, and `AfterEach` tag types which differentiate each kind of fixture
* The `Fixture` type itself, which abstracts over all of these details
* In the `FixtureVariant` type:
* A constructor accepting a `FixtureFunction`
* A getter method called `get_name()` which returns the name of the fixture variant based on which derived class calls it
* A method named `execute()` which runs the fixture and returns an outcome, just like a scenario
* In the `BeforeAll`, `AfterAll`, `BeforeEach`, and `AfterEach` types:
* A constant string field containing the name of the variant for reporting purposes
* In the `Fixture` type:
* A constructor which accepts a name and a fixture variant
* A template method called `has_variant()` which checks what kind of fixture this is
* A method called `get_variant_name()` which forwards to `get_name()` on the underlying variant
* A getter method called `get_name()` which retrieves the fixture's name
* A method called `execute()` which forwards to `execute()` on the underlying variant
* In the `suite` namespace:
* Four new macros which define fixtures in the same way as scenarios: `BEFORE_ALL`, `AFTER_ALL`, `BEFORE_EACH`, and `AFTER_EACH`
* A new type called `FixtureRegistrar` which is used by the new macros to add fixtures to the suite
* In the `FixtureRegistrar` type:
* A constructor that forwards to `add_fixture()` on the suite
* In the `Suite` singleton:
* A method called `add_fixture()` which registers a new fixture in the suite
* In `reporter::Reporter`, `abstract_reporter::AbstractReporter`, and `console_reporter::ConsoleReporter`:
* Two new methods called `handle_fixture_start()` and `handle_fixture_end()` which are called before and after each fixture
* Another new method called `set_show_fixtures()` which toggles how much information is reported about fixtures
* In the `expect` namespace:
* A new template function called `fail_comparison()`, which is exactly like `fail()` but formats its output specifically as a comparison failure
### Changed
#### Build system
* Upgrade the C++ version to C++20
* Renamed the `test` library to `testing` to better fit with other library names (specifically `parsing`)
#### `testing` library features
* Print a special message when there are no tests in a test suite
* Tests can now accept a `--show-fixtures` argument on the command line which causes the reporter to print more information about which fixtures run and when
* The `SCENARIO` macro and `ScenarioRegistrar` type have been moved to the `suite` namespace
* The console reporter will now display a count of total fixture invocations in the suite summary
* All reporters now require a third argument, `fixture_count`, to the `handle_suite_end()` method
* The `EXPECT` family of macros now print much more detailed information when a test fails
* In the `expect` namespace:
* The `fail` function now takes more arguments and has been made into a template based on the type of value being `EXPECT`ed
### Fixed
#### `parsing` library
* Compilation `cast truncates constant value` warning on MSVC
#### `testing` library
* Disallow copying and moving the Suite singleton
* Incorrect include guard symbols
* Compilation warning on AppleClang: `[[nodiscard]]` on a function returning `void`
#### Build system
* Give a nice message from CMake instead of weird errors when trying to build for non-64-bit systems
## [0.1.0]
Released on September 04, 2021.
### Added
#### New libraries
* `core` library for fundamental types and functions used by everything else
* `test` library for testing infrastructure
* `unix` library for wrapping Unix-like APIs
* `windows` library for wrapping Windows APIs
#### `core` library features
* `core::constant_error` namespace, containing a `ConstantError` template for errors with a constant message
* `core::error_chain` namespace, containing the `ErrorChain` class for building complex error types
* `core::none` namespace, containing the `None` type to use as a placeholder
* `core::resource_warden` namespace, containing a class template for cleaning up raw resources on scope exit
* `core::result` namespace, containing facilities for operations that can fail
#### `test` library features
* `test::abstract_reporter` namespace, containing the `AbstractReporter` interface
* `test::cli` namespace, containing a function `execute()` that can be called from `main()`
* `test::console_reporter` namespace, containing a reporter that writes to stdout
* `test::expect` namespace, containing macros to express test assertions
* `test::outcome` namespace, containing types representing scenario outcomes
* `test::reporter` namespace, containing factories for specific reporters and also a wrapper type
* `test::scenario` namespace, containing the `Scenario` type for representing a single test scenario
* `test::suite` namespace, containing the `Suite` singleton used to hold all of the tests in a suite
#### `unix` library features
* `unix::errno_error` namespace, containing utilities for working with `errno`
* `unix::fs` namespace, containing wrappers for filesystem APIs on Unix-like systems
#### `windows` library features
* `windows::fs` namespace, containing wrappers for filesystem APIs on Windows
* `windows::transcoding` namespace, containing functions for transcoding UTF8 with UTF16 for Windows APIs
* `windows::windows_error` namespace, containing functions and a type for reading and formatting Windows errors
#### Build system features
* `AddCrucibleExecutable` module, which provides a wrapper for `add_executable()`
* `AddCrucibleLibrary` module, which provides a wrapper for `add_library()`
* `AddCrucibleTest` module, which provides a wrapper for `add_test()`
* `EnableCompilerWarnings` module, which provides a function that enables common compiler warning flags
* `EnableRuntimeSanitizers` module, which provides a function that enables ASAN, TSAN, and UBSAN based on options
* Write all final build outputs (executables and libraries) to `${PROJECT_BINARY_DIR}/artifacts`
* Automatically export all symbols from all libraries when building Windows DLLs
#### Repository features
* Build dependencies in the README
* Build instructions in the README
* Test instructions in the README
* Attribution in the README
[Unreleased]: https://afterlight.dev/git/crucible.git
[0.8.0]: https://afterlight.dev/git/crucible.git
[0.7.0]: https://gitlab.com/bravelytyped/crucible/-/tree/v0.7.0
[0.6.0]: https://gitlab.com/bravelytyped/crucible/-/tree/v0.6.0
[0.5.0]: https://gitlab.com/bravelytyped/crucible/-/tree/v0.5.0
[0.4.0]: https://gitlab.com/bravelytyped/crucible/-/tree/v0.4.0
[0.3.0]: https://gitlab.com/bravelytyped/crucible/-/tree/v0.3.0
[0.2.0]: https://gitlab.com/bravelytyped/crucible/-/tree/v0.2.0
[0.1.0]: https://gitlab.com/bravelytyped/crucible/-/tree/v0.1.0
[`C4180`]: https://docs.microsoft.com/en-us/cpp/error-messages/compiler-warnings/compiler-warning-level-1-c4180?view=msvc-170