diff --git a/.github/workflows/build_run_unit_test_cmake.yml b/.github/workflows/build_run_unit_test_cmake.yml
index 5f68d1a..311762a 100644
--- a/.github/workflows/build_run_unit_test_cmake.yml
+++ b/.github/workflows/build_run_unit_test_cmake.yml
@@ -12,8 +12,8 @@ jobs:
   build_matrix:
     strategy:
       matrix:
-        # os: [ubuntu-latest, windows-latest, macos-14]
-        os: [ubuntu-latest]
+        os: [ubuntu-latest, windows-latest, macos-14]
+        # os: [ubuntu-latest, windows-latest]
     runs-on: ${{ matrix.os }}
     defaults:
       run:
diff --git a/README.md b/README.md
index 93231e2..9a1bbad 100644
--- a/README.md
+++ b/README.md
@@ -10,6 +10,8 @@
 
 ![GH Tag](https://img.shields.io/github/v/tag/connectivecpp/shared-buffer?label=GH%20tag)
 
+![License](https://img.shields.io/badge/License-Boost%201.0-blue)
+
 ## Overview
 
 The `shared_buffer` classes are reference counted `std::byte` buffer classes useful for asynchronous networking. In particular, the Asio asynchronous networking library requires a buffer to be kept alive and valid until the outstanding IO operation (e.g. a network write) is completed. A straightforward and idiomatic way to achieve this is by using reference counted buffers.
@@ -40,7 +42,7 @@ The unit test code uses [Catch2](https://github.com/catchorg/Catch2). If the `SH
 
 The unit test uses utilities from Connective C++'s [utility-rack](https://github.com/connectivecpp/utility-rack).
 
-Specific version (or branch) specs for the dependenies are in `test/CMakeLists.txt`.
+Specific version (or branch) specs for the dependencies are in the [test/CMakeLists.txt](test/CMakeLists.txt) file, look for the `CPMAddPackage` commands.
 
 ## Build and Run Unit Tests
 
diff --git a/include/buffer/shared_buffer.hpp b/include/buffer/shared_buffer.hpp
index ad200fc..3a2f095 100644
--- a/include/buffer/shared_buffer.hpp
+++ b/include/buffer/shared_buffer.hpp
@@ -81,12 +81,12 @@
 #include <span>
 
 #include <utility> // std::move, std::swap
-#include <cstring> // std::memcpy
+#include <algorithm> // std::copy
 
-// TODO - add conecepts and / or requires
+// TODO - add concepts and / or requires
 //
 // modify the templated constructor that takes a buffer of any valid 
-// byte type, add constraints; this makes the "reinterpret_cast" safe
+// byte type, add constraints which makes the casting safer
 
 namespace chops {
 
@@ -147,6 +147,34 @@ class mutable_shared_buffer {
   mutable_shared_buffer() noexcept : 
       m_data{std::make_shared<byte_vec>(size_type(0))} { }
 
+/**
+ * @brief Construct by copying from a @c std::span of @c std::byte.
+ *
+ * @param sp @c std::byte span pointing to buffer of data. The data is
+ * copied into the internal buffer of the @c mutable_shared_buffer. 
+ *
+ */
+  template <std::size_t Ext>
+  explicit mutable_shared_buffer(std::span<const std::byte, Ext> sp) : 
+      m_data{std::make_shared<byte_vec>(sp.data(), sp.data()+sp.size())} { }
+
+/**
+ * @brief Construct by copying from a @c std::byte array.
+ *
+ * A @c std::span is first created, then the constructor taking
+ * a @c std::span is called.
+ *
+ * @pre Size cannot be greater than the source buffer.
+ *
+ * @param buf Non-null pointer to a @c std::byte buffer of data. The 
+ * data is copied into the internal buffer of the @c mutable_shared_buffer.
+ *
+ * @param sz Size of buffer.
+ *
+ */
+  mutable_shared_buffer(const std::byte* buf, std::size_t sz) : 
+      mutable_shared_buffer(std::as_bytes(std::span<const std::byte>{buf, sz})) { }
+
 /**
  * @brief Move construct from a @c std::vector of @c std::bytes.
  *
@@ -161,9 +189,10 @@ class mutable_shared_buffer {
       m_data{std::make_shared<byte_vec>(size_type(0))} {
     *m_data = std::move(bv);
   }
+
 /**
  * @brief Construct a @c mutable_shared_buffer with an initial size, contents
- * set to zero.
+ * of each byte set to zero.
  *
  * Allocate zero initialized space which can be overwritten with data as needed.
  * The @c data method is called to get access to the underlying @c std::byte 
@@ -171,35 +200,23 @@ class mutable_shared_buffer {
  *
  * @param sz Size for internal @c std::byte buffer.
  */
-  explicit mutable_shared_buffer(size_type sz) noexcept : 
+  explicit mutable_shared_buffer(size_type sz) : 
       m_data{std::make_shared<byte_vec>(sz)} { }
 
-/**
- * @brief Construct by copying from a @c std::span of @c std::byte.
- *
- * @param sp @c std::byte span pointing to buffer of data. The data is
- * copied into the internal buffer of the @c mutable_shared_buffer. 
- *
- */
-  mutable_shared_buffer(std::span<const std::byte> sp) noexcept : 
-      m_data{std::make_shared<byte_vec>(sp.data(), sp.data()+sp.size())} { }
 
 /**
- * @brief Construct by copying from a @c std::byte array.
- *
- * A @c std::span is first created, then the constructor taking
- * a @c std::span is called.
+ * @brief Construct by copying bytes from a @c std::span.
  *
- * @pre Size cannot be greater than the source buffer.
- *
- * @param buf @c std::byte array containing buffer of data. The data is
- * copied into the internal buffer of the @c mutable_shared_buffer.
+ * The type of the span must be convertible to or be layout compatible with
+ * @c std::byte.
  *
- * @param sz Size of buffer.
+ * @param sp @c std::span pointing to buffer of data. The @c std::span 
+ * pointer is cast into a @c std::byte pointer and bytes are then copied. 
  *
  */
-  mutable_shared_buffer(const std::byte* buf, size_type sz) noexcept : 
-      mutable_shared_buffer(std::span<const std::byte>(buf, sz)) { }
+  template <typename T, std::size_t Ext>
+  mutable_shared_buffer(std::span<const T, Ext> sp) : 
+      mutable_shared_buffer(std::as_bytes(sp)) { }
 
 /**
  * @brief Construct by copying bytes from an arbitrary pointer.
@@ -210,14 +227,13 @@ class mutable_shared_buffer {
  *
  * @pre Size cannot be greater than the source buffer.
  *
- * @param buf Pointer to a buffer of data. The pointer must be convertible 
- * to a @c void pointer and then to a @c std::byte pointer.
+ * @param buf Non-null pointer to a buffer of data. 
  *
  * @param sz Size of buffer, in bytes.
  */
   template <typename T>
   mutable_shared_buffer(const T* buf, size_type sz) : 
-      mutable_shared_buffer(reinterpret_cast<const std::byte *>(buf), sz) { }
+      mutable_shared_buffer(std::as_bytes(std::span<const T>{buf, sz})) { }
 
 /**
  * @brief Construct from input iterators.
@@ -256,23 +272,23 @@ class mutable_shared_buffer {
   const std::byte* data() const noexcept { return m_data->data(); }
 
 /**
- * @brief Return access to underlying @c std::vector.
- *
- * This can be used to instantiate a dynamic_buffer as defined in the Networking TS.
- * Changing the @c std::vector from outside this class works because no state
- * data is stored within this object that needs to be consistent with the @c std::vector
- * contents.
+ * @brief Return size (number of bytes) of buffer.
  *
- * @return Reference to @c std::vector<std::byte>.
+ * @return Size of buffer, which may be zero.
  */
-  byte_vec& get_byte_vec() noexcept { return *m_data; }
+  size_type size() const noexcept { return m_data->size(); }
 
 /**
- * @brief Return size (number of bytes) of buffer.
+ * @brief Return access to underlying @c std::vector.
  *
- * @return Size of buffer, which may be zero.
+ * This can be used to instantiate a @c dynamic_buffer as defined in the Networking TS
+ * or Asio API. Changing the @c std::vector from outside this class works because no 
+ * state data is stored within this object that needs to be consistent with the 
+ * @c std::vector contents.
+ *
+ * @return Reference to @c std::vector<std::byte>.
  */
-  size_type size() const noexcept { return m_data->size(); }
+  byte_vec& get_byte_vec() noexcept { return *m_data; }
 
 /**
  * @brief Query to see if size is zero.
@@ -315,19 +331,31 @@ class mutable_shared_buffer {
 /**
  * @brief Append a @c std::byte buffer to the end of the internal buffer.
  *
- * @param buf @c std::byte array containing buffer of data.
+ * @param buf Non-null pointer to @c std::byte buffer of data.
  *
  * @param sz Size of buffer.
  *
  * @return Reference to @c this (to allow method chaining).
  */
-  mutable_shared_buffer& append(const std::byte* buf, size_type sz) {
+  mutable_shared_buffer& append(const std::byte* buf, std::size_t sz) {
     size_type old_sz = size();
     resize(old_sz + sz); // set up buffer space
-    std::memcpy(data() + old_sz, buf, sz);
+    std::copy(buf, buf+sz, data()+old_sz);
     return *this;
   }
 
+/**
+ * @brief Append a @c std::span to the end of the internal buffer.
+ *
+ * @param sp @c std::span of @c std::byte data.
+ *
+ * @return Reference to @c this (to allow method chaining).
+ */
+  template <std::size_t Ext>
+  mutable_shared_buffer& append(std::span<const std::byte, Ext> sp) {
+    return append(sp.data(), sp.size());
+  }
+
 /**
  * @brief Append by copying bytes from an arbitrary pointer.
  *
@@ -335,14 +363,31 @@ class mutable_shared_buffer {
  * are then copied. In particular, this method can be used for @c char pointers, 
  * @c void pointers, @ unsigned @c char pointers, etc.
  *
- * @param buf Pointer to a buffer of data. The pointer must be convertible 
- * to a @c void pointer and then to a @c std::byte pointer.
+ * @param buf Non-null pointer to a buffer of data.
  *
  * @param sz Size of buffer, in bytes.
  */
   template <typename T>
-  mutable_shared_buffer& append(const T* buf, size_type sz) {
-    return append(reinterpret_cast<const std::byte *>(buf), sz);
+  mutable_shared_buffer& append(const T* buf, std::size_t sz) {
+    return append(std::as_bytes(std::span<const T>{buf, sz}));
+  }
+
+/**
+ * @brief Append a @c std::span that is a non @c std::byte buffer.
+ *
+ * The @c std::span passed into this method is performs a cast on the
+ * data. In particular, this method can be used for @c char pointers, 
+ * @c void pointers, @ unsigned @c char pointers, etc.
+ *
+ * The type of the span must be convertible to or be layout compatible with
+ * @c std::byte.
+ *
+ * @param sp @c std::span of arbitrary bytes.
+ *
+ */
+  template <typename T, std::size_t Ext>
+  mutable_shared_buffer& append(std::span<const T, Ext> sp) {
+    return append(std::as_bytes(sp));
   }
 
 /**
@@ -463,19 +508,42 @@ class const_shared_buffer {
   const_shared_buffer& operator=(const const_shared_buffer&) = delete;
   const_shared_buffer& operator=(const_shared_buffer&&) = delete;
 
+/**
+ * @brief Construct by copying from a @c std::span of @c std::byte.
+ *
+ * @param sp @c std::byte span pointing to buffer of data. The data is
+ * copied into the internal buffer of the @c const_shared_buffer. 
+ *
+ */
+  template <std::size_t Ext>
+  explicit const_shared_buffer(std::span<const std::byte, Ext> sp) : 
+      m_data(std::make_shared<byte_vec>(sp.data(), sp.data()+sp.size())) { }
 /**
  * @brief Construct by copying from a @c std::byte array.
  *
  * @pre Size cannot be greater than the source buffer.
  *
- * @param buf @c std::byte array containing buffer of data. The data is
+ * @param buf Non-null pointer to @c std::byte buffer of data. The data is
  * copied into the internal buffer of the @c const_shared_buffer.
  *
  * @param sz Size of buffer.
  */
-  const_shared_buffer(const std::byte* buf, size_type sz) : 
-      m_data(std::make_shared<byte_vec>(buf, buf+sz)) { }
+  const_shared_buffer(const std::byte* buf, std::size_t sz) : 
+      const_shared_buffer(std::as_bytes(std::span<const std::byte>{buf, sz})) { }
 
+/**
+ * @brief Construct by copying from a @c std::span.
+ *
+ * The type of the span must be convertible to or be layout compatible with
+ * @c std::byte.
+ *
+ * @param sp @c std::span pointing to buffer of data. The @c std::span 
+ * pointer is cast into a @c std::byte pointer and bytes are then copied. 
+ *
+ */
+  template <typename T, std::size_t Ext>
+  const_shared_buffer(std::span<const T, Ext> sp) : 
+      const_shared_buffer(std::as_bytes(sp)) { }
 /**
  * @brief Construct by copying bytes from an arbitrary pointer.
  *
@@ -483,16 +551,18 @@ class const_shared_buffer {
  * are then copied. In particular, this method can be used for @c char pointers, 
  * @c void pointers, @c unsigned @c char pointers, etc.
  *
+ * The type of the span must be convertible to or be layout compatible with
+ * @c std::byte.
+ *
  * @pre Size cannot be greater than the source buffer.
  *
- * @param buf Pointer to a buffer of data. The pointer must be convertible 
- * to a @c void pointer and then to a @c std::byte pointer.
+ * @param buf Non-null pointer to a buffer of data. 
  *
  * @param sz Size of buffer, in bytes.
  */
   template <typename T>
-  const_shared_buffer(const T* buf, size_type sz) : 
-      const_shared_buffer(reinterpret_cast<const std::byte *>(buf), sz) { }
+  const_shared_buffer(const T* buf, std::size_t sz) : 
+      const_shared_buffer(std::as_bytes(std::span<const T>{buf, sz})) { }
 
 /**
  * @brief Construct by copying from a @c mutable_shared_buffer object.
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 8f9b073..5a72e14 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -15,8 +15,8 @@ target_compile_features ( shared_buffer_test PRIVATE cxx_std_20 )
 # add dependencies
 include ( ../cmake/download_cpm.cmake )
 
-CPMAddPackage ( "gh:catchorg/Catch2@3.6.0" )
-CPMAddPackage ( "gh:connectivecpp/utility-rack@1.0.0" )
+CPMAddPackage ( "gh:catchorg/Catch2@3.7.0" )
+CPMAddPackage ( "gh:connectivecpp/utility-rack@1.0.3" )
 
 # link dependencies
 target_link_libraries ( shared_buffer_test PRIVATE shared_buffer utility_rack Catch2::Catch2WithMain )
diff --git a/test/shared_buffer_test.cpp b/test/shared_buffer_test.cpp
index d1445db..4776df7 100644
--- a/test/shared_buffer_test.cpp
+++ b/test/shared_buffer_test.cpp
@@ -20,62 +20,125 @@
 #include <list>
 #include <string_view>
 #include <span>
+#include <array>
+#include <algorithm> // std::copy
+#include <bit> // std::bit_cast
 
 #include "buffer/shared_buffer.hpp"
 
 #include "utility/repeat.hpp"
-#include "utility/make_byte_array.hpp"
+#include "utility/byte_array.hpp"
 
-constexpr std::byte Harhar { 42 };
-constexpr int N = 11;
+constexpr std::size_t test_data_size { 12u };
+using test_data_type = std::array<std::byte, test_data_size>;
+constexpr test_data_type test_data { chops::make_byte_array( 40, 41, 42, 43, 44, 60, 59, 58, 57, 56, 42, 42 ) };
+char test_data_char[test_data_size] { 40, 41, 42, 43, 44, 60, 59, 58, 57, 56, 42, 42 };
+const char* test_data_char_ptr {test_data_char};
 
+template <typename SB>
+bool check_sb_against_test_data(SB sb) {
+  REQUIRE (sb.size() == test_data_size);
+  test_data_type buf;
+  std::copy(sb.data(), sb.data()+sb.size(), buf.begin());
+  return chops::compare_byte_arrays(buf, test_data);
+}
 
 template <typename SB, typename PT>
-void generic_pointer_construction_test() {
-  auto arr = chops::make_byte_array( 40, 41, 42, 43, 44, 60, 59, 58, 57, 56, 42, 42 );
-  const PT* ptr = reinterpret_cast<const PT *>(arr.data());
-  SB sb(ptr, arr.size());
+SB generic_pointer_construction_test() {
+  auto ptr { std::bit_cast<const PT *>(test_data.data()) };
+  SB sb(ptr, test_data_size);
   REQUIRE_FALSE (sb.empty());
-  chops::repeat(static_cast<int>(arr.size()), [&sb, arr] (int i) { REQUIRE(*(sb.data()+i) == arr[i]); } );
+  REQUIRE (check_sb_against_test_data(sb));
+  return sb;
+}
+
+template <typename PT>
+void generic_pointer_append_test() {
+  auto sb { generic_pointer_construction_test<chops::mutable_shared_buffer, PT>() };
+  auto sav_sz { sb.size() };
+  const PT arr[] { 5, 6, 7 };
+  const PT* ptr_arr { arr };
+  sb.append (ptr_arr, 3);
+  REQUIRE (sb.size() == (sav_sz + 3));
+  std::span<const PT, 3> sp { arr };
+  sb.append (sp);
+  REQUIRE (sb.size() == (sav_sz + 6));
 }
 
 template <typename SB>
-void common_methods_test(const std::byte* buf, typename SB::size_type sz) {
+void check_sb(SB sb) {
+  REQUIRE_FALSE (sb.empty());
+  REQUIRE (sb.size() == test_data_size);
+  REQUIRE (check_sb_against_test_data(sb));
+}
 
-  REQUIRE (sz > 2);
+template <typename SB>
+void common_ctor_test() {
 
-  SB sb(buf, sz);
-  REQUIRE_FALSE (sb.empty());
   {
-    SB sb2(buf, sz);
-    REQUIRE_FALSE (sb2.empty());
-    REQUIRE (sb == sb2);
+    std::span<const std::byte, test_data_size> sp { test_data };
+    SB sb{sp};
+    check_sb(sb);
   }
   {
-    std::list<std::byte> lst (buf, buf+sz);
-    SB sb2(lst.cbegin(), lst.cend());
-    REQUIRE_FALSE (sb2.empty());
-    REQUIRE (sb == sb2);
+    std::span<const std::byte> sp { test_data.data(), test_data.size() };
+    SB sb{sp};
+    check_sb(sb);
+  }
+  {
+    SB sb{test_data.data(), test_data.size()};
+    check_sb(sb);
+  }
+  {
+    std::span<const char, test_data_size> sp { test_data_char };
+    SB sb{sp};
+    check_sb(sb);
+  }
+  {
+    std::span<const char> sp { test_data_char, test_data_char+test_data_size };
+    SB sb{sp};
+    check_sb(sb);
   }
   {
-    auto ba = chops::make_byte_array(buf[0], buf[1]);
-    SB sb2(ba.cbegin(), ba.cend());
-    REQUIRE_FALSE (sb2.empty());
-    REQUIRE (((sb2 < sb) != 0)); // uses spaceship operator
-    REQUIRE (sb2 != sb);
+    SB sb{test_data_char_ptr, test_data_size};
+    check_sb(sb);
+  }
+
+  {
+    std::list<std::byte> lst {test_data.cbegin(), test_data.cend()};
+    SB sb {lst.cbegin(), lst.cend()};
+    check_sb(sb);
+  }
+  {
+    SB sb1{test_data.data(), test_data.size()};
+    SB sb2{test_data.data(), test_data.size()};
+    REQUIRE (sb1 == sb2);
   }
   {
-    auto ba = chops::make_byte_array(0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
-    SB sb2(ba.cbegin(), ba.cend());
-    REQUIRE_FALSE (sb2.empty());
-    REQUIRE (sb2 != sb);
+    SB sb1{test_data.data(), test_data.size()};
+    SB sb2{sb1};
+    REQUIRE (sb1 == sb2);
   }
+
+}
+
+template <typename SB>
+void common_comparison_test() {
+  auto ba1 { chops::make_byte_array(0x00, 0x00, 0x00) };
+  auto ba2 { chops::make_byte_array(0x00, 0x22, 0x33) };
+
+  SB sb1(ba1.cbegin(), ba1.cend());
+  SB sb2(ba2.cbegin(), ba2.cend());
+  REQUIRE_FALSE (sb1.empty());
+  REQUIRE_FALSE (sb2.empty());
+  REQUIRE_FALSE (sb1 == sb2);
+  REQUIRE (((sb1 < sb2) != 0)); // uses spaceship operator
 }
 
 template <typename SB>
 void byte_vector_move_test() {
 
-  auto arr = chops::make_byte_array (0x01, 0x02, 0x03, 0x04, 0x05);
+  auto arr { chops::make_byte_array (0x01, 0x02, 0x03, 0x04, 0x05) };
 
   std::vector<std::byte> bv { arr.cbegin(), arr.cend() };
   SB sb(std::move(bv));
@@ -83,25 +146,32 @@ void byte_vector_move_test() {
   REQUIRE_FALSE (bv.size() == sb.size());
 }
  
-TEMPLATE_TEST_CASE ( "Checking generic pointer construction",
+TEMPLATE_TEST_CASE ( "Generic pointer construction",
                      "[common]",
-                     char, unsigned char, signed char ) {
+                     char, unsigned char, signed char, std::uint8_t ) {
   generic_pointer_construction_test<chops::mutable_shared_buffer, TestType>();
   generic_pointer_construction_test<chops::const_shared_buffer, TestType>();
 }
 
                      
-TEMPLATE_TEST_CASE ( "Shared buffer common methods test",
-                     "[const_shared_buffer] [common]",
+TEMPLATE_TEST_CASE ( "Shared buffer common ctor methods",
+                     "[const_shared_buffer] [mutable_shared_buffer] [common]",
+                     chops::mutable_shared_buffer, chops::const_shared_buffer ) {
+  common_ctor_test<TestType>();
+}
+
+TEMPLATE_TEST_CASE ( "Shared buffer common comparison methods",
+                     "[const_shared_buffer] [mutable_shared_buffer] [common]",
                      chops::mutable_shared_buffer, chops::const_shared_buffer ) {
-  auto arr = chops::make_byte_array ( 80, 81, 82, 83, 84, 90, 91, 92 );
-  common_methods_test<TestType>(arr.data(), arr.size());
+  common_comparison_test<TestType>();
 }
 
 TEST_CASE ( "Mutable shared buffer copy construction and assignment",
             "[mutable_shared_buffer] [copy]" ) {
 
-  auto arr = chops::make_byte_array ( 80, 81, 82, 83, 84, 90, 91, 92 );
+  constexpr std::byte Harhar { 42 };
+
+  auto arr { chops::make_byte_array ( 80, 81, 82, 83, 84, 90, 91, 92 ) };
 
   chops::mutable_shared_buffer sb;
   REQUIRE (sb.empty());
@@ -122,148 +192,130 @@ TEST_CASE ( "Mutable shared buffer copy construction and assignment",
   }
 }
 
-SCENARIO ( "Mutable shared buffer resize and clear",
-           "[mutable_shared_buffer] [resize_and_clear]" ) {
-
-  GIVEN ("A default constructed mutable shared_buffer") {
-    chops::mutable_shared_buffer sb;
-    WHEN ("Resize is called") {
-      sb.resize(N);
-      THEN ("the internal buffer will have all zeros") {
-        REQUIRE (sb.size() == N);
-        chops::repeat(N, [&sb] (const int& i) { REQUIRE (*(sb.data() + i) == std::byte{0} ); } );
-      }
-    }
-    AND_WHEN ("Another mutable shared buffer with a size is constructed") {
-      sb.resize(N);
-      chops::mutable_shared_buffer sb2(N);
-      THEN ("the two shared buffers compare equal, with all zeros in the buffer") {
-        REQUIRE (sb == sb2);
-        chops::repeat(N, [&sb, &sb2] (const int& i) {
-          REQUIRE (*(sb.data() + i) == std::byte{0} );
-          REQUIRE (*(sb2.data() + i) == std::byte{0} );
-        } );
-      }
-    }
-    AND_WHEN ("The mutable shared buffer is cleared") {
-      sb.resize(N);
-      sb.clear();
-      THEN ("the size will be zero and the buffer is empty") {
-        REQUIRE (sb.size() == 0);
-        REQUIRE (sb.empty());
-      }
-    }
+TEST_CASE ( "Mutable shared buffer resize and clear",
+            "[mutable_shared_buffer] [resize_and_clear]" ) {
+
+  constexpr int N = 11;
+
+  chops::mutable_shared_buffer sb;
+  REQUIRE (sb.empty());
+  REQUIRE (sb.size() == 0);
+
+  sb.resize(N);
+  REQUIRE (sb.size() == N);
+  chops::repeat(N, [&sb] (int i) { REQUIRE (std::to_integer<int>(*(sb.data() + i)) == 0 ); } );
+
+  SECTION ( "Compare two resized mutable shared buffer with same size" ) {
+    chops::mutable_shared_buffer sb2(N);
+    REQUIRE (sb == sb2);
+    chops::repeat(N, [&sb, &sb2] (int i) {
+      REQUIRE (std::to_integer<int>(*(sb.data() + i)) == 0 );
+      REQUIRE (std::to_integer<int>(*(sb2.data() + i)) == 0 );
+    } );
+  }
+  SECTION ( "Clear, check size" ) {
+    sb.clear();
+    REQUIRE (sb.size() == 0);
+    REQUIRE (sb.empty());
   } // end given
 }
 
-SCENARIO ( "Mutable shared buffer swap",
-           "[mutable_shared_buffer] [swap]" ) {
-
-  GIVEN ("Two mutable shared_buffers") {
-    auto arr1 = chops::make_byte_array (0xaa, 0xbb, 0xcc);
-    auto arr2 = chops::make_byte_array (0x01, 0x02, 0x03, 0x04, 0x05);
-
-    chops::mutable_shared_buffer sb1(arr1.cbegin(), arr1.cend());
-    chops::mutable_shared_buffer sb2(arr2.cbegin(), arr2.cend());
-
-    WHEN ("The buffers are swapped") {
-      chops::swap(sb1, sb2);
-      THEN ("the sizes and contents will be swapped") {
-        REQUIRE (sb1.size() == arr2.size());
-        REQUIRE (sb2.size() == arr1.size());
-        REQUIRE (*(sb1.data()+0) == *(arr2.data()+0));
-        REQUIRE (*(sb1.data()+1) == *(arr2.data()+1));
-        REQUIRE (*(sb2.data()+0) == *(arr1.data()+0));
-        REQUIRE (*(sb2.data()+1) == *(arr1.data()+1));
-      }
-    }
-  } // end given
+TEST_CASE ( "Mutable shared buffer swap",
+            "[mutable_shared_buffer] [swap]" ) {
+
+  auto arr1 = chops::make_byte_array (0xaa, 0xbb, 0xcc);
+  auto arr2 = chops::make_byte_array (0x01, 0x02, 0x03, 0x04, 0x05);
+
+  chops::mutable_shared_buffer sb1(arr1.cbegin(), arr1.cend());
+  chops::mutable_shared_buffer sb2(arr2.cbegin(), arr2.cend());
+
+  chops::swap(sb1, sb2);
+  REQUIRE (sb1.size() == arr2.size());
+  REQUIRE (sb2.size() == arr1.size());
+
+  REQUIRE (std::to_integer<int>(*(sb1.data()+0)) == std::to_integer<int>(*(arr2.data()+0)));
+  REQUIRE (std::to_integer<int>(*(sb1.data()+1)) == std::to_integer<int>(*(arr2.data()+1)));
+  REQUIRE (std::to_integer<int>(*(sb1.data()+2)) == std::to_integer<int>(*(arr2.data()+2)));
+  REQUIRE (std::to_integer<int>(*(sb1.data()+3)) == std::to_integer<int>(*(arr2.data()+3)));
+  REQUIRE (std::to_integer<int>(*(sb1.data()+4)) == std::to_integer<int>(*(arr2.data()+4)));
+
+  REQUIRE (std::to_integer<int>(*(sb2.data()+0)) == std::to_integer<int>(*(arr1.data()+0)));
+  REQUIRE (std::to_integer<int>(*(sb2.data()+1)) == std::to_integer<int>(*(arr1.data()+1)));
+  REQUIRE (std::to_integer<int>(*(sb2.data()+2)) == std::to_integer<int>(*(arr1.data()+2)));
 }
 
-SCENARIO ( "Mutable shared buffer append",
-           "[mutable_shared_buffer] [append]" ) {
+TEST_CASE ( "Mutable shared buffer append",
+            "[mutable_shared_buffer] [append]" ) {
 
   auto arr = chops::make_byte_array (0xaa, 0xbb, 0xcc);
   auto arr2 = chops::make_byte_array (0xaa, 0xbb, 0xcc, 0xaa, 0xbb, 0xcc);
   chops::mutable_shared_buffer ta(arr.cbegin(), arr.cend());
   chops::mutable_shared_buffer ta2(arr2.cbegin(), arr2.cend());
 
-  GIVEN ("A default constructed mutable shared_buffer") {
-    chops::mutable_shared_buffer sb;
-    WHEN ("Append with a pointer and size is called") {
-      sb.append(arr.data(), arr.size());
-      THEN ("the internal buffer will contain the appended data") {
-        REQUIRE (sb == ta);
-      }
-    }
-    AND_WHEN ("Append with a mutable shared buffer is called") {
-      sb.append(ta);
-      THEN ("the internal buffer will contain the appended data") {
-        REQUIRE (sb == ta);
-      }
-    }
-    AND_WHEN ("Append is called twice") {
-      sb.append(ta);
-      sb.append(ta);
-      THEN ("the internal buffer will contain twice the appended data") {
-        REQUIRE (sb == ta2);
-      }
-    }
-    AND_WHEN ("Appending with single bytes") {
-      sb.append(std::byte(0xaa));
-      sb.append(std::byte(0xbb));
-      sb += std::byte(0xcc);
-      THEN ("the internal buffer will contain the appended data") {
-        REQUIRE (sb == ta);
-      }
-    }
-    AND_WHEN ("Appending with a char* to test templated append") {
-      std::string_view sv("Haha, Bro!");
-      chops::mutable_shared_buffer cb(sv.data(), sv.size());
-      sb.append(sv.data(), sv.size());
-      THEN ("the internal buffer will contain the appended data") {
-        REQUIRE (sb == cb);
-      }
-    }
-  } // end given
+  chops::mutable_shared_buffer sb;
+  REQUIRE (sb.empty());
+
+  SECTION ( "Append array to default constructed mutable shared_buffer" ) {
+    sb.append(arr.data(), arr.size());
+    REQUIRE (sb == ta);
+  }
+
+  SECTION ( "Append mutable shared buffer" ) {
+    sb.append(ta);
+    REQUIRE (sb == ta);
+  }
+
+  SECTION ( "Call append twice" ) {
+    sb.append(ta);
+    sb.append(ta);
+    REQUIRE (sb == ta2);
+  }
+
+  SECTION ( "Append with single byte" ) {
+    sb.append(std::byte(0xaa));
+    sb.append(std::byte(0xbb));
+    sb += std::byte(0xcc);
+    REQUIRE (sb == ta);
+  }
+
+  SECTION ( "Append with templated append" ) {
+    std::string_view sv("Haha, Bro!");
+    chops::mutable_shared_buffer cb(sv.data(), sv.size());
+    sb.append(sv.data(), sv.size());
+    REQUIRE (sb == cb);
+  } 
 }
 
-SCENARIO ( "Compare a mutable shared_buffer with a const shared buffer",
-           "[mutable_shared_buffer] [const_shared_buffer] [compare]" ) {
-
-  GIVEN ("An array of bytes") {
-    auto arr = chops::make_byte_array (0xaa, 0xbb, 0xcc);
-    WHEN ("A mutable_shared_buffer and a const_shared_buffer are created from the bytes") {
-      chops::mutable_shared_buffer msb(arr.cbegin(), arr.cend());
-      chops::const_shared_buffer csb(arr.cbegin(), arr.cend());
-      THEN ("the shared buffers will compare equal") {
-        REQUIRE (msb == csb);
-        REQUIRE (csb == msb);
-      }
-    }
-  } // end given
+TEMPLATE_TEST_CASE ( "Generic pointer append",
+                     "[mutable_shared_buffer] [pointer] [append]",
+                     char, unsigned char, signed char, std::uint8_t ) {
+  generic_pointer_append_test<TestType>();
+}
+
+TEST_CASE ( "Compare a mutable shared_buffer with a const shared buffer",
+            "[mutable_shared_buffer] [const_shared_buffer] [compare]" ) {
+
+  auto arr = chops::make_byte_array (0xaa, 0xbb, 0xcc);
+  chops::mutable_shared_buffer msb(arr.cbegin(), arr.cend());
+  chops::const_shared_buffer csb(arr.cbegin(), arr.cend());
+  REQUIRE (msb == csb);
+  REQUIRE (csb == msb);
 }
 
-SCENARIO ( "Mutable shared buffer move into const shared buffer",
-           "[mutable_shared_buffer] [const_shared_buffer] [move]" ) {
+TEST_CASE ( "Mutable shared buffer move into const shared buffer",
+            "[mutable_shared_buffer] [const_shared_buffer] [move]" ) {
 
   auto arr1 = chops::make_byte_array (0xaa, 0xbb, 0xcc);
   auto arr2 = chops::make_byte_array (0x01, 0x02, 0x03, 0x04, 0x05);
 
-  GIVEN ("A mutable_shared_buffer") {
-    chops::mutable_shared_buffer msb(arr1.cbegin(), arr1.cend());
-    WHEN ("A const_shared_buffer is move constructed from the mutable_shared_buffer") {
-      chops::const_shared_buffer csb(std::move(msb));
-      THEN ("the const_shared_buffer will contain the data and the mutable_shared_buffer will not") {
-        REQUIRE (csb == chops::const_shared_buffer(arr1.cbegin(), arr1.cend()));
-        REQUIRE_FALSE (msb == csb);
-        msb.clear();
-        msb.resize(arr2.size());
-        msb.append(arr2.data(), arr2.size());
-        REQUIRE_FALSE (msb == csb);
-      }
-    }
-  } // end given
+  chops::mutable_shared_buffer msb(arr1.cbegin(), arr1.cend());
+  chops::const_shared_buffer csb(std::move(msb));
+  REQUIRE (csb == chops::const_shared_buffer(arr1.cbegin(), arr1.cend()));
+  REQUIRE_FALSE (msb == csb);
+  msb.clear();
+  msb.resize(arr2.size());
+  msb.append(arr2.data(), arr2.size());
+  REQUIRE_FALSE (msb == csb);
 }
 
 TEMPLATE_TEST_CASE ( "Move a vector of bytes into a shared buffer",
@@ -274,24 +326,21 @@ TEMPLATE_TEST_CASE ( "Move a vector of bytes into a shared buffer",
 
 }
 
-SCENARIO ( "Use get_byte_vec for external modification of buffer",
-           "[mutable_shared_buffer] [get_byte_vec]" ) {
+TEST_CASE ( "Use get_byte_vec for external modification of buffer",
+            "[mutable_shared_buffer] [get_byte_vec]" ) {
 
   auto arr = chops::make_byte_array (0xaa, 0xbb, 0xcc);
   chops::mutable_shared_buffer::byte_vec bv (arr.cbegin(), arr.cend());
 
-  GIVEN ("A mutable_shared_buffer") {
-    chops::mutable_shared_buffer msb(bv.cbegin(), bv.cend());
-
-    WHEN ("get_byte_vec is called") {
-      auto r = msb.get_byte_vec();
-      THEN ("the refererence can be used to access and modify data") {
-        REQUIRE (r == bv);
-        r[0] = std::byte(0xdd);
-        REQUIRE_FALSE (r == bv);
-      }
-    }
-  } // end given
+  chops::mutable_shared_buffer msb(bv.cbegin(), bv.cend());
 
+  auto r = msb.get_byte_vec();
+//  REQUIRE (r == bv); // Catch2 build problems on MSVC
+  std::array<std::byte, 3> arr2 { r[0], r[1], r[2] };
+  REQUIRE (chops::compare_byte_arrays(arr, arr2));
+  r[0] = std::byte(0xdd);
+//  REQUIRE_FALSE (r == bv); // Catch2 build problems on MSVC
+  std::array<std::byte, 3> arr3 { r[0], r[1], r[2] };
+  REQUIRE_FALSE (chops::compare_byte_arrays(arr, arr3));
 }