diff --git a/libcxx/include/string b/libcxx/include/string
--- a/libcxx/include/string
+++ b/libcxx/include/string
@@ -684,6 +684,9 @@
                   "traits_type::char_type must be the same type as CharT");
     static_assert(( is_same<typename allocator_type::value_type, value_type>::value),
                   "Allocator::value_type must be same type as value_type");
+#if _LIBCPP_STD_VER < 20
+    static_assert((is_trivially_destructible<pointer>::value), "pointer type must have a trivial destructor.");
+#endif
 
     typedef __wrap_iter<pointer>                         iterator;
     typedef __wrap_iter<const_pointer>                   const_iterator;
@@ -772,7 +775,20 @@
 
     static_assert(sizeof(__short) == (sizeof(value_type) * (__min_cap + 1)), "__short has an unexpected size.");
 
+#ifdef _LIBCPP_CXX03_LANG
     union __ulx{__long __lx; __short __lxx;};
+#else
+    // Since C++03, unions can contain members with non-trivial special member functions. The corresponding special
+    // member functions of the union will be deleted and therefore must be explicitly defined. To support fancy pointers
+    // with non-trivial constructors in __long, we must explicitly define a constructor in __ulx, as the default
+    // constructor will be deleted.
+    union __ulx {
+      _LIBCPP_CONSTEXPR_SINCE_CXX20 __ulx() _NOEXCEPT : __lx{} {}
+
+      __long __lx;
+      __short __lxx;
+    };
+#endif // _LIBCPP_CXX03_LANG
 
     enum {__n_words = sizeof(__ulx) / sizeof(size_type)};
 
@@ -781,6 +797,7 @@
         size_type __words[__n_words];
     };
 
+#ifdef _LIBCPP_CXX03_LANG
     struct __rep
     {
         union
@@ -790,6 +807,59 @@
             __raw   __r;
         };
     };
+#else
+    // Since C++03, unions can contain members with non-trivial special member functions. The corresponding special
+    // member functions of the union will be deleted and therefore must be explicitly defined. To support fancy pointers
+    // with non-trivial special member functions in __long, we must explicitly define a constructor, copy constructor
+    // and copy assignment operator in __rep. Since C++20, unions can also contain members with non-trivial destructors.
+    struct __rep {
+      _LIBCPP_CONSTEXPR_SINCE_CXX20 __rep() _NOEXCEPT : __l{} {}
+      _LIBCPP_CONSTEXPR_SINCE_CXX20 ~__rep() _NOEXCEPT {}
+
+      _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __is_rep_long(const __rep& __str_rep) const _NOEXCEPT {
+        if (__libcpp_is_constant_evaluated())
+          return true;
+        return __str_rep.__l.__is_long_;
+      }
+
+      _LIBCPP_CONSTEXPR_SINCE_CXX20 __rep(const __rep& __other) _NOEXCEPT : __l{} {
+        // For certain fancy pointers such as offset pointers, the value of __l.__data_ will be different for 2 pointers
+        // pointing to the same object (because the offset is calculated with respect to the pointer itself). Therefore,
+        // the copy assignment operator of the underlying pointer needs to be explicitly called. For a short string, the
+        // memory should be directly copied.
+        if (__is_rep_long(__other)) {
+          __l.__is_long_ = __other.__l.__is_long_;
+          __l.__cap_     = __other.__l.__cap_;
+          __l.__size_    = __other.__l.__size_;
+          __l.__data_    = __other.__l.__data_;
+        } else {
+          for (unsigned __i = 0; __i < __n_words; ++__i)
+            __r.__words[__i] = __other.__r.__words[__i];
+        }
+      }
+
+      _LIBCPP_CONSTEXPR_SINCE_CXX20 __rep& operator=(const __rep& __other) _NOEXCEPT {
+        if (this != &__other) {
+          if (__is_rep_long(__other)) {
+            __l.__is_long_ = __other.__l.__is_long_;
+            __l.__cap_     = __other.__l.__cap_;
+            __l.__size_    = __other.__l.__size_;
+            __l.__data_    = __other.__l.__data_;
+          } else {
+            for (unsigned __i = 0; __i < __n_words; ++__i)
+              __r.__words[__i] = __other.__r.__words[__i];
+          }
+        }
+        return *this;
+      }
+
+      union {
+        __long __l;
+        __short __s;
+        __raw __r;
+      };
+    };
+#endif // _LIBCPP_CXX03_LANG
 
     __compressed_pair<__rep, allocator_type> __r_;
 
diff --git a/libcxx/test/libcxx/strings/basic.string/alignof.compile.pass.cpp b/libcxx/test/libcxx/strings/basic.string/alignof.compile.pass.cpp
--- a/libcxx/test/libcxx/strings/basic.string/alignof.compile.pass.cpp
+++ b/libcxx/test/libcxx/strings/basic.string/alignof.compile.pass.cpp
@@ -44,6 +44,9 @@
 template <class CharT>
 using min_string = std::basic_string<CharT, std::char_traits<CharT>, min_allocator<CharT>>;
 
+template <class CharT>
+using fancy_string = std::basic_string<CharT, std::char_traits<CharT>, fancy_pointer_allocator<CharT>>;
+
 template <class CharT>
 using test_string = std::basic_string<CharT, std::char_traits<CharT>, test_allocator<CharT>>;
 
@@ -54,6 +57,7 @@
 
 static_assert(alignof(std::string) == 8, "");
 static_assert(alignof(min_string<char>) == 8, "");
+static_assert(alignof(fancy_string<char>) == 8, "");
 static_assert(alignof(test_string<char>) == 8, "");
 static_assert(alignof(small_string<char>) == 2, "");
 
@@ -61,11 +65,13 @@
 #    if __WCHAR_WIDTH__ == 32
 static_assert(alignof(std::wstring) == 8, "");
 static_assert(alignof(min_string<wchar_t>) == 8, "");
+static_assert(alignof(fancy_string<wchar_t>) == 8, "");
 static_assert(alignof(test_string<wchar_t>) == 8, "");
 static_assert(alignof(small_string<wchar_t>) == 4, "");
 #    elif __WCHAR_WIDTH__ == 16
 static_assert(alignof(std::wstring) == 8, "");
 static_assert(alignof(min_string<wchar_t>) == 8, "");
+static_assert(alignof(fancy_string<wchar_t>) == 8, "");
 static_assert(alignof(test_string<wchar_t>) == 8, "");
 static_assert(alignof(small_string<wchar_t>) == 2, "");
 #    else
@@ -76,6 +82,7 @@
 #  ifndef TEST_HAS_NO_CHAR8_T
 static_assert(alignof(std::u8string) == 8, "");
 static_assert(alignof(min_string<char8_t>) == 8, "");
+static_assert(alignof(fancy_string<char8_t>) == 8, "");
 static_assert(alignof(test_string<char8_t>) == 8, "");
 static_assert(alignof(small_string<char8_t>) == 2, "");
 #  endif
@@ -85,6 +92,8 @@
 static_assert(alignof(std::u32string) == 8, "");
 static_assert(alignof(min_string<char16_t>) == 8, "");
 static_assert(alignof(min_string<char32_t>) == 8, "");
+static_assert(alignof(fancy_string<char32_t>) == 8, "");
+static_assert(alignof(fancy_string<char32_t>) == 8, "");
 static_assert(alignof(test_string<char16_t>) == 8, "");
 static_assert(alignof(test_string<char32_t>) == 8, "");
 static_assert(alignof(small_string<char16_t>) == 2, "");
@@ -95,6 +104,7 @@
 
 static_assert(alignof(std::string) == 4, "");
 static_assert(alignof(min_string<char>) == 4, "");
+static_assert(alignof(fancy_string<char>) == 4, "");
 static_assert(alignof(test_string<char>) == 4, "");
 static_assert(alignof(small_string<char>) == 2, "");
 
@@ -102,11 +112,13 @@
 #    if __WCHAR_WIDTH__ == 32
 static_assert(alignof(std::wstring) == 4, "");
 static_assert(alignof(min_string<wchar_t>) == 4, "");
+static_assert(alignof(fancy_string<wchar_t>) == 4, "");
 static_assert(alignof(test_string<wchar_t>) == 4, "");
 static_assert(alignof(small_string<wchar_t>) == 4, "");
 #    elif __WCHAR_WIDTH__ == 16
 static_assert(alignof(std::wstring) == 4, "");
 static_assert(alignof(min_string<wchar_t>) == 4, "");
+static_assert(alignof(fancy_string<wchar_t>) == 4, "");
 static_assert(alignof(test_string<wchar_t>) == 4, "");
 static_assert(alignof(small_string<wchar_t>) == 2, "");
 #    else
@@ -117,6 +129,7 @@
 #  ifndef TEST_HAS_NO_CHAR8_T
 static_assert(alignof(std::u8string) == 4, "");
 static_assert(alignof(min_string<char8_t>) == 4, "");
+static_assert(alignof(fancy_string<char8_t>) == 4, "");
 static_assert(alignof(test_string<char8_t>) == 4, "");
 static_assert(alignof(small_string<char8_t>) == 2, "");
 #  endif
@@ -126,6 +139,8 @@
 static_assert(alignof(std::u32string) == 4, "");
 static_assert(alignof(min_string<char16_t>) == 4, "");
 static_assert(alignof(min_string<char32_t>) == 4, "");
+static_assert(alignof(fancy_string<char16_t>) == 4, "");
+static_assert(alignof(fancy_string<char32_t>) == 4, "");
 static_assert(alignof(test_string<char16_t>) == 4, "");
 static_assert(alignof(test_string<char32_t>) == 4, "");
 static_assert(alignof(small_string<char32_t>) == 4, "");
diff --git a/libcxx/test/libcxx/strings/basic.string/allocator_with_fancy_pointer_non_trivial_destructor.verify.cpp b/libcxx/test/libcxx/strings/basic.string/allocator_with_fancy_pointer_non_trivial_destructor.verify.cpp
new file mode 100644
--- /dev/null
+++ b/libcxx/test/libcxx/strings/basic.string/allocator_with_fancy_pointer_non_trivial_destructor.verify.cpp
@@ -0,0 +1,79 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03
+
+// <string>
+
+// Test that basic_string requires its allocator to use a pointer with a trivial destructor.
+#include "test_macros.h"
+
+#include <string>
+#include <cstddef>
+#include <iterator>
+#include <type_traits>
+
+template <class T>
+class NonTriviallyDestructiblePointer {
+public:
+  // For the std::pointer_traits interface.
+  using pointer         = T*;
+  using element_type    = T;
+  using difference_type = std::ptrdiff_t;
+
+  template <class U>
+  using rebind = NonTriviallyDestructiblePointer<U>;
+
+  // For the std::iterator_traits interface.
+  using value_type        = typename std::remove_cv<T>::type;
+  using reference         = typename std::add_lvalue_reference<T>::type;
+  using iterator_category = std::random_access_iterator_tag;
+
+  _LIBCPP_CONSTEXPR_SINCE_CXX20 NonTriviallyDestructiblePointer() {} // non-trivial constructor
+  _LIBCPP_CONSTEXPR_SINCE_CXX20 NonTriviallyDestructiblePointer(T* p) : ptr(p) {}
+
+  template <typename T2>
+  NonTriviallyDestructiblePointer(const NonTriviallyDestructiblePointer<T2>& other) noexcept : ptr(other.get()) {}
+
+  operator T*() const { return ptr; }
+  NonTriviallyDestructiblePointer(NonTriviallyDestructiblePointer&&)                 = default;
+  NonTriviallyDestructiblePointer(const NonTriviallyDestructiblePointer&)            = default;
+  NonTriviallyDestructiblePointer& operator=(NonTriviallyDestructiblePointer&&)      = default;
+  NonTriviallyDestructiblePointer& operator=(const NonTriviallyDestructiblePointer&) = default;
+  _LIBCPP_CONSTEXPR_SINCE_CXX20 ~NonTriviallyDestructiblePointer() {} // non-trivial destructor
+  T& operator*() const { return *ptr; }
+  T* operator->() const { return ptr; }
+  operator bool() const { return ptr; }
+  T* get() const { return ptr; }
+
+  static NonTriviallyDestructiblePointer pointer_to(reference ref) noexcept {
+    return NonTriviallyDestructiblePointer(&ref);
+  }
+
+private:
+  T* ptr;
+};
+
+template <class T>
+class allocator : public std::allocator<T> {
+  using base = std::allocator<T>;
+
+public:
+  using pointer = NonTriviallyDestructiblePointer<T>;
+  pointer allocate(size_t n) { return base::allocate(n); }
+  void deallocate(pointer p, size_t n) { return base::deallocate(p, n); }
+};
+
+int main() {
+#if TEST_STD_VER >= 20
+  std::basic_string<char, std::char_traits<char>, allocator<char> > s; // expected-no-diagnostics
+#else
+  std::basic_string<char, std::char_traits<char>, allocator<char> >
+      s; // expected-error-re@* {{{{.*}}pointer type must have a trivial destructor.}}
+#endif
+}
diff --git a/libcxx/test/libcxx/strings/basic.string/sizeof.compile.pass.cpp b/libcxx/test/libcxx/strings/basic.string/sizeof.compile.pass.cpp
--- a/libcxx/test/libcxx/strings/basic.string/sizeof.compile.pass.cpp
+++ b/libcxx/test/libcxx/strings/basic.string/sizeof.compile.pass.cpp
@@ -42,6 +42,9 @@
 template <class CharT>
 using min_string = std::basic_string<CharT, std::char_traits<CharT>, min_allocator<CharT> >;
 
+template <class CharT>
+using fancy_string = std::basic_string<CharT, std::char_traits<CharT>, fancy_pointer_allocator<CharT> >;
+
 template <class CharT>
 using test_string = std::basic_string<CharT, std::char_traits<CharT>, test_allocator<CharT> >;
 
@@ -52,6 +55,7 @@
 
 static_assert(sizeof(std::string) == 24, "");
 static_assert(sizeof(min_string<char>) == 24, "");
+static_assert(sizeof(fancy_string<char>) == 24, "");
 static_assert(sizeof(test_string<char>) == 32, "");
 static_assert(sizeof(small_string<char>) == 6, "");
 
@@ -59,11 +63,13 @@
 #    if __WCHAR_WIDTH__ == 32
 static_assert(sizeof(std::wstring) == 24, "");
 static_assert(sizeof(min_string<wchar_t>) == 24, "");
+static_assert(sizeof(fancy_string<wchar_t>) == 24, "");
 static_assert(sizeof(test_string<wchar_t>) == 32, "");
 static_assert(sizeof(small_string<wchar_t>) == 12, "");
 #    elif __WCHAR_WIDTH__ == 16
 static_assert(sizeof(std::wstring) == 24, "");
 static_assert(sizeof(min_string<wchar_t>) == 24, "");
+static_assert(sizeof(fancy_string<wchar_t>) == 24, "");
 static_assert(sizeof(test_string<wchar_t>) == 32, "");
 static_assert(sizeof(small_string<wchar_t>) == 6, "");
 #    else
@@ -74,6 +80,7 @@
 #  ifndef TEST_HAS_NO_CHAR8_T
 static_assert(sizeof(std::u8string) == 24, "");
 static_assert(sizeof(min_string<char8_t>) == 24, "");
+static_assert(sizeof(fancy_string<char8_t>) == 24, "");
 static_assert(sizeof(test_string<char8_t>) == 32, "");
 static_assert(sizeof(small_string<char8_t>) == 6, "");
 #  endif
@@ -82,7 +89,9 @@
 static_assert(sizeof(std::u16string) == 24, "");
 static_assert(sizeof(std::u32string) == 24, "");
 static_assert(sizeof(min_string<char16_t>) == 24, "");
+static_assert(sizeof(fancy_string<char16_t>) == 24, "");
 static_assert(sizeof(min_string<char32_t>) == 24, "");
+static_assert(sizeof(fancy_string<char32_t>) == 24, "");
 static_assert(sizeof(test_string<char16_t>) == 32, "");
 static_assert(sizeof(test_string<char32_t>) == 32, "");
 static_assert(sizeof(small_string<char16_t>) == 6, "");
@@ -93,6 +102,7 @@
 
 static_assert(sizeof(std::string) == 12, "");
 static_assert(sizeof(min_string<char>) == 12, "");
+static_assert(sizeof(fancy_string<char>) == 12, "");
 static_assert(sizeof(test_string<char>) == 24, "");
 static_assert(sizeof(small_string<char>) == 6, "");
 
@@ -100,11 +110,13 @@
 #    if __WCHAR_WIDTH__ == 32
 static_assert(sizeof(std::wstring) == 12, "");
 static_assert(sizeof(min_string<wchar_t>) == 12, "");
+static_assert(sizeof(fancy_string<wchar_t>) == 12, "");
 static_assert(sizeof(test_string<wchar_t>) == 24, "");
 static_assert(sizeof(small_string<wchar_t>) == 12, "");
 #    elif __WCHAR_WIDTH__ == 16
 static_assert(sizeof(std::wstring) == 12, "");
 static_assert(sizeof(min_string<wchar_t>) == 12, "");
+static_assert(sizeof(fancy_string<wchar_t>) == 12, "");
 static_assert(sizeof(test_string<wchar_t>) == 24, "");
 static_assert(sizeof(small_string<wchar_t>) == 6, "");
 #    else
@@ -115,6 +127,7 @@
 #  ifndef TEST_HAS_NO_CHAR8_T
 static_assert(sizeof(std::u8string) == 12, "");
 static_assert(sizeof(min_string<char8_t>) == 12, "");
+static_assert(sizeof(fancy_string<char8_t>) == 12, "");
 static_assert(sizeof(test_string<char8_t>) == 24, "");
 static_assert(sizeof(small_string<char>) == 6, "");
 #  endif
@@ -124,6 +137,8 @@
 static_assert(sizeof(std::u32string) == 12, "");
 static_assert(sizeof(min_string<char16_t>) == 12, "");
 static_assert(sizeof(min_string<char32_t>) == 12, "");
+static_assert(sizeof(fancy_string<char16_t>) == 12, "");
+static_assert(sizeof(fancy_string<char32_t>) == 12, "");
 static_assert(sizeof(test_string<char16_t>) == 24, "");
 static_assert(sizeof(test_string<char32_t>) == 24, "");
 static_assert(sizeof(small_string<char16_t>) == 6, "");
diff --git a/libcxx/test/libcxx/strings/basic.string/string.access/assert.back.pass.cpp b/libcxx/test/libcxx/strings/basic.string/string.access/assert.back.pass.cpp
--- a/libcxx/test/libcxx/strings/basic.string/string.access/assert.back.pass.cpp
+++ b/libcxx/test/libcxx/strings/basic.string/string.access/assert.back.pass.cpp
@@ -19,18 +19,18 @@
 
 #include "check_assertion.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
+
+template <class S>
+void test() {
+  S s;
+  TEST_LIBCPP_ASSERT_FAILURE(s.back(), "string::back(): string is empty");
+}
 
 int main(int, char**) {
-    {
-        std::string s;
-        TEST_LIBCPP_ASSERT_FAILURE(s.back(), "string::back(): string is empty");
-    }
-
-    {
-        typedef std::basic_string<char, std::char_traits<char>, min_allocator<char> > S;
-        S s;
-        TEST_LIBCPP_ASSERT_FAILURE(s.back(), "string::back(): string is empty");
-    }
-
-    return 0;
+  test<std::string>();
+  test<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> >>();
+
+  return 0;
 }
diff --git a/libcxx/test/libcxx/strings/basic.string/string.access/assert.cback.pass.cpp b/libcxx/test/libcxx/strings/basic.string/string.access/assert.cback.pass.cpp
--- a/libcxx/test/libcxx/strings/basic.string/string.access/assert.cback.pass.cpp
+++ b/libcxx/test/libcxx/strings/basic.string/string.access/assert.cback.pass.cpp
@@ -19,18 +19,18 @@
 
 #include "check_assertion.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
+
+template <class S>
+void test() {
+  const S s;
+  TEST_LIBCPP_ASSERT_FAILURE(s.back(), "string::back(): string is empty");
+}
 
 int main(int, char**) {
-    {
-        std::string const s;
-        TEST_LIBCPP_ASSERT_FAILURE(s.back(), "string::back(): string is empty");
-    }
-
-    {
-        typedef std::basic_string<char, std::char_traits<char>, min_allocator<char> > S;
-        const S s;
-        TEST_LIBCPP_ASSERT_FAILURE(s.back(), "string::back(): string is empty");
-    }
-
-    return 0;
+  test<std::string>();
+  test<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> >>();
+
+  return 0;
 }
diff --git a/libcxx/test/libcxx/strings/basic.string/string.access/assert.cfront.pass.cpp b/libcxx/test/libcxx/strings/basic.string/string.access/assert.cfront.pass.cpp
--- a/libcxx/test/libcxx/strings/basic.string/string.access/assert.cfront.pass.cpp
+++ b/libcxx/test/libcxx/strings/basic.string/string.access/assert.cfront.pass.cpp
@@ -19,19 +19,18 @@
 
 #include "check_assertion.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
+
+template <class S>
+void test() {
+  const S s;
+  TEST_LIBCPP_ASSERT_FAILURE(s.front(), "string::front(): string is empty");
+}
 
 int main(int, char**) {
-  {
-    typedef std::string S;
-    const S s;
-    TEST_LIBCPP_ASSERT_FAILURE(s.front(), "string::front(): string is empty");
-  }
-
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char> > S;
-    const S s;
-    TEST_LIBCPP_ASSERT_FAILURE(s.front(), "string::front(): string is empty");
-  }
+  test<std::string>();
+  test<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> >>();
 
   return 0;
 }
diff --git a/libcxx/test/libcxx/strings/basic.string/string.access/assert.cindex.pass.cpp b/libcxx/test/libcxx/strings/basic.string/string.access/assert.cindex.pass.cpp
--- a/libcxx/test/libcxx/strings/basic.string/string.access/assert.cindex.pass.cpp
+++ b/libcxx/test/libcxx/strings/basic.string/string.access/assert.cindex.pass.cpp
@@ -20,21 +20,19 @@
 
 #include "check_assertion.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
+
+template <class S>
+void test() {
+  const S s;
+  assert(s[0] == 0);
+  TEST_LIBCPP_ASSERT_FAILURE(s[1], "string index out of bounds");
+}
 
 int main(int, char**) {
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char> > S;
-    const S s;
-    assert(s[0] == 0);
-    TEST_LIBCPP_ASSERT_FAILURE(s[1], "string index out of bounds");
-  }
-
-  {
-    typedef std::string S;
-    const S s;
-    assert(s[0] == 0);
-    TEST_LIBCPP_ASSERT_FAILURE(s[1], "string index out of bounds");
-  }
+  test<std::string>();
+  test<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> >>();
 
   return 0;
 }
diff --git a/libcxx/test/libcxx/strings/basic.string/string.access/assert.front.pass.cpp b/libcxx/test/libcxx/strings/basic.string/string.access/assert.front.pass.cpp
--- a/libcxx/test/libcxx/strings/basic.string/string.access/assert.front.pass.cpp
+++ b/libcxx/test/libcxx/strings/basic.string/string.access/assert.front.pass.cpp
@@ -20,19 +20,18 @@
 
 #include "check_assertion.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
+
+template <class S>
+void test() {
+  S s;
+  TEST_LIBCPP_ASSERT_FAILURE(s.front(), "string::front(): string is empty");
+}
 
 int main(int, char**) {
-  {
-    typedef std::string S;
-    S s;
-    TEST_LIBCPP_ASSERT_FAILURE(s.front(), "string::front(): string is empty");
-  }
-
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char> > S;
-    S s;
-    TEST_LIBCPP_ASSERT_FAILURE(s.front(), "string::front(): string is empty");
-  }
+  test<std::string>();
+  test<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> >>();
 
   return 0;
 }
diff --git a/libcxx/test/libcxx/strings/basic.string/string.access/assert.index.pass.cpp b/libcxx/test/libcxx/strings/basic.string/string.access/assert.index.pass.cpp
--- a/libcxx/test/libcxx/strings/basic.string/string.access/assert.index.pass.cpp
+++ b/libcxx/test/libcxx/strings/basic.string/string.access/assert.index.pass.cpp
@@ -20,21 +20,19 @@
 
 #include "check_assertion.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
+
+template <class S>
+void test() {
+  S s;
+  assert(s[0] == 0);
+  TEST_LIBCPP_ASSERT_FAILURE(s[1], "string index out of bounds");
+}
 
 int main(int, char**) {
-  {
-    typedef std::string S;
-    S s;
-    assert(s[0] == 0);
-    TEST_LIBCPP_ASSERT_FAILURE(s[1], "string index out of bounds");
-  }
-
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char> > S;
-    S s;
-    assert(s[0] == 0);
-    TEST_LIBCPP_ASSERT_FAILURE(s[1], "string index out of bounds");
-  }
+  test<std::string>();
+  test<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> >>();
 
   return 0;
 }
diff --git a/libcxx/test/libcxx/strings/basic.string/string.capacity/PR53170.pass.cpp b/libcxx/test/libcxx/strings/basic.string/string.capacity/PR53170.pass.cpp
--- a/libcxx/test/libcxx/strings/basic.string/string.capacity/PR53170.pass.cpp
+++ b/libcxx/test/libcxx/strings/basic.string/string.capacity/PR53170.pass.cpp
@@ -31,6 +31,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 void test() {
@@ -73,6 +74,7 @@
 
 #if TEST_STD_VER >= 11
     test<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+    test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
     return 0;
diff --git a/libcxx/test/libcxx/strings/basic.string/string.capacity/max_size.pass.cpp b/libcxx/test/libcxx/strings/basic.string/string.capacity/max_size.pass.cpp
--- a/libcxx/test/libcxx/strings/basic.string/string.capacity/max_size.pass.cpp
+++ b/libcxx/test/libcxx/strings/basic.string/string.capacity/max_size.pass.cpp
@@ -16,81 +16,93 @@
 #include <string>
 
 #include "test_macros.h"
+#include "test_allocator.h"
 
 // alignment of the string heap buffer is hardcoded to 16
 static const size_t alignment = 16;
 
+template <template <class> class Alloc>
 void full_size() {
-  std::string str;
+  std::basic_string<char, std::char_traits<char>, Alloc<char>> str;
   assert(str.max_size() == std::numeric_limits<size_t>::max() - alignment);
 
 #ifndef TEST_HAS_NO_CHAR8_T
-  std::u8string u8str;
+  std::basic_string<char8_t, std::char_traits<char8_t>, Alloc<char8_t>> u8str;
   assert(u8str.max_size() == std::numeric_limits<size_t>::max() - alignment);
 #endif
 
 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
-  std::wstring wstr;
+  std::basic_string<wchar_t, std::char_traits<wchar_t>, Alloc<wchar_t>> wstr;
   assert(wstr.max_size() == std::numeric_limits<size_t>::max() / sizeof(wchar_t) - alignment);
 #endif
 
-  std::u16string u16str;
-  std::u32string u32str;
+  std::basic_string<char16_t, std::char_traits<char16_t>, Alloc<char16_t>> u16str;
+  std::basic_string<char32_t, std::char_traits<char32_t>, Alloc<char32_t>> u32str;
   assert(u16str.max_size() == std::numeric_limits<size_t>::max() / 2 - alignment);
   assert(u32str.max_size() == std::numeric_limits<size_t>::max() / 4 - alignment);
 }
 
+template <template <class> class Alloc>
 void half_size() {
-  std::string str;
+  std::basic_string<char, std::char_traits<char>, Alloc<char>> str;
   assert(str.max_size() == std::numeric_limits<size_t>::max() / 2 - alignment);
 
 #ifndef TEST_HAS_NO_CHAR8_T
-  std::u8string u8str;
+  std::basic_string<char8_t, std::char_traits<char8_t>, Alloc<char8_t>> u8str;
   assert(u8str.max_size() == std::numeric_limits<size_t>::max() / 2 - alignment);
 #endif
 
 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
-  std::wstring wstr;
+  std::basic_string<wchar_t, std::char_traits<wchar_t>, Alloc<wchar_t>> wstr;
   assert(wstr.max_size() == std::numeric_limits<size_t>::max() / std::max<size_t>(2ul, sizeof(wchar_t)) - alignment);
 #endif
 
-  std::u16string u16str;
-  std::u32string u32str;
+  std::basic_string<char16_t, std::char_traits<char16_t>, Alloc<char16_t>> u16str;
+  std::basic_string<char32_t, std::char_traits<char32_t>, Alloc<char32_t>> u32str;
   assert(u16str.max_size() == std::numeric_limits<size_t>::max() / 2 - alignment);
   assert(u32str.max_size() == std::numeric_limits<size_t>::max() / 4 - alignment);
 }
 
 bool test() {
-
 #if _LIBCPP_ABI_VERSION == 1
 
-# if defined(__x86_64__) || defined(__i386__)
-  full_size();
-# elif defined(__APPLE__) && defined(__aarch64__)
-  half_size();
-# elif defined(__arm__) || defined(__aarch64__)
-#   ifdef __BIG_ENDIAN__
-  half_size();
-#   else
-  full_size();
-#   endif
-# elif defined(__powerpc__) || defined(__powerpc64__)
-#   ifdef __BIG_ENDIAN__
-  half_size();
-#   else
-  full_size();
-#   endif
-# elif defined(__sparc64__)
-  half_size();
-# elif defined(_WIN32)
-  full_size();
-# else
-#   error "Your target system seems to be unsupported."
-# endif
+#  if defined(__x86_64__) || defined(__i386__)
+  full_size<std::allocator>();
+  full_size<fancy_pointer_allocator>();
+#  elif defined(__APPLE__) && defined(__aarch64__)
+  half_size<std::allocator>();
+  half_size<fancy_pointer_allocator>();
+#  elif defined(__arm__) || defined(__aarch64__)
+#    ifdef __BIG_ENDIAN__
+  half_size<std::allocator>();
+  half_size<fancy_pointer_allocator>();
+#    else
+  full_size<std::allocator>();
+  full_size<fancy_pointer_allocator>();
+#    endif
+#  elif defined(__powerpc__) || defined(__powerpc64__)
+#    ifdef __BIG_ENDIAN__
+  half_size<std::allocator>();
+  half_size<fancy_pointer_allocator>();
+#    else
+  full_size<std::allocator>();
+  full_size<fancy_pointer_allocator>();
+#    endif
+#  elif defined(__sparc64__)
+  half_size<std::allocator>();
+  half_size<fancy_pointer_allocator>();
+#  elif defined(_WIN32)
+  full_size<std::allocator>();
+  full_size<fancy_pointer_allocator>();
+#  else
+#    error "Your target system seems to be unsupported."
+#  endif
 
 #else
 
-  half_size();
+  half_size<std::allocator>();
+  half_size<min_allocator>();
+  half_size<fancy_pointer_allocator>();
 
 #endif
 
diff --git a/libcxx/test/libcxx/strings/basic.string/string.cons/copy_shrunk_long.pass.cpp b/libcxx/test/libcxx/strings/basic.string/string.cons/copy_shrunk_long.pass.cpp
--- a/libcxx/test/libcxx/strings/basic.string/string.cons/copy_shrunk_long.pass.cpp
+++ b/libcxx/test/libcxx/strings/basic.string/string.cons/copy_shrunk_long.pass.cpp
@@ -33,17 +33,10 @@
 
 int main(int, char**)
 {
-    {
-    typedef test_allocator<char> A;
-    typedef std::basic_string<char, std::char_traits<char>, A> S;
-    test<S>();
-    }
+  test<std::string>();
 #if TEST_STD_VER >= 11
-    {
-    typedef min_allocator<char> A;
-    typedef std::basic_string<char, std::char_traits<char>, A> S;
-    test<S>();
-    }
+  test<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return 0;
diff --git a/libcxx/test/libcxx/strings/basic.string/string.iterators/debug.iterator.add.pass.cpp b/libcxx/test/libcxx/strings/basic.string/string.iterators/debug.iterator.add.pass.cpp
--- a/libcxx/test/libcxx/strings/basic.string/string.iterators/debug.iterator.add.pass.cpp
+++ b/libcxx/test/libcxx/strings/basic.string/string.iterators/debug.iterator.add.pass.cpp
@@ -18,27 +18,22 @@
 
 #include "check_assertion.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
+
+template <class C>
+void test() {
+  C c(1, '\0');
+  C::iterator i = c.begin();
+  i += 1;
+  assert(i == c.end());
+  i = c.begin();
+  TEST_LIBCPP_ASSERT_FAILURE(i += 2, "Attempted to add/subtract an iterator outside its valid range");
+}
 
 int main(int, char**) {
-  {
-    typedef std::string C;
-    C c(1, '\0');
-    C::iterator i = c.begin();
-    i += 1;
-    assert(i == c.end());
-    i = c.begin();
-    TEST_LIBCPP_ASSERT_FAILURE(i += 2, "Attempted to add/subtract an iterator outside its valid range");
-  }
-
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char> > C;
-    C c(1, '\0');
-    C::iterator i = c.begin();
-    i += 1;
-    assert(i == c.end());
-    i = c.begin();
-    TEST_LIBCPP_ASSERT_FAILURE(i += 2, "Attempted to add/subtract an iterator outside its valid range");
-  }
+  test<std::string>();
+  test<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> >>();
 
   return 0;
 }
diff --git a/libcxx/test/libcxx/strings/basic.string/string.iterators/debug.iterator.compare.pass.cpp b/libcxx/test/libcxx/strings/basic.string/string.iterators/debug.iterator.compare.pass.cpp
--- a/libcxx/test/libcxx/strings/basic.string/string.iterators/debug.iterator.compare.pass.cpp
+++ b/libcxx/test/libcxx/strings/basic.string/string.iterators/debug.iterator.compare.pass.cpp
@@ -17,21 +17,19 @@
 
 #include "check_assertion.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
+
+template <class S>
+void test() {
+  S s1;
+  S s2;
+  TEST_LIBCPP_ASSERT_FAILURE(s1.begin() < s2.begin(), "Attempted to compare incomparable iterators");
+}
 
 int main(int, char**) {
-  {
-    typedef std::string S;
-    S s1;
-    S s2;
-    TEST_LIBCPP_ASSERT_FAILURE(s1.begin() < s2.begin(), "Attempted to compare incomparable iterators");
-  }
-
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char> > S;
-    S s1;
-    S s2;
-    TEST_LIBCPP_ASSERT_FAILURE(s1.begin() < s2.begin(), "Attempted to compare incomparable iterators");
-  }
+  test<std::string>();
+  test<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> >>();
 
   return 0;
 }
diff --git a/libcxx/test/libcxx/strings/basic.string/string.iterators/debug.iterator.decrement.pass.cpp b/libcxx/test/libcxx/strings/basic.string/string.iterators/debug.iterator.decrement.pass.cpp
--- a/libcxx/test/libcxx/strings/basic.string/string.iterators/debug.iterator.decrement.pass.cpp
+++ b/libcxx/test/libcxx/strings/basic.string/string.iterators/debug.iterator.decrement.pass.cpp
@@ -18,25 +18,21 @@
 
 #include "check_assertion.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
+
+template <class C>
+void test() {
+  C c(1, '\0');
+  C::iterator i = c.end();
+  --i;
+  assert(i == c.begin());
+  TEST_LIBCPP_ASSERT_FAILURE(--i, "Attempted to decrement a non-decrementable iterator");
+}
 
 int main(int, char**) {
-  {
-    typedef std::string C;
-    C c(1, '\0');
-    C::iterator i = c.end();
-    --i;
-    assert(i == c.begin());
-    TEST_LIBCPP_ASSERT_FAILURE(--i, "Attempted to decrement a non-decrementable iterator");
-  }
-
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char> > C;
-    C c(1, '\0');
-    C::iterator i = c.end();
-    --i;
-    assert(i == c.begin());
-    TEST_LIBCPP_ASSERT_FAILURE(--i, "Attempted to decrement a non-decrementable iterator");
-  }
+  test<std::string>();
+  test<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> >>();
 
   return 0;
 }
diff --git a/libcxx/test/libcxx/strings/basic.string/string.iterators/debug.iterator.dereference.pass.cpp b/libcxx/test/libcxx/strings/basic.string/string.iterators/debug.iterator.dereference.pass.cpp
--- a/libcxx/test/libcxx/strings/basic.string/string.iterators/debug.iterator.dereference.pass.cpp
+++ b/libcxx/test/libcxx/strings/basic.string/string.iterators/debug.iterator.dereference.pass.cpp
@@ -17,21 +17,19 @@
 
 #include "check_assertion.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
+
+template <class C>
+void test() {
+  C c(1, '\0');
+  C::iterator i = c.end();
+  TEST_LIBCPP_ASSERT_FAILURE(*i, "Attempted to dereference a non-dereferenceable iterator");
+}
 
 int main(int, char**) {
-  {
-    typedef std::string C;
-    C c(1, '\0');
-    C::iterator i = c.end();
-    TEST_LIBCPP_ASSERT_FAILURE(*i, "Attempted to dereference a non-dereferenceable iterator");
-  }
-
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char> > C;
-    C c(1, '\0');
-    C::iterator i = c.end();
-    TEST_LIBCPP_ASSERT_FAILURE(*i, "Attempted to dereference a non-dereferenceable iterator");
-  }
+  test<std::string>();
+  test<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> >>();
 
   return 0;
 }
diff --git a/libcxx/test/libcxx/strings/basic.string/string.iterators/debug.iterator.increment.pass.cpp b/libcxx/test/libcxx/strings/basic.string/string.iterators/debug.iterator.increment.pass.cpp
--- a/libcxx/test/libcxx/strings/basic.string/string.iterators/debug.iterator.increment.pass.cpp
+++ b/libcxx/test/libcxx/strings/basic.string/string.iterators/debug.iterator.increment.pass.cpp
@@ -18,25 +18,21 @@
 
 #include "check_assertion.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
+
+template <class C>
+void test() {
+  C c(1, '\0');
+  C::iterator i = c.begin();
+  ++i;
+  assert(i == c.end());
+  TEST_LIBCPP_ASSERT_FAILURE(++i, "Attempted to increment a non-incrementable iterator");
+}
 
 int main(int, char**) {
-  {
-    typedef std::string C;
-    C c(1, '\0');
-    C::iterator i = c.begin();
-    ++i;
-    assert(i == c.end());
-    TEST_LIBCPP_ASSERT_FAILURE(++i, "Attempted to increment a non-incrementable iterator");
-  }
-
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char> > C;
-    C c(1, '\0');
-    C::iterator i = c.begin();
-    ++i;
-    assert(i == c.end());
-    TEST_LIBCPP_ASSERT_FAILURE(++i, "Attempted to increment a non-incrementable iterator");
-  }
+  test<std::string>();
+  test<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> >>();
 
   return 0;
 }
diff --git a/libcxx/test/libcxx/strings/basic.string/string.iterators/debug.iterator.index.pass.cpp b/libcxx/test/libcxx/strings/basic.string/string.iterators/debug.iterator.index.pass.cpp
--- a/libcxx/test/libcxx/strings/basic.string/string.iterators/debug.iterator.index.pass.cpp
+++ b/libcxx/test/libcxx/strings/basic.string/string.iterators/debug.iterator.index.pass.cpp
@@ -18,23 +18,20 @@
 
 #include "check_assertion.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
+
+template <class C>
+void test() {
+  C c(1, '\0');
+  C::iterator i = c.begin();
+  assert(i[0] == 0);
+  TEST_LIBCPP_ASSERT_FAILURE(i[1], "Attempted to subscript an iterator outside its valid range");
+}
 
 int main(int, char**) {
-  {
-    typedef std::string C;
-    C c(1, '\0');
-    C::iterator i = c.begin();
-    assert(i[0] == 0);
-    TEST_LIBCPP_ASSERT_FAILURE(i[1], "Attempted to subscript an iterator outside its valid range");
-  }
-
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char> > C;
-    C c(1, '\0');
-    C::iterator i = c.begin();
-    assert(i[0] == 0);
-    TEST_LIBCPP_ASSERT_FAILURE(i[1], "Attempted to subscript an iterator outside its valid range");
-  }
+  test<std::string>();
+  test<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> >>();
 
   return 0;
 }
diff --git a/libcxx/test/libcxx/strings/basic.string/string.iterators/debug.iterator.subtract.pass.cpp b/libcxx/test/libcxx/strings/basic.string/string.iterators/debug.iterator.subtract.pass.cpp
--- a/libcxx/test/libcxx/strings/basic.string/string.iterators/debug.iterator.subtract.pass.cpp
+++ b/libcxx/test/libcxx/strings/basic.string/string.iterators/debug.iterator.subtract.pass.cpp
@@ -17,21 +17,19 @@
 
 #include "check_assertion.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
+
+template <class S>
+void test() {
+  S s1;
+  S s2;
+  TEST_LIBCPP_ASSERT_FAILURE(s1.begin() - s2.begin(), "Attempted to subtract incompatible iterators");
+}
 
 int main(int, char**) {
-  {
-    typedef std::string S;
-    S s1;
-    S s2;
-    TEST_LIBCPP_ASSERT_FAILURE(s1.begin() - s2.begin(), "Attempted to subtract incompatible iterators");
-  }
-
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char> > S;
-    S s1;
-    S s2;
-    TEST_LIBCPP_ASSERT_FAILURE(s1.begin() - s2.begin(), "Attempted to subtract incompatible iterators");
-  }
+  test<std::string>();
+  test<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> >>();
 
   return 0;
 }
diff --git a/libcxx/test/libcxx/strings/basic.string/string.modifiers/assert.erase_iter.null.pass.cpp b/libcxx/test/libcxx/strings/basic.string/string.modifiers/assert.erase_iter.null.pass.cpp
--- a/libcxx/test/libcxx/strings/basic.string/string.modifiers/assert.erase_iter.null.pass.cpp
+++ b/libcxx/test/libcxx/strings/basic.string/string.modifiers/assert.erase_iter.null.pass.cpp
@@ -19,20 +19,19 @@
 
 #include "check_assertion.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
+
+template <class S>
+void test() {
+  S l1("123");
+  typename S::const_iterator i = l1.end();
+  TEST_LIBCPP_ASSERT_FAILURE(l1.erase(i), "string::erase(iterator) called with a non-dereferenceable iterator");
+}
 
 int main(int, char**) {
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char> > S;
-    S l1("123");
-    S::const_iterator i = l1.end();
-    TEST_LIBCPP_ASSERT_FAILURE(l1.erase(i), "string::erase(iterator) called with a non-dereferenceable iterator");
-  }
-
-  {
-    std::string l1("123");
-    std::string::const_iterator i = l1.end();
-    TEST_LIBCPP_ASSERT_FAILURE(l1.erase(i), "string::erase(iterator) called with a non-dereferenceable iterator");
-  }
+  test<std::string>();
+  test<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> >>();
 
   return 0;
 }
diff --git a/libcxx/test/libcxx/strings/basic.string/string.modifiers/assert.pop_back.pass.cpp b/libcxx/test/libcxx/strings/basic.string/string.modifiers/assert.pop_back.pass.cpp
--- a/libcxx/test/libcxx/strings/basic.string/string.modifiers/assert.pop_back.pass.cpp
+++ b/libcxx/test/libcxx/strings/basic.string/string.modifiers/assert.pop_back.pass.cpp
@@ -18,10 +18,17 @@
 #include <string>
 
 #include "check_assertion.h"
+#include "test_allocator.h"
+
+template <class S>
+void test() {
+  S s;
+  TEST_LIBCPP_ASSERT_FAILURE(s.pop_back(), "string::pop_back(): string is already empty");
+}
 
 int main(int, char**) {
-    std::string s;
-    TEST_LIBCPP_ASSERT_FAILURE(s.pop_back(), "string::pop_back(): string is already empty");
+  test<std::string>();
+  test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> >>();
 
-    return 0;
+  return 0;
 }
diff --git a/libcxx/test/libcxx/strings/basic.string/string.modifiers/debug.erase.iter.pass.cpp b/libcxx/test/libcxx/strings/basic.string/string.modifiers/debug.erase.iter.pass.cpp
--- a/libcxx/test/libcxx/strings/basic.string/string.modifiers/debug.erase.iter.pass.cpp
+++ b/libcxx/test/libcxx/strings/basic.string/string.modifiers/debug.erase.iter.pass.cpp
@@ -17,22 +17,21 @@
 
 #include "check_assertion.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
+
+template <class S>
+void test() {
+  S l1("123");
+  S l2("123");
+  S::const_iterator i = l2.begin();
+  TEST_LIBCPP_ASSERT_FAILURE(
+      l1.erase(i), "string::erase(iterator) called with an iterator not referring to this string");
+}
 
 int main(int, char**) {
-    {
-        std::string l1("123");
-        std::string l2("123");
-        std::string::const_iterator i = l2.begin();
-        TEST_LIBCPP_ASSERT_FAILURE(l1.erase(i), "string::erase(iterator) called with an iterator not referring to this string");
-    }
-
-    {
-        typedef std::basic_string<char, std::char_traits<char>, min_allocator<char> > S;
-        S l1("123");
-        S l2("123");
-        S::const_iterator i = l2.begin();
-        TEST_LIBCPP_ASSERT_FAILURE(l1.erase(i), "string::erase(iterator) called with an iterator not referring to this string");
-    }
-
-    return 0;
+  test<std::string>();
+  test<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> >>();
+
+  return 0;
 }
diff --git a/libcxx/test/libcxx/strings/basic.string/string.modifiers/debug.erase.iter_iter.pass.cpp b/libcxx/test/libcxx/strings/basic.string/string.modifiers/debug.erase.iter_iter.pass.cpp
--- a/libcxx/test/libcxx/strings/basic.string/string.modifiers/debug.erase.iter_iter.pass.cpp
+++ b/libcxx/test/libcxx/strings/basic.string/string.modifiers/debug.erase.iter_iter.pass.cpp
@@ -17,75 +17,47 @@
 
 #include "check_assertion.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
+
+template <class S>
+void test() {
+  // With first iterator from another container
+  {
+    S l1("123");
+    S l2("123");
+    TEST_LIBCPP_ASSERT_FAILURE(
+        l1.erase(l2.cbegin(), l1.cbegin() + 1),
+        "string::erase(iterator,  iterator) called with an iterator not referring to this string");
+  }
+
+  // With second iterator from another container
+  {
+    S l1("123");
+    S l2("123");
+    TEST_LIBCPP_ASSERT_FAILURE(l1.erase(l1.cbegin(), l2.cbegin() + 1), "Attempted to compare incomparable iterators");
+  }
+
+  // With both iterators from another container
+  {
+    S l1("123");
+    S l2("123");
+    TEST_LIBCPP_ASSERT_FAILURE(
+        l1.erase(l2.cbegin(), l2.cbegin() + 1),
+        "string::erase(iterator,  iterator) called with an iterator not referring to this string");
+  }
+
+  // With an invalid range
+  {
+    S l1("123");
+    TEST_LIBCPP_ASSERT_FAILURE(
+        l1.erase(l1.cbegin() + 1, l1.cbegin()), "string::erase(first, last) called with invalid range");
+  }
+}
 
 int main(int, char**) {
+  test<std::string>();
+  test<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> >>();
 
-    // With first iterator from another container
-    {
-        {
-            std::string l1("123");
-            std::string l2("123");
-            TEST_LIBCPP_ASSERT_FAILURE(
-                l1.erase(l2.cbegin(), l1.cbegin() + 1),
-                "string::erase(iterator,  iterator) called with an iterator not referring to this string");
-        }
-        {
-            typedef std::basic_string<char, std::char_traits<char>, min_allocator<char> > S;
-            S l1("123");
-            S l2("123");
-            TEST_LIBCPP_ASSERT_FAILURE(l1.erase(l2.cbegin(), l1.cbegin() + 1),
-                                        "string::erase(iterator,  iterator) called with an iterator not referring to this string");
-        }
-    }
-
-    // With second iterator from another container
-    {
-        {
-            std::string l1("123");
-            std::string l2("123");
-            TEST_LIBCPP_ASSERT_FAILURE(l1.erase(l1.cbegin(), l2.cbegin() + 1), "Attempted to compare incomparable iterators");
-        }
-        {
-            typedef std::basic_string<char, std::char_traits<char>, min_allocator<char> > S;
-            S l1("123");
-            S l2("123");
-            TEST_LIBCPP_ASSERT_FAILURE(l1.erase(l1.cbegin(), l2.cbegin() + 1), "Attempted to compare incomparable iterators");
-        }
-    }
-
-    // With both iterators from another container
-    {
-        {
-            std::string l1("123");
-            std::string l2("123");
-            TEST_LIBCPP_ASSERT_FAILURE(
-                l1.erase(l2.cbegin(), l2.cbegin() + 1),
-                "string::erase(iterator,  iterator) called with an iterator not referring to this string");
-        }
-        {
-            typedef std::basic_string<char, std::char_traits<char>, min_allocator<char> > S;
-            S l1("123");
-            S l2("123");
-            TEST_LIBCPP_ASSERT_FAILURE(
-                l1.erase(l2.cbegin(), l2.cbegin() + 1),
-                "string::erase(iterator,  iterator) called with an iterator not referring to this string");
-        }
-    }
-
-    // With an invalid range
-    {
-        {
-            std::string l1("123");
-            TEST_LIBCPP_ASSERT_FAILURE(l1.erase(l1.cbegin() + 1, l1.cbegin()),
-                                    "string::erase(first, last) called with invalid range");
-        }
-        {
-            typedef std::basic_string<char, std::char_traits<char>, min_allocator<char> > S;
-            S l1("123");
-            TEST_LIBCPP_ASSERT_FAILURE(l1.erase(l1.cbegin() + 1, l1.cbegin()),
-                                    "string::erase(first, last) called with invalid range");
-        }
-    }
-
-    return 0;
+  return 0;
 }
diff --git a/libcxx/test/libcxx/strings/basic.string/string.modifiers/debug.insert.iter_char.pass.cpp b/libcxx/test/libcxx/strings/basic.string/string.modifiers/debug.insert.iter_char.pass.cpp
--- a/libcxx/test/libcxx/strings/basic.string/string.modifiers/debug.insert.iter_char.pass.cpp
+++ b/libcxx/test/libcxx/strings/basic.string/string.modifiers/debug.insert.iter_char.pass.cpp
@@ -22,13 +22,20 @@
 #include <string>
 
 #include "check_assertion.h"
+#include "test_allocator.h"
+
+template <class S>
+void test() {
+  S s;
+  S s2;
+  TEST_LIBCPP_ASSERT_FAILURE(
+      s.insert(s2.begin(), '1'),
+      "string::insert(iterator, character) called with an iterator not referring to this string");
+}
 
 int main(int, char**) {
-    typedef std::string S;
-    S s;
-    S s2;
-    TEST_LIBCPP_ASSERT_FAILURE(s.insert(s2.begin(), '1'),
-        "string::insert(iterator, character) called with an iterator not referring to this string");
+  test<std::string>();
+  test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> >>();
 
-    return 0;
+  return 0;
 }
diff --git a/libcxx/test/libcxx/strings/basic.string/string.modifiers/debug.insert.iter_iter_iter.pass.cpp b/libcxx/test/libcxx/strings/basic.string/string.modifiers/debug.insert.iter_iter_iter.pass.cpp
--- a/libcxx/test/libcxx/strings/basic.string/string.modifiers/debug.insert.iter_iter_iter.pass.cpp
+++ b/libcxx/test/libcxx/strings/basic.string/string.modifiers/debug.insert.iter_iter_iter.pass.cpp
@@ -17,14 +17,21 @@
 #include <string>
 
 #include "check_assertion.h"
+#include "test_allocator.h"
+
+template <class S>
+void test() {
+  S v;
+  S v2;
+  char a[]    = "123";
+  const int N = sizeof(a) / sizeof(a[0]);
+  TEST_LIBCPP_ASSERT_FAILURE(
+      v.insert(v2.cbegin() + 10, a, a + N), "Attempted to add/subtract an iterator outside its valid range");
+}
 
 int main(int, char**) {
-    std::string v;
-    std::string v2;
-    char a[] = "123";
-    const int N = sizeof(a)/sizeof(a[0]);
-    TEST_LIBCPP_ASSERT_FAILURE(v.insert(v2.cbegin() + 10, a, a + N),
-                               "Attempted to add/subtract an iterator outside its valid range");
-
-    return 0;
+  test<std::string>();
+  test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> >>();
+
+  return 0;
 }
diff --git a/libcxx/test/libcxx/strings/basic.string/string.modifiers/debug.insert.iter_size_char.pass.cpp b/libcxx/test/libcxx/strings/basic.string/string.modifiers/debug.insert.iter_size_char.pass.cpp
--- a/libcxx/test/libcxx/strings/basic.string/string.modifiers/debug.insert.iter_size_char.pass.cpp
+++ b/libcxx/test/libcxx/strings/basic.string/string.modifiers/debug.insert.iter_size_char.pass.cpp
@@ -16,13 +16,19 @@
 #include <string>
 
 #include "check_assertion.h"
+#include "test_allocator.h"
+
+template <class S>
+void test() {
+  S s;
+  S s2;
+  TEST_LIBCPP_ASSERT_FAILURE(s.insert(s2.begin(), 1, 'a'),
+                             "string::insert(iterator, n, value) called with an iterator not referring to this string");
+}
 
 int main(int, char**) {
-    std::string s;
-    std::string s2;
-    TEST_LIBCPP_ASSERT_FAILURE(
-        s.insert(s2.begin(), 1, 'a'),
-        "string::insert(iterator, n, value) called with an iterator not referring to this string");
+  test<std::string>();
+  test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> >>();
 
-    return 0;
+  return 0;
 }
diff --git a/libcxx/test/libcxx/strings/basic.string/string.modifiers/resize_default_initialized.pass.cpp b/libcxx/test/libcxx/strings/basic.string/string.modifiers/resize_default_initialized.pass.cpp
--- a/libcxx/test/libcxx/strings/basic.string/string.modifiers/resize_default_initialized.pass.cpp
+++ b/libcxx/test/libcxx/strings/basic.string/string.modifiers/resize_default_initialized.pass.cpp
@@ -14,6 +14,7 @@
 #include <cassert>
 
 #include "test_macros.h"
+#include "test_allocator.h"
 
 void write_c_str(char *buf, int size) {
   for (int i=0; i < size; ++i) {
@@ -22,12 +23,12 @@
   buf[size] = '\0';
 }
 
-void test_buffer_usage()
-{
+template <class S>
+void test_buffer_usage() {
   {
     unsigned buff_size = 125;
     unsigned used_size = buff_size - 16;
-    std::string s;
+    S s;
     s.__resize_default_init(buff_size);
     write_c_str(&s[0], used_size);
     assert(s.size() == buff_size);
@@ -41,9 +42,10 @@
   }
 }
 
+template <class S>
 void test_basic() {
   {
-    std::string s;
+    S s;
     s.__resize_default_init(3);
     assert(s.size() == 3);
     assert(s.data()[3] == '\0');
@@ -57,8 +59,11 @@
 }
 
 int main(int, char**) {
-  test_basic();
-  test_buffer_usage();
+  test_basic<std::string>();
+  test_basic<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> >>();
+
+  test_buffer_usage<std::string>();
+  test_buffer_usage<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> >>();
 
   return 0;
 }
diff --git a/libcxx/test/std/strings/basic.string/string.access/at.pass.cpp b/libcxx/test/std/strings/basic.string/string.access/at.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.access/at.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.access/at.pass.cpp
@@ -16,41 +16,32 @@
 #include <cassert>
 
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 #include "test_macros.h"
 
 template <class S>
-TEST_CONSTEXPR_CXX20 void
-test(S s, typename S::size_type pos)
-{
-    const S& cs = s;
-    if (pos < s.size())
-    {
-        assert(s.at(pos) == s[pos]);
-        assert(cs.at(pos) == cs[pos]);
-    }
+TEST_CONSTEXPR_CXX20 void test(S s, typename S::size_type pos) {
+  const S& cs = s;
+  if (pos < s.size()) {
+    assert(s.at(pos) == s[pos]);
+    assert(cs.at(pos) == cs[pos]);
+  }
 #ifndef TEST_HAS_NO_EXCEPTIONS
-    else if (!TEST_IS_CONSTANT_EVALUATED)
-    {
-        try
-        {
-            TEST_IGNORE_NODISCARD s.at(pos);
-            assert(false);
-        }
-        catch (std::out_of_range&)
-        {
-            assert(pos >= s.size());
-        }
-        try
-        {
-            TEST_IGNORE_NODISCARD cs.at(pos);
-            assert(false);
-        }
-        catch (std::out_of_range&)
-        {
-            assert(pos >= s.size());
-        }
+  else if (!TEST_IS_CONSTANT_EVALUATED) {
+    try {
+      TEST_IGNORE_NODISCARD s.at(pos);
+      assert(false);
+    } catch (std::out_of_range&) {
+      assert(pos >= s.size());
+    }
+    try {
+      TEST_IGNORE_NODISCARD cs.at(pos);
+      assert(false);
+    } catch (std::out_of_range&) {
+      assert(pos >= s.size());
     }
+  }
 #endif
 }
 
@@ -65,15 +56,16 @@
 
 TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
+
 #if TEST_STD_VER >= 11
-  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
 }
 
-int main(int, char**)
-{
+int main(int, char**) {
   test();
 #if TEST_STD_VER > 17
   static_assert(test());
diff --git a/libcxx/test/std/strings/basic.string/string.access/back.pass.cpp b/libcxx/test/std/strings/basic.string/string.access/back.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.access/back.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.access/back.pass.cpp
@@ -16,20 +16,19 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
-TEST_CONSTEXPR_CXX20 void
-test(S s)
-{
-    const S& cs = s;
-    ASSERT_SAME_TYPE(decltype( s.back()), typename S::reference);
-    ASSERT_SAME_TYPE(decltype(cs.back()), typename S::const_reference);
-    LIBCPP_ASSERT_NOEXCEPT(    s.back());
-    LIBCPP_ASSERT_NOEXCEPT(   cs.back());
-    assert(&cs.back() == &cs[cs.size()-1]);
-    assert(&s.back() == &s[cs.size()-1]);
-    s.back() = typename S::value_type('z');
-    assert(s.back() == typename S::value_type('z'));
+TEST_CONSTEXPR_CXX20 void test(S s) {
+  const S& cs = s;
+  ASSERT_SAME_TYPE(decltype(s.back()), typename S::reference);
+  ASSERT_SAME_TYPE(decltype(cs.back()), typename S::const_reference);
+  LIBCPP_ASSERT_NOEXCEPT(s.back());
+  LIBCPP_ASSERT_NOEXCEPT(cs.back());
+  assert(&cs.back() == &cs[cs.size() - 1]);
+  assert(&s.back() == &s[cs.size() - 1]);
+  s.back() = typename S::value_type('z');
+  assert(s.back() == typename S::value_type('z'));
 }
 
 template <class S>
@@ -41,14 +40,14 @@
 TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
-  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
 }
 
-int main(int, char**)
-{
+int main(int, char**) {
   test();
 #if TEST_STD_VER > 17
   static_assert(test());
diff --git a/libcxx/test/std/strings/basic.string/string.access/front.pass.cpp b/libcxx/test/std/strings/basic.string/string.access/front.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.access/front.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.access/front.pass.cpp
@@ -16,20 +16,19 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
-TEST_CONSTEXPR_CXX20 void
-test(S s)
-{
-    const S& cs = s;
-    ASSERT_SAME_TYPE(decltype( s.front()), typename S::reference);
-    ASSERT_SAME_TYPE(decltype(cs.front()), typename S::const_reference);
-    LIBCPP_ASSERT_NOEXCEPT(    s.front());
-    LIBCPP_ASSERT_NOEXCEPT(   cs.front());
-    assert(&cs.front() == &cs[0]);
-    assert(&s.front() == &s[0]);
-    s.front() = typename S::value_type('z');
-    assert(s.front() == typename S::value_type('z'));
+TEST_CONSTEXPR_CXX20 void test(S s) {
+  const S& cs = s;
+  ASSERT_SAME_TYPE(decltype(s.front()), typename S::reference);
+  ASSERT_SAME_TYPE(decltype(cs.front()), typename S::const_reference);
+  LIBCPP_ASSERT_NOEXCEPT(s.front());
+  LIBCPP_ASSERT_NOEXCEPT(cs.front());
+  assert(&cs.front() == &cs[0]);
+  assert(&s.front() == &s[0]);
+  s.front() = typename S::value_type('z');
+  assert(s.front() == typename S::value_type('z'));
 }
 
 template <class S>
@@ -41,14 +40,14 @@
 TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
-  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
 }
 
-int main(int, char**)
-{
+int main(int, char**) {
   test();
 #if TEST_STD_VER > 17
   static_assert(test());
diff --git a/libcxx/test/std/strings/basic.string/string.access/index.pass.cpp b/libcxx/test/std/strings/basic.string/string.access/index.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.access/index.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.access/index.pass.cpp
@@ -16,6 +16,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test_string() {
@@ -38,14 +39,14 @@
 TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
-  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
 }
 
-int main(int, char**)
-{
+int main(int, char**) {
   test();
 #if TEST_STD_VER > 17
   static_assert(test());
diff --git a/libcxx/test/std/strings/basic.string/string.capacity/capacity.pass.cpp b/libcxx/test/std/strings/basic.string/string.capacity/capacity.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.capacity/capacity.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.capacity/capacity.pass.cpp
@@ -15,57 +15,60 @@
 
 #include "test_allocator.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 #include "test_macros.h"
 
 template <class S>
-TEST_CONSTEXPR_CXX20 void
-test(S s, test_allocator_statistics& alloc_stats)
-{
-    alloc_stats.throw_after = 0;
+TEST_CONSTEXPR_CXX20 void test(S s, test_allocator_statistics& alloc_stats) {
+  alloc_stats.throw_after = 0;
 #ifndef TEST_HAS_NO_EXCEPTIONS
-    try
+  try
 #endif
-    {
-        while (s.size() < s.capacity())
-            s.push_back(typename S::value_type());
-        assert(s.size() == s.capacity());
-    }
+  {
+    while (s.size() < s.capacity())
+      s.push_back(typename S::value_type());
+    assert(s.size() == s.capacity());
+  }
 #ifndef TEST_HAS_NO_EXCEPTIONS
-    catch (...)
-    {
-        assert(false);
-    }
+  catch (...) {
+    assert(false);
+  }
 #endif
-    alloc_stats.throw_after = INT_MAX;
+  alloc_stats.throw_after = INT_MAX;
+}
+
+template <class S>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  S s;
+  assert(s.capacity() > 0);
+}
+
+template <>
+TEST_CONSTEXPR_CXX20 void test_string<std::basic_string<char, std::char_traits<char>, test_allocator<char> >>() {
+  using S = std::basic_string<char, std::char_traits<char>, test_allocator<char> >;
+  test_allocator_statistics alloc_stats;
+  S s((test_allocator<char>(&alloc_stats)));
+  test(s, alloc_stats);
+  s.assign(10, 'a');
+  s.erase(5);
+  test(s, alloc_stats);
+  s.assign(100, 'a');
+  s.erase(50);
+  test(s, alloc_stats);
 }
 
 TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    test_allocator_statistics alloc_stats;
-    typedef std::basic_string<char, std::char_traits<char>, test_allocator<char> > S;
-    S s((test_allocator<char>(&alloc_stats)));
-    test(s, alloc_stats);
-    s.assign(10, 'a');
-    s.erase(5);
-    test(s, alloc_stats);
-    s.assign(100, 'a');
-    s.erase(50);
-    test(s, alloc_stats);
-  }
+  test_string<std::basic_string<char, std::char_traits<char>, test_allocator<char> > >();
 #if TEST_STD_VER >= 11
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    S s;
-    assert(s.capacity() > 0);
-  }
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
 }
 
-int main(int, char**)
-{
+int main(int, char**) {
   test();
 #if TEST_STD_VER > 17
   static_assert(test());
diff --git a/libcxx/test/std/strings/basic.string/string.capacity/clear.pass.cpp b/libcxx/test/std/strings/basic.string/string.capacity/clear.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.capacity/clear.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.capacity/clear.pass.cpp
@@ -15,13 +15,12 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
-TEST_CONSTEXPR_CXX20 void
-test(S s)
-{
-    s.clear();
-    assert(s.size() == 0);
+TEST_CONSTEXPR_CXX20 void test(S s) {
+  s.clear();
+  assert(s.size() == 0);
 }
 
 template <class S>
@@ -41,14 +40,14 @@
 TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
-  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
 }
 
-int main(int, char**)
-{
+int main(int, char**) {
   test();
 #if TEST_STD_VER > 17
   static_assert(test());
diff --git a/libcxx/test/std/strings/basic.string/string.capacity/empty.pass.cpp b/libcxx/test/std/strings/basic.string/string.capacity/empty.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.capacity/empty.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.capacity/empty.pass.cpp
@@ -15,13 +15,12 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
-TEST_CONSTEXPR_CXX20 void
-test(const S& s)
-{
-    ASSERT_NOEXCEPT(s.empty());
-    assert(s.empty() == (s.size() == 0));
+TEST_CONSTEXPR_CXX20 void test(const S& s) {
+  ASSERT_NOEXCEPT(s.empty());
+  assert(s.empty() == (s.size() == 0));
 }
 
 template <class S>
@@ -34,14 +33,14 @@
 TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
-  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
 }
 
-int main(int, char**)
-{
+int main(int, char**) {
   test();
 #if TEST_STD_VER > 17
   static_assert(test());
diff --git a/libcxx/test/std/strings/basic.string/string.capacity/length.pass.cpp b/libcxx/test/std/strings/basic.string/string.capacity/length.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.capacity/length.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.capacity/length.pass.cpp
@@ -15,12 +15,11 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
-TEST_CONSTEXPR_CXX20 void
-test(const S& s)
-{
-    assert(s.length() == s.size());
+TEST_CONSTEXPR_CXX20 void test(const S& s) {
+  assert(s.length() == s.size());
 }
 
 template <class S>
@@ -33,14 +32,14 @@
 TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
-  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
 }
 
-int main(int, char**)
-{
+int main(int, char**) {
   test();
 #if TEST_STD_VER > 17
   static_assert(test());
diff --git a/libcxx/test/std/strings/basic.string/string.capacity/max_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.capacity/max_size.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.capacity/max_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.capacity/max_size.pass.cpp
@@ -24,36 +24,37 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
-TEST_CONSTEXPR_CXX20 void
-test1(const S& s)
-{
-    S s2(s);
-    const size_t sz = s2.max_size() - 1;
-    try { s2.resize(sz, 'x'); }
-    catch ( const std::bad_alloc & ) { return ; }
-    assert ( s2.size() ==  sz );
+TEST_CONSTEXPR_CXX20 void test1(const S& s) {
+  S s2(s);
+  const size_t sz = s2.max_size() - 1;
+  try {
+    s2.resize(sz, 'x');
+  } catch (const std::bad_alloc&) {
+    return;
+  }
+  assert(s2.size() == sz);
 }
 
 template <class S>
-TEST_CONSTEXPR_CXX20 void
-test2(const S& s)
-{
-    S s2(s);
-    const size_t sz = s2.max_size();
-    try { s2.resize(sz, 'x'); }
-    catch ( const std::bad_alloc & ) { return ; }
-    assert ( s.size() ==  sz );
+TEST_CONSTEXPR_CXX20 void test2(const S& s) {
+  S s2(s);
+  const size_t sz = s2.max_size();
+  try {
+    s2.resize(sz, 'x');
+  } catch (const std::bad_alloc&) {
+    return;
+  }
+  assert(s.size() == sz);
 }
 
 template <class S>
-TEST_CONSTEXPR_CXX20 void
-test(const S& s)
-{
-    assert(s.max_size() >= s.size());
-    test1(s);
-    test2(s);
+TEST_CONSTEXPR_CXX20 void test(const S& s) {
+  assert(s.max_size() >= s.size());
+  test1(s);
+  test2(s);
 }
 
 template <class S>
@@ -63,28 +64,35 @@
   test(S("12345678901234567890123456789012345678901234567890"));
 }
 
-TEST_CONSTEXPR_CXX20 bool test() {
+TEST_CONSTEXPR_CXX20
+bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
-  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
 }
 
 #if TEST_STD_VER > 17
-constexpr bool test_constexpr() {
-  std::string str;
+template <class S>
+TEST_CONSTEXPR_CXX20 void test_string_constexpr() {
+  S str;
 
   size_t size = str.max_size();
   assert(size > 0);
+}
+
+TEST_CONSTEXPR_CXX20 bool test_constexpr() {
+  test_string_constexpr<std::string>();
+  test_string_constexpr<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 
   return true;
 }
 #endif
 
-int main(int, char**)
-{
+int main(int, char**) {
   test();
 #if TEST_STD_VER > 17
   test_constexpr();
diff --git a/libcxx/test/std/strings/basic.string/string.capacity/over_max_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.capacity/over_max_size.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.capacity/over_max_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.capacity/over_max_size.pass.cpp
@@ -24,17 +24,19 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
-void
-test(const S& s)
-{
-    assert(s.max_size() >= s.size());
-    S s2(s);
-    const size_t sz = s2.max_size() + 1;
-    try { s2.resize(sz, 'x'); }
-    catch ( const std::length_error & ) { return ; }
-    assert ( false );
+TEST_CONSTEXPR_CXX20 void test(const S& s) {
+  assert(s.max_size() >= s.size());
+  S s2(s);
+  const size_t sz = s2.max_size() + 1;
+  try {
+    s2.resize(sz, 'x');
+  } catch (const std::length_error&) {
+    return;
+  }
+  assert(false);
 }
 
 template <class S>
@@ -48,13 +50,13 @@
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
 }
 
-int main(int, char**)
-{
+int main(int, char**) {
   test();
 
   return 0;
diff --git a/libcxx/test/std/strings/basic.string/string.capacity/reserve.pass.cpp b/libcxx/test/std/strings/basic.string/string.capacity/reserve.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.capacity/reserve.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.capacity/reserve.pass.cpp
@@ -18,23 +18,22 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
-void
-test(typename S::size_type min_cap, typename S::size_type erased_index)
-{
-    S s(min_cap, 'a');
-    s.erase(erased_index);
-    assert(s.size() == erased_index);
-    assert(s.capacity() >= min_cap); // Check that we really have at least this capacity.
-
-    typename S::size_type old_cap = s.capacity();
-    S s0 = s;
-    s.reserve();
-    LIBCPP_ASSERT(s.__invariants());
-    assert(s == s0);
-    assert(s.capacity() <= old_cap);
-    assert(s.capacity() >= s.size());
+void test(typename S::size_type min_cap, typename S::size_type erased_index) {
+  S s(min_cap, 'a');
+  s.erase(erased_index);
+  assert(s.size() == erased_index);
+  assert(s.capacity() >= min_cap); // Check that we really have at least this capacity.
+
+  typename S::size_type old_cap = s.capacity();
+  S s0                          = s;
+  s.reserve();
+  LIBCPP_ASSERT(s.__invariants());
+  assert(s == s0);
+  assert(s.capacity() <= old_cap);
+  assert(s.capacity() >= s.size());
 }
 
 template <class S>
@@ -47,14 +46,14 @@
 bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
-  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
 }
 
-int main(int, char**)
-{
+int main(int, char**) {
   test();
 
   return 0;
diff --git a/libcxx/test/std/strings/basic.string/string.capacity/reserve_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.capacity/reserve_size.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.capacity/reserve_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.capacity/reserve_size.pass.cpp
@@ -20,45 +20,40 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
-test(typename S::size_type min_cap, typename S::size_type erased_index, typename S::size_type res_arg)
-{
-    S s(min_cap, 'a');
-    s.erase(erased_index);
-    assert(s.size() == erased_index);
-    assert(s.capacity() >= min_cap); // Check that we really have at least this capacity.
+test(typename S::size_type min_cap, typename S::size_type erased_index, typename S::size_type res_arg) {
+  S s(min_cap, 'a');
+  s.erase(erased_index);
+  assert(s.size() == erased_index);
+  assert(s.capacity() >= min_cap); // Check that we really have at least this capacity.
 
 #if TEST_STD_VER > 17
-    typename S::size_type old_cap = s.capacity();
+  typename S::size_type old_cap = s.capacity();
 #endif
-    S s0 = s;
-    if (res_arg <= s.max_size())
-    {
-        s.reserve(res_arg);
-        LIBCPP_ASSERT(s.__invariants());
-        assert(s == s0);
-        assert(s.capacity() >= res_arg);
-        assert(s.capacity() >= s.size());
+  S s0 = s;
+  if (res_arg <= s.max_size()) {
+    s.reserve(res_arg);
+    LIBCPP_ASSERT(s.__invariants());
+    assert(s == s0);
+    assert(s.capacity() >= res_arg);
+    assert(s.capacity() >= s.size());
 #if TEST_STD_VER > 17
-        assert(s.capacity() >= old_cap); // reserve never shrinks as of P0966 (C++20)
+    assert(s.capacity() >= old_cap); // reserve never shrinks as of P0966 (C++20)
 #endif
-    }
+  }
 #ifndef TEST_HAS_NO_EXCEPTIONS
-    else if (!TEST_IS_CONSTANT_EVALUATED)
-    {
-        try
-        {
-            s.reserve(res_arg);
-            LIBCPP_ASSERT(s.__invariants());
-            assert(false);
-        }
-        catch (std::length_error&)
-        {
-            assert(res_arg > s.max_size());
-        }
+  else if (!TEST_IS_CONSTANT_EVALUATED) {
+    try {
+      s.reserve(res_arg);
+      LIBCPP_ASSERT(s.__invariants());
+      assert(false);
+    } catch (std::length_error&) {
+      assert(res_arg > s.max_size());
     }
+  }
 #endif
 }
 
@@ -82,14 +77,14 @@
 TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
-  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
 }
 
-int main(int, char**)
-{
+int main(int, char**) {
   test();
 #if TEST_STD_VER > 17
   static_assert(test());
diff --git a/libcxx/test/std/strings/basic.string/string.capacity/resize_and_overwrite.pass.cpp b/libcxx/test/std/strings/basic.string/string.capacity/resize_and_overwrite.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.capacity/resize_and_overwrite.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.capacity/resize_and_overwrite.pass.cpp
@@ -19,6 +19,7 @@
 
 #include "make_string.h"
 #include "test_macros.h"
+#include "test_allocator.h"
 
 template <class S>
 constexpr void test_appending(size_t k, size_t N, size_t new_capacity) {
@@ -49,7 +50,7 @@
     LIBCPP_ASSERT(s.begin().base() == p);
     assert(std::all_of(p, p + n, [](auto ch) { return ch == 'a'; }));
     p[n - 1] = 'b';
-    p[n] = 'c'; // will be overwritten
+    p[n]     = 'c'; // will be overwritten
     return n;
   });
   const S expected = S(N - 1, 'a') + S(1, 'b');
@@ -57,9 +58,9 @@
   assert(s.c_str()[N] == '\0');
 }
 
-template <class CharT>
-constexpr bool test() {
-  using S = std::basic_string<CharT>;
+template <class CharT, template <class> class Alloc>
+constexpr bool test_string() {
+  using S = std::basic_string<CharT, std::char_traits<CharT>, Alloc<CharT>>;
   test_appending<S>(10, 15, 15);
   test_appending<S>(10, 15, 20);
   test_appending<S>(10, 40, 40);
@@ -85,19 +86,36 @@
 }
 
 int main(int, char**) {
-  test<char>();
-  test<char8_t>();
-  test<char16_t>();
-  test<char32_t>();
+  test_string<char, std::allocator>();
+  test_string<char, fancy_pointer_allocator>();
+
+  test_string<char8_t, std::allocator>();
+  test_string<char8_t, fancy_pointer_allocator>();
+
+  test_string<char16_t, std::allocator>();
+  test_string<char16_t, fancy_pointer_allocator>();
+
+  test_string<char32_t, std::allocator>();
+  test_string<char32_t, fancy_pointer_allocator>();
 
-  static_assert(test<char>());
-  static_assert(test<char8_t>());
-  static_assert(test<char16_t>());
-  static_assert(test<char32_t>());
+  static_assert(test_string<char, std::allocator>());
+  static_assert(test_string<char, fancy_pointer_allocator>());
+
+  static_assert(test_string<char8_t, std::allocator>());
+  static_assert(test_string<char8_t, fancy_pointer_allocator>());
+
+  static_assert(test_string<char16_t, std::allocator>());
+  static_assert(test_string<char16_t, fancy_pointer_allocator>());
+
+  static_assert(test_string<char32_t, std::allocator>());
+  static_assert(test_string<char32_t, fancy_pointer_allocator>());
 
 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
-  test<wchar_t>();
-  static_assert(test<wchar_t>());
+  test_string<wchar_t, std::allocator>();
+  test_string<wchar_t, fancy_pointer_allocator>();
+
+  static_assert(test_string<wchar_t, std::allocator>());
+  static_assert(test_string<wchar_t, fancy_pointer_allocator>());
 #endif
   return 0;
 }
diff --git a/libcxx/test/std/strings/basic.string/string.capacity/resize_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.capacity/resize_size.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.capacity/resize_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.capacity/resize_size.pass.cpp
@@ -16,30 +16,24 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
-TEST_CONSTEXPR_CXX20 void
-test(S s, typename S::size_type n, S expected)
-{
-    if (n <= s.max_size())
-    {
-        s.resize(n);
-        LIBCPP_ASSERT(s.__invariants());
-        assert(s == expected);
-    }
+TEST_CONSTEXPR_CXX20 void test(S s, typename S::size_type n, S expected) {
+  if (n <= s.max_size()) {
+    s.resize(n);
+    LIBCPP_ASSERT(s.__invariants());
+    assert(s == expected);
+  }
 #ifndef TEST_HAS_NO_EXCEPTIONS
-    else if (!TEST_IS_CONSTANT_EVALUATED)
-    {
-        try
-        {
-            s.resize(n);
-            assert(false);
-        }
-        catch (std::length_error&)
-        {
-            assert(n > s.max_size());
-        }
+  else if (!TEST_IS_CONSTANT_EVALUATED) {
+    try {
+      s.resize(n);
+      assert(false);
+    } catch (std::length_error&) {
+      assert(n > s.max_size());
     }
+  }
 #endif
 }
 
@@ -65,15 +59,16 @@
 
 TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
+
 #if TEST_STD_VER >= 11
-  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
 }
 
-int main(int, char**)
-{
+int main(int, char**) {
   test();
 #if TEST_STD_VER > 17
   static_assert(test());
diff --git a/libcxx/test/std/strings/basic.string/string.capacity/resize_size_char.pass.cpp b/libcxx/test/std/strings/basic.string/string.capacity/resize_size_char.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.capacity/resize_size_char.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.capacity/resize_size_char.pass.cpp
@@ -16,30 +16,24 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
-TEST_CONSTEXPR_CXX20 void
-test(S s, typename S::size_type n, typename S::value_type c, S expected)
-{
-    if (n <= s.max_size())
-    {
-        s.resize(n, c);
-        LIBCPP_ASSERT(s.__invariants());
-        assert(s == expected);
-    }
+TEST_CONSTEXPR_CXX20 void test(S s, typename S::size_type n, typename S::value_type c, S expected) {
+  if (n <= s.max_size()) {
+    s.resize(n, c);
+    LIBCPP_ASSERT(s.__invariants());
+    assert(s == expected);
+  }
 #ifndef TEST_HAS_NO_EXCEPTIONS
-    else if (!TEST_IS_CONSTANT_EVALUATED)
-    {
-        try
-        {
-            s.resize(n, c);
-            assert(false);
-        }
-        catch (std::length_error&)
-        {
-            assert(n > s.max_size());
-        }
+  else if (!TEST_IS_CONSTANT_EVALUATED) {
+    try {
+      s.resize(n, c);
+      assert(false);
+    } catch (std::length_error&) {
+      assert(n > s.max_size());
     }
+  }
 #endif
 }
 
@@ -66,14 +60,14 @@
 TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
-  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
 }
 
-int main(int, char**)
-{
+int main(int, char**) {
   test();
 #if TEST_STD_VER > 17
   static_assert(test());
diff --git a/libcxx/test/std/strings/basic.string/string.capacity/shrink_to_fit.pass.cpp b/libcxx/test/std/strings/basic.string/string.capacity/shrink_to_fit.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.capacity/shrink_to_fit.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.capacity/shrink_to_fit.pass.cpp
@@ -15,18 +15,17 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
-TEST_CONSTEXPR_CXX20 void
-test(S s)
-{
-    typename S::size_type old_cap = s.capacity();
-    S s0 = s;
-    s.shrink_to_fit();
-    LIBCPP_ASSERT(s.__invariants());
-    assert(s == s0);
-    assert(s.capacity() <= old_cap);
-    assert(s.capacity() >= s.size());
+TEST_CONSTEXPR_CXX20 void test(S s) {
+  typename S::size_type old_cap = s.capacity();
+  S s0                          = s;
+  s.shrink_to_fit();
+  LIBCPP_ASSERT(s.__invariants());
+  assert(s == s0);
+  assert(s.capacity() <= old_cap);
+  assert(s.capacity() >= s.size());
 }
 
 template <class S>
@@ -47,13 +46,13 @@
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
 }
 
-int main(int, char**)
-{
+int main(int, char**) {
   test();
 #if TEST_STD_VER > 17
   static_assert(test());
diff --git a/libcxx/test/std/strings/basic.string/string.capacity/size.pass.cpp b/libcxx/test/std/strings/basic.string/string.capacity/size.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.capacity/size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.capacity/size.pass.cpp
@@ -15,12 +15,11 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
-TEST_CONSTEXPR_CXX20 void
-test(const S& s, typename S::size_type c)
-{
-    assert(s.size() == c);
+TEST_CONSTEXPR_CXX20 void test(const S& s, typename S::size_type c) {
+  assert(s.size() == c);
 }
 
 template <class S>
@@ -33,14 +32,14 @@
 TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
-  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
 }
 
-int main(int, char**)
-{
+int main(int, char**) {
   test();
 #if TEST_STD_VER > 17
   static_assert(test());
diff --git a/libcxx/test/std/strings/basic.string/string.cons/T_size_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.cons/T_size_size.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.cons/T_size_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.cons/T_size_size.pass.cpp
@@ -25,168 +25,160 @@
 #include "min_allocator.h"
 
 template <class S, class SV>
-TEST_CONSTEXPR_CXX20 void
-test(SV sv, std::size_t pos, std::size_t n)
-{
-    typedef typename S::traits_type T;
-    typedef typename S::allocator_type A;
-    typedef typename S::size_type Size;
-    if (pos <= sv.size())
-    {
-        S s2(sv, static_cast<Size>(pos), static_cast<Size>(n));
-        LIBCPP_ASSERT(s2.__invariants());
-        assert(pos <= sv.size());
-        std::size_t rlen = std::min(sv.size() - pos, n);
-        assert(s2.size() == rlen);
-        assert(T::compare(s2.data(), sv.data() + pos, rlen) == 0);
-        assert(s2.get_allocator() == A());
-        assert(s2.capacity() >= s2.size());
-    }
+TEST_CONSTEXPR_CXX20 void test(SV sv, std::size_t pos, std::size_t n) {
+  typedef typename S::traits_type T;
+  typedef typename S::allocator_type A;
+  typedef typename S::size_type Size;
+  if (pos <= sv.size()) {
+    S s2(sv, static_cast<Size>(pos), static_cast<Size>(n));
+    LIBCPP_ASSERT(s2.__invariants());
+    assert(pos <= sv.size());
+    std::size_t rlen = std::min(sv.size() - pos, n);
+    assert(s2.size() == rlen);
+    assert(T::compare(s2.data(), sv.data() + pos, rlen) == 0);
+    assert(s2.get_allocator() == A());
+    assert(s2.capacity() >= s2.size());
+  }
 #ifndef TEST_HAS_NO_EXCEPTIONS
-    else if (!TEST_IS_CONSTANT_EVALUATED)
-    {
-        try
-        {
-            S s2(sv, static_cast<Size>(pos), static_cast<Size>(n));
-            assert(false);
-        }
-        catch (std::out_of_range&)
-        {
-            assert(pos > sv.size());
-        }
+  else if (!TEST_IS_CONSTANT_EVALUATED) {
+    try {
+      S s2(sv, static_cast<Size>(pos), static_cast<Size>(n));
+      assert(false);
+    } catch (std::out_of_range&) {
+      assert(pos > sv.size());
     }
+  }
 #endif
 }
 
 template <class S, class SV>
-TEST_CONSTEXPR_CXX20 void
-test(SV sv, std::size_t pos, std::size_t n, const typename S::allocator_type& a)
-{
-    typedef typename S::traits_type T;
-    typedef typename S::size_type Size;
-    if (pos <= sv.size())
-    {
-        S s2(sv, static_cast<Size>(pos), static_cast<Size>(n), a);
-        LIBCPP_ASSERT(s2.__invariants());
-        assert(pos <= sv.size());
-        std::size_t rlen = std::min(sv.size() - pos, n);
-        assert(s2.size() == rlen);
-        assert(T::compare(s2.data(), sv.data() + pos, rlen) == 0);
-        assert(s2.get_allocator() == a);
-        assert(s2.capacity() >= s2.size());
-    }
+TEST_CONSTEXPR_CXX20 void test(SV sv, std::size_t pos, std::size_t n, const typename S::allocator_type& a) {
+  typedef typename S::traits_type T;
+  typedef typename S::size_type Size;
+  if (pos <= sv.size()) {
+    S s2(sv, static_cast<Size>(pos), static_cast<Size>(n), a);
+    LIBCPP_ASSERT(s2.__invariants());
+    assert(pos <= sv.size());
+    std::size_t rlen = std::min(sv.size() - pos, n);
+    assert(s2.size() == rlen);
+    assert(T::compare(s2.data(), sv.data() + pos, rlen) == 0);
+    assert(s2.get_allocator() == a);
+    assert(s2.capacity() >= s2.size());
+  }
 #ifndef TEST_HAS_NO_EXCEPTIONS
-    else if (!TEST_IS_CONSTANT_EVALUATED)
-    {
-        try
-        {
-            S s2(sv, static_cast<Size>(pos), static_cast<Size>(n), a);
-            assert(false);
-        }
-        catch (std::out_of_range&)
-        {
-            assert(pos > sv.size());
-        }
+  else if (!TEST_IS_CONSTANT_EVALUATED) {
+    try {
+      S s2(sv, static_cast<Size>(pos), static_cast<Size>(n), a);
+      assert(false);
+    } catch (std::out_of_range&) {
+      assert(pos > sv.size());
     }
+  }
 #endif
 }
 
-TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef test_allocator<char> A;
-    typedef std::basic_string_view<char, std::char_traits<char> > SV;
-    typedef std::basic_string     <char, std::char_traits<char>, A> S;
-
-    test<S,SV>(SV(), 0, 0);
-    test<S,SV>(SV(), 0, 1);
-    test<S,SV>(SV(), 1, 0);
-    test<S,SV>(SV(), 1, 1);
-    test<S,SV>(SV(), 1, 2);
-    test<S,SV>(SV("1"), 0, 0);
-    test<S,SV>(SV("1"), 0, 1);
-    test<S,SV>(SV("1234567890123456789012345678901234567890123456789012345678901234567890"), 50,   0);
-    test<S,SV>(SV("1234567890123456789012345678901234567890123456789012345678901234567890"), 50,   1);
-    test<S,SV>(SV("1234567890123456789012345678901234567890123456789012345678901234567890"), 50,  10);
-    test<S,SV>(SV("1234567890123456789012345678901234567890123456789012345678901234567890"), 50, 100);
-
-    test<S,SV>(SV(), 0, 0, A(4));
-    test<S,SV>(SV(), 0, 1, A(4));
-    test<S,SV>(SV(), 1, 0, A(4));
-    test<S,SV>(SV(), 1, 1, A(4));
-    test<S,SV>(SV(), 1, 2, A(4));
-    test<S,SV>(SV("1"), 0, 0, A(6));
-    test<S,SV>(SV("1"), 0, 1, A(6));
-    test<S,SV>(SV("1234567890123456789012345678901234567890123456789012345678901234567890"), 50,   0, A(8));
-    test<S,SV>(SV("1234567890123456789012345678901234567890123456789012345678901234567890"), 50,   1, A(8));
-    test<S,SV>(SV("1234567890123456789012345678901234567890123456789012345678901234567890"), 50,  10, A(8));
-    test<S,SV>(SV("1234567890123456789012345678901234567890123456789012345678901234567890"), 50, 100, A(8));
-  }
+template <class CharT, template <class> class Alloc>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  using A  = Alloc<CharT>;
+  using S  = std::basic_string<CharT, std::char_traits<CharT>, A>;
+  using SV = std::basic_string_view< CharT, std::char_traits<CharT>>;
+
+  test<S, SV>(SV(), 0, 0);
+  test<S, SV>(SV(), 0, 1);
+  test<S, SV>(SV(), 1, 0);
+  test<S, SV>(SV(), 1, 1);
+  test<S, SV>(SV(), 1, 2);
+  test<S, SV>(SV("1"), 0, 0);
+  test<S, SV>(SV("1"), 0, 1);
+  test<S, SV>(SV("1234567890123456789012345678901234567890123456789012345678901234567890"), 50, 0);
+  test<S, SV>(SV("1234567890123456789012345678901234567890123456789012345678901234567890"), 50, 1);
+  test<S, SV>(SV("1234567890123456789012345678901234567890123456789012345678901234567890"), 50, 10);
+  test<S, SV>(SV("1234567890123456789012345678901234567890123456789012345678901234567890"), 50, 100);
+
+  test<S, SV>(SV(), 0, 0, A());
+  test<S, SV>(SV(), 0, 1, A());
+  test<S, SV>(SV(), 1, 0, A());
+  test<S, SV>(SV(), 1, 1, A());
+  test<S, SV>(SV(), 1, 2, A());
+  test<S, SV>(SV("1"), 0, 0, A());
+  test<S, SV>(SV("1"), 0, 1, A());
+  test<S, SV>(SV("1234567890123456789012345678901234567890123456789012345678901234567890"), 50, 0, A());
+  test<S, SV>(SV("1234567890123456789012345678901234567890123456789012345678901234567890"), 50, 1, A());
+  test<S, SV>(SV("1234567890123456789012345678901234567890123456789012345678901234567890"), 50, 10, A());
+  test<S, SV>(SV("1234567890123456789012345678901234567890123456789012345678901234567890"), 50, 100, A());
+}
+
+template <>
+TEST_CONSTEXPR_CXX20 void test_string<char, test_allocator>() {
+  using A  = test_allocator<char>;
+  using S  = std::basic_string<char, std::char_traits<char>, A>;
+  using SV = std::basic_string_view< char, std::char_traits<char>>;
+
+  test<S, SV>(SV(), 0, 0);
+  test<S, SV>(SV(), 0, 1);
+  test<S, SV>(SV(), 1, 0);
+  test<S, SV>(SV(), 1, 1);
+  test<S, SV>(SV(), 1, 2);
+  test<S, SV>(SV("1"), 0, 0);
+  test<S, SV>(SV("1"), 0, 1);
+  test<S, SV>(SV("1234567890123456789012345678901234567890123456789012345678901234567890"), 50, 0);
+  test<S, SV>(SV("1234567890123456789012345678901234567890123456789012345678901234567890"), 50, 1);
+  test<S, SV>(SV("1234567890123456789012345678901234567890123456789012345678901234567890"), 50, 10);
+  test<S, SV>(SV("1234567890123456789012345678901234567890123456789012345678901234567890"), 50, 100);
+
+  test<S, SV>(SV(), 0, 0, A(4));
+  test<S, SV>(SV(), 0, 1, A(4));
+  test<S, SV>(SV(), 1, 0, A(4));
+  test<S, SV>(SV(), 1, 1, A(4));
+  test<S, SV>(SV(), 1, 2, A(4));
+  test<S, SV>(SV("1"), 0, 0, A(6));
+  test<S, SV>(SV("1"), 0, 1, A(6));
+  test<S, SV>(SV("1234567890123456789012345678901234567890123456789012345678901234567890"), 50, 0, A(8));
+  test<S, SV>(SV("1234567890123456789012345678901234567890123456789012345678901234567890"), 50, 1, A(8));
+  test<S, SV>(SV("1234567890123456789012345678901234567890123456789012345678901234567890"), 50, 10, A(8));
+  test<S, SV>(SV("1234567890123456789012345678901234567890123456789012345678901234567890"), 50, 100, A(8));
+}
 
+TEST_CONSTEXPR_CXX20 bool test() {
+  test_string<char, std::allocator>();
+  test_string<char, test_allocator>();
 #if TEST_STD_VER >= 11
-  {
-    typedef min_allocator<char> A;
-    typedef std::basic_string_view<char, std::char_traits<char> > SV;
-    typedef std::basic_string     <char, std::char_traits<char>, A> S;
-
-    test<S,SV>(SV(), 0, 0);
-    test<S,SV>(SV(), 0, 1);
-    test<S,SV>(SV(), 1, 0);
-    test<S,SV>(SV(), 1, 1);
-    test<S,SV>(SV(), 1, 2);
-    test<S,SV>(SV("1"), 0, 0);
-    test<S,SV>(SV("1"), 0, 1);
-    test<S,SV>(SV("1234567890123456789012345678901234567890123456789012345678901234567890"), 50, 0);
-    test<S,SV>(SV("1234567890123456789012345678901234567890123456789012345678901234567890"), 50, 1);
-    test<S,SV>(SV("1234567890123456789012345678901234567890123456789012345678901234567890"), 50, 10);
-    test<S,SV>(SV("1234567890123456789012345678901234567890123456789012345678901234567890"), 50, 100);
-
-    test<S,SV>(SV(), 0, 0, A());
-    test<S,SV>(SV(), 0, 1, A());
-    test<S,SV>(SV(), 1, 0, A());
-    test<S,SV>(SV(), 1, 1, A());
-    test<S,SV>(SV(), 1, 2, A());
-    test<S,SV>(SV("1"), 0, 0, A());
-    test<S,SV>(SV("1"), 0, 1, A());
-    test<S,SV>(SV("1234567890123456789012345678901234567890123456789012345678901234567890"), 50, 0, A());
-    test<S,SV>(SV("1234567890123456789012345678901234567890123456789012345678901234567890"), 50, 1, A());
-    test<S,SV>(SV("1234567890123456789012345678901234567890123456789012345678901234567890"), 50, 10, A());
-    test<S,SV>(SV("1234567890123456789012345678901234567890123456789012345678901234567890"), 50, 100, A());
-  }
+  test_string<char, min_allocator>();
+  test_string<char, fancy_pointer_allocator>();
 #endif
   {
-    typedef std::string S;
-    typedef std::string_view SV;
-    S s = "ABCD";
-    SV sv = "EFGH";
+    using S    = std::string;
+    using SV   = std::string_view;
+    S s        = "ABCD";
+    SV sv      = "EFGH";
     char arr[] = "IJKL";
 
-    S s1("CDEF", 4);    // calls ctor(const char *, len)
+    S s1("CDEF", 4); // calls ctor(const char *, len)
     assert(s1 == "CDEF");
 
     S s2("QRST", 0, 3); // calls ctor(string("QRST", pos, len)
     assert(s2 == "QRS");
 
-    S s3(sv, 0, std::string::npos);   // calls ctor(T, pos, npos)
+    S s3(sv, 0, std::string::npos); // calls ctor(T, pos, npos)
     assert(s3 == sv);
 
-    S s4(sv, 0, 3);   // calls ctor(T, pos, len)
+    S s4(sv, 0, 3); // calls ctor(T, pos, len)
     assert(s4 == "EFG");
 
-    S s5(arr, 0, 2);     // calls ctor(const char *, len)
+    S s5(arr, 0, 2); // calls ctor(const char *, len)
     assert(s5 == "IJ");
 
-    S s6(arr, 0);     // calls ctor(const char *, len)
+    S s6(arr, 0); // calls ctor(const char *, len)
     assert(s6 == "");
 
-    S s7(s.data(), 2);     // calls ctor(const char *, len)
+    S s7(s.data(), 2); // calls ctor(const char *, len)
     assert(s7 == "AB");
   }
 
   return true;
 }
 
-int main(int, char**)
-{
+int main(int, char**) {
   test();
 #if TEST_STD_VER > 17
   static_assert(test());
diff --git a/libcxx/test/std/strings/basic.string/string.cons/alloc.pass.cpp b/libcxx/test/std/strings/basic.string/string.cons/alloc.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.cons/alloc.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.cons/alloc.pass.cpp
@@ -16,6 +16,7 @@
 #include "test_macros.h"
 #include "test_allocator.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -89,6 +90,7 @@
   test<std::basic_string<char, std::char_traits<char>, test_allocator<char> > >();
 #if TEST_STD_VER >= 11
   test2<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test2<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
   test2<std::basic_string<char, std::char_traits<char>, explicit_allocator<char> > >();
 #endif
 
diff --git a/libcxx/test/std/strings/basic.string/string.cons/char_assignment.pass.cpp b/libcxx/test/std/strings/basic.string/string.cons/char_assignment.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.cons/char_assignment.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.cons/char_assignment.pass.cpp
@@ -15,17 +15,16 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
-TEST_CONSTEXPR_CXX20 void
-test(S s1, typename S::value_type s2)
-{
-    typedef typename S::traits_type T;
-    s1 = s2;
-    LIBCPP_ASSERT(s1.__invariants());
-    assert(s1.size() == 1);
-    assert(T::eq(s1[0], s2));
-    assert(s1.capacity() >= s1.size());
+TEST_CONSTEXPR_CXX20 void test(S s1, typename S::value_type s2) {
+  typedef typename S::traits_type T;
+  s1 = s2;
+  LIBCPP_ASSERT(s1.__invariants());
+  assert(s1.size() == 1);
+  assert(T::eq(s1[0], s2));
+  assert(s1.capacity() >= s1.size());
 }
 
 template <class S>
@@ -38,15 +37,16 @@
 
 TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
+
 #if TEST_STD_VER >= 11
-  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
 }
 
-int main(int, char**)
-{
+int main(int, char**) {
   test();
 #if TEST_STD_VER > 17
   static_assert(test());
diff --git a/libcxx/test/std/strings/basic.string/string.cons/copy.pass.cpp b/libcxx/test/std/strings/basic.string/string.cons/copy.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.cons/copy.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.cons/copy.pass.cpp
@@ -18,39 +18,44 @@
 #include "min_allocator.h"
 
 template <class S>
-TEST_CONSTEXPR_CXX20 void
-test(S s1)
-{
-    S s2 = s1;
-    LIBCPP_ASSERT(s2.__invariants());
-    assert(s2 == s1);
-    assert(s2.capacity() >= s2.size());
-    assert(s2.get_allocator() == s1.get_allocator());
+TEST_CONSTEXPR_CXX20 void test(S s1) {
+  S s2 = s1;
+  LIBCPP_ASSERT(s2.__invariants());
+  assert(s2 == s1);
+  assert(s2.capacity() >= s2.size());
+  assert(s2.get_allocator() == s1.get_allocator());
+}
+
+template <class CharT, template <class> class Alloc>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  using A = Alloc<CharT>;
+  using S = std::basic_string<CharT, std::char_traits<CharT>, A>;
+  test(S(A()));
+  test(S("1", A()));
+  test(S("1234567890123456789012345678901234567890123456789012345678901234567890", A()));
+}
+
+template <>
+TEST_CONSTEXPR_CXX20 void test_string<char, test_allocator>() {
+  using A = test_allocator<char>;
+  using S = std::basic_string<char, std::char_traits<char>, A>;
+  test(S(A(3)));
+  test(S("1", A(5)));
+  test(S("1234567890123456789012345678901234567890123456789012345678901234567890", A(7)));
 }
 
 TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef test_allocator<char> A;
-    typedef std::basic_string<char, std::char_traits<char>, A> S;
-    test(S(A(3)));
-    test(S("1", A(5)));
-    test(S("1234567890123456789012345678901234567890123456789012345678901234567890", A(7)));
-  }
+  test_string<char, std::allocator>();
+  test_string<char, test_allocator>();
 #if TEST_STD_VER >= 11
-  {
-    typedef min_allocator<char> A;
-    typedef std::basic_string<char, std::char_traits<char>, A> S;
-    test(S(A{}));
-    test(S("1", A()));
-    test(S("1234567890123456789012345678901234567890123456789012345678901234567890", A()));
-  }
+  test_string<char, min_allocator>();
+  test_string<char, fancy_pointer_allocator>();
 #endif
 
   return true;
 }
 
-int main(int, char**)
-{
+int main(int, char**) {
   test();
 #if TEST_STD_VER > 17
   static_assert(test());
diff --git a/libcxx/test/std/strings/basic.string/string.cons/copy_alloc.pass.cpp b/libcxx/test/std/strings/basic.string/string.cons/copy_alloc.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.cons/copy_alloc.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.cons/copy_alloc.pass.cpp
@@ -19,98 +19,102 @@
 
 #ifndef TEST_HAS_NO_EXCEPTIONS
 struct alloc_imp {
-    bool active;
-
-    TEST_CONSTEXPR alloc_imp() : active(true) {}
-
-    template <class T>
-    T* allocate(std::size_t n)
-    {
-        if (active)
-            return static_cast<T*>(std::malloc(n * sizeof(T)));
-        else
-            throw std::bad_alloc();
-    }
-
-    template <class T>
-    void deallocate(T* p, std::size_t) { std::free(p); }
-    void activate  ()                  { active = true; }
-    void deactivate()                  { active = false; }
+  bool active;
+
+  TEST_CONSTEXPR alloc_imp() : active(true) {}
+
+  template <class T>
+  T* allocate(std::size_t n) {
+    if (active)
+      return static_cast<T*>(std::malloc(n * sizeof(T)));
+    else
+      throw std::bad_alloc();
+  }
+
+  template <class T>
+  void deallocate(T* p, std::size_t) {
+    std::free(p);
+  }
+  void activate() { active = true; }
+  void deactivate() { active = false; }
 };
 
 template <class T>
 struct poca_alloc {
-    typedef T value_type;
-    typedef std::true_type propagate_on_container_copy_assignment;
+  typedef T value_type;
+  typedef std::true_type propagate_on_container_copy_assignment;
 
-    alloc_imp *imp;
+  alloc_imp* imp;
 
-    TEST_CONSTEXPR poca_alloc(alloc_imp *imp_) : imp (imp_) {}
+  TEST_CONSTEXPR poca_alloc(alloc_imp* imp_) : imp(imp_) {}
 
-    template <class U>
-    TEST_CONSTEXPR poca_alloc(const poca_alloc<U>& other) : imp(other.imp) {}
+  template <class U>
+  TEST_CONSTEXPR poca_alloc(const poca_alloc<U>& other) : imp(other.imp) {}
 
-    T*   allocate  (std::size_t n)       { return imp->allocate<T>(n);}
-    void deallocate(T* p, std::size_t n) { imp->deallocate(p, n); }
+  T* allocate(std::size_t n) { return imp->allocate<T>(n); }
+  void deallocate(T* p, std::size_t n) { imp->deallocate(p, n); }
 };
 
 template <typename T, typename U>
-bool operator==(const poca_alloc<T>& lhs, const poca_alloc<U>& rhs)
-{
-    return lhs.imp == rhs.imp;
+bool operator==(const poca_alloc<T>& lhs, const poca_alloc<U>& rhs) {
+  return lhs.imp == rhs.imp;
 }
 
 template <typename T, typename U>
-bool operator!=(const poca_alloc<T>& lhs, const poca_alloc<U>& rhs)
-{
-    return lhs.imp != rhs.imp;
+bool operator!=(const poca_alloc<T>& lhs, const poca_alloc<U>& rhs) {
+  return lhs.imp != rhs.imp;
 }
 
 template <class S>
-TEST_CONSTEXPR_CXX20 void test_assign(S &s1, const S& s2)
-{
-    try { s1 = s2; }
-    catch ( std::bad_alloc &) { return; }
-    assert(false);
+TEST_CONSTEXPR_CXX20 void test_assign(S& s1, const S& s2) {
+  try {
+    s1 = s2;
+  } catch (std::bad_alloc&) {
+    return;
+  }
+  assert(false);
 }
 #endif
 
+template <class S>
+TEST_CONSTEXPR_CXX20 void test(S s1, const typename S::allocator_type& a) {
+  S s2(s1, a);
+  LIBCPP_ASSERT(s2.__invariants());
+  assert(s2 == s1);
+  assert(s2.capacity() >= s2.size());
+  assert(s2.get_allocator() == a);
+}
 
+template <class CharT, template <class> class Alloc>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  using A = Alloc<CharT>;
+  using S = std::basic_string<CharT, std::char_traits<CharT>, A>;
+  test(S(), A());
+  test(S("1"), A());
+  test(S("1234567890123456789012345678901234567890123456789012345678901234567890"), A());
+}
 
-template <class S>
-TEST_CONSTEXPR_CXX20 void
-test(S s1, const typename S::allocator_type& a)
-{
-    S s2(s1, a);
-    LIBCPP_ASSERT(s2.__invariants());
-    assert(s2 == s1);
-    assert(s2.capacity() >= s2.size());
-    assert(s2.get_allocator() == a);
+template <>
+TEST_CONSTEXPR_CXX20 void test_string<char, test_allocator>() {
+  using A = test_allocator<char>;
+  using S = std::basic_string<char, std::char_traits<char>, A>;
+  test(S(), A(3));
+  test(S("1"), A(5));
+  test(S("1234567890123456789012345678901234567890123456789012345678901234567890"), A(7));
 }
 
 TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef test_allocator<char> A;
-    typedef std::basic_string<char, std::char_traits<char>, A> S;
-    test(S(), A(3));
-    test(S("1"), A(5));
-    test(S("1234567890123456789012345678901234567890123456789012345678901234567890"), A(7));
-  }
+  test_string<char, test_allocator>();
 #if TEST_STD_VER >= 11
-  {
-    typedef min_allocator<char> A;
-    typedef std::basic_string<char, std::char_traits<char>, A> S;
-    test(S(), A());
-    test(S("1"), A());
-    test(S("1234567890123456789012345678901234567890123456789012345678901234567890"), A());
-  }
+  test_string<char, min_allocator>();
+  test_string<char, fancy_pointer_allocator>();
 
-#ifndef TEST_HAS_NO_EXCEPTIONS
+#  ifndef TEST_HAS_NO_EXCEPTIONS
   if (!TEST_IS_CONSTANT_EVALUATED) {
     typedef poca_alloc<char> A;
     typedef std::basic_string<char, std::char_traits<char>, A> S;
-    const char * p1 = "This is my first string";
-    const char * p2 = "This is my second string";
+    const char* p1 = "This is my first string";
+    const char* p2 = "This is my second string";
 
     alloc_imp imp1;
     alloc_imp imp2;
@@ -125,14 +129,13 @@
     assert(s1 == p1);
     assert(s2 == p2);
   }
-#endif
+#  endif
 #endif
 
   return true;
 }
 
-int main(int, char**)
-{
+int main(int, char**) {
   test();
 #if TEST_STD_VER > 17
   static_assert(test());
diff --git a/libcxx/test/std/strings/basic.string/string.cons/default.pass.cpp b/libcxx/test/std/strings/basic.string/string.cons/default.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.cons/default.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.cons/default.pass.cpp
@@ -21,6 +21,9 @@
 LIBCPP_STATIC_ASSERT(std::is_nothrow_default_constructible<std::string>::value, "");
 LIBCPP_STATIC_ASSERT(std::is_nothrow_default_constructible<
                      std::basic_string<char, std::char_traits<char>, test_allocator<char>>>::value, "");
+LIBCPP_STATIC_ASSERT(std::is_nothrow_default_constructible<
+                         std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>::value,
+                     "");
 LIBCPP_STATIC_ASSERT(!std::is_nothrow_default_constructible<
                      std::basic_string<char, std::char_traits<char>, limited_allocator<char, 10>>>::value, "");
 #endif
diff --git a/libcxx/test/std/strings/basic.string/string.cons/dtor.pass.cpp b/libcxx/test/std/strings/basic.string/string.cons/dtor.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.cons/dtor.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.cons/dtor.pass.cpp
@@ -37,6 +37,9 @@
 static_assert(std::is_nothrow_destructible<std::string>::value, "");
 static_assert(std::is_nothrow_destructible<
                 std::basic_string<char, std::char_traits<char>, test_allocator<char>>>::value, "");
+static_assert(std::is_nothrow_destructible<
+                  std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>::value,
+              "");
 LIBCPP_STATIC_ASSERT(!std::is_nothrow_destructible<
                      std::basic_string<char, std::char_traits<char>, throwing_alloc<char>>>::value, "");
 
diff --git a/libcxx/test/std/strings/basic.string/string.cons/initializer_list.pass.cpp b/libcxx/test/std/strings/basic.string/string.cons/initializer_list.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.cons/initializer_list.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.cons/initializer_list.pass.cpp
@@ -19,37 +19,29 @@
 #include "test_allocator.h"
 #include "min_allocator.h"
 
-TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    std::string s = {'a', 'b', 'c'};
-    assert(s == "abc");
-  }
-#ifndef TEST_HAS_NO_WIDE_CHARACTERS
-  {
-    std::wstring s;
-    s = {L'a', L'b', L'c'};
-    assert(s == L"abc");
-  }
-#endif
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    S s = {'a', 'b', 'c'};
-    assert(s == "abc");
-  }
+template <template <class> class Alloc>
+TEST_CONSTEXPR_CXX20 void
+test_string(){{std::basic_string<char, std::char_traits<char>, Alloc<char>> s = {'a', 'b', 'c'};
+assert(s == "abc");
+}
 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
-  {
-    typedef std::basic_string<wchar_t, std::char_traits<wchar_t>, min_allocator<wchar_t>> S;
-    S s;
-    s = {L'a', L'b', L'c'};
-    assert(s == L"abc");
-  }
+{
+  std::basic_string<wchar_t, std::char_traits<wchar_t>, Alloc<wchar_t>> s;
+  s = {L'a', L'b', L'c'};
+  assert(s == L"abc");
+}
 #endif
+}
+
+TEST_CONSTEXPR_CXX20 bool test() {
+  test_string<std::allocator>();
+  test_string<min_allocator>();
+  test_string<fancy_pointer_allocator>();
 
   return true;
 }
 
-int main(int, char**)
-{
+int main(int, char**) {
   test();
 #if TEST_STD_VER > 17
   static_assert(test());
diff --git a/libcxx/test/std/strings/basic.string/string.cons/initializer_list_assignment.pass.cpp b/libcxx/test/std/strings/basic.string/string.cons/initializer_list_assignment.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.cons/initializer_list_assignment.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.cons/initializer_list_assignment.pass.cpp
@@ -17,25 +17,24 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
+
+template <class S>
+TEST_CONSTEXPR_CXX20 void test_case() {
+  S s;
+  s = {'a', 'b', 'c'};
+  assert(s == "abc");
+}
 
 TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    std::string s;
-    s = {'a', 'b', 'c'};
-    assert(s == "abc");
-  }
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    S s;
-    s = {'a', 'b', 'c'};
-    assert(s == "abc");
-  }
+  test_case<std::string>();
+  test_case<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_case<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 
   return true;
 }
 
-int main(int, char**)
-{
+int main(int, char**) {
   test();
 #if TEST_STD_VER > 17
   static_assert(test());
diff --git a/libcxx/test/std/strings/basic.string/string.cons/iter_alloc.pass.cpp b/libcxx/test/std/strings/basic.string/string.cons/iter_alloc.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.cons/iter_alloc.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.cons/iter_alloc.pass.cpp
@@ -12,7 +12,6 @@
 //   basic_string(InputIterator begin, InputIterator end,
 //   const Allocator& a = Allocator()); // constexpr since C++20
 
-
 #include <string>
 #include <iterator>
 #include <cassert>
@@ -24,118 +23,84 @@
 #include "min_allocator.h"
 
 template <class It>
-TEST_CONSTEXPR_CXX20 void
-test(It first, It last)
-{
-    typedef typename std::iterator_traits<It>::value_type charT;
-    typedef std::basic_string<charT, std::char_traits<charT>, test_allocator<charT> > S;
-    typedef typename S::allocator_type A;
-    S s2(first, last);
-    LIBCPP_ASSERT(s2.__invariants());
-    assert(s2.size() == static_cast<std::size_t>(std::distance(first, last)));
-    unsigned i = 0;
-    for (It it = first; it != last;) {
-        assert(s2[i] == *it);
-        ++it;
-        ++i;
-    }
-    assert(s2.get_allocator() == A());
-    assert(s2.capacity() >= s2.size());
+TEST_CONSTEXPR_CXX20 void test(It first, It last) {
+  typedef typename std::iterator_traits<It>::value_type charT;
+  typedef std::basic_string<charT, std::char_traits<charT>, test_allocator<charT> > S;
+  typedef typename S::allocator_type A;
+  S s2(first, last);
+  LIBCPP_ASSERT(s2.__invariants());
+  assert(s2.size() == static_cast<std::size_t>(std::distance(first, last)));
+  unsigned i = 0;
+  for (It it = first; it != last;) {
+    assert(s2[i] == *it);
+    ++it;
+    ++i;
+  }
+  assert(s2.get_allocator() == A());
+  assert(s2.capacity() >= s2.size());
 }
 
 template <class It, class A>
-TEST_CONSTEXPR_CXX20 void
-test(It first, It last, const A& a)
-{
-    typedef typename std::iterator_traits<It>::value_type charT;
-    typedef std::basic_string<charT, std::char_traits<charT>, A> S;
-    S s2(first, last, a);
-    LIBCPP_ASSERT(s2.__invariants());
-    assert(s2.size() == static_cast<std::size_t>(std::distance(first, last)));
-    unsigned i = 0;
-    for (It it = first; it != last;) {
-        assert(s2[i] == *it);
-        ++it;
-        ++i;
-    }
-    assert(s2.get_allocator() == a);
-    assert(s2.capacity() >= s2.size());
+TEST_CONSTEXPR_CXX20 void test(It first, It last, const A& a) {
+  typedef typename std::iterator_traits<It>::value_type charT;
+  typedef std::basic_string<charT, std::char_traits<charT>, A> S;
+  S s2(first, last, a);
+  LIBCPP_ASSERT(s2.__invariants());
+  assert(s2.size() == static_cast<std::size_t>(std::distance(first, last)));
+  unsigned i = 0;
+  for (It it = first; it != last;) {
+    assert(s2[i] == *it);
+    ++it;
+    ++i;
+  }
+  assert(s2.get_allocator() == a);
+  assert(s2.capacity() >= s2.size());
 }
 
-TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef test_allocator<char> A;
-    const char* s = "12345678901234567890123456789012345678901234567890";
-
-    test(s, s);
-    test(s, s, A(2));
-
-    test(s, s+1);
-    test(s, s+1, A(2));
+template <class Alloc>
+TEST_CONSTEXPR_CXX20 void test(const Alloc& a) {
+  const char* s = "12345678901234567890123456789012345678901234567890";
 
-    test(s, s+10);
-    test(s, s+10, A(2));
+  test(s, s);
+  test(s, s, a);
 
-    test(s, s+50);
-    test(s, s+50, A(2));
+  test(s, s + 1);
+  test(s, s + 1, a);
 
-    test(cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s));
-    test(cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s), A(2));
+  test(s, s + 10);
+  test(s, s + 10, a);
 
-    test(cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s+1));
-    test(cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s+1), A(2));
+  test(s, s + 50);
+  test(s, s + 50, a);
 
-    test(cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s+10));
-    test(cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s+10), A(2));
+  test(cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s));
+  test(cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s), a);
 
-    test(cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s+50));
-    test(cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s+50), A(2));
-  }
-#if TEST_STD_VER >= 11
-  {
-    typedef min_allocator<char> A;
-    const char* s = "12345678901234567890123456789012345678901234567890";
+  test(cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s + 1));
+  test(cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s + 1), a);
 
-    test(s, s);
-    test(s, s, A());
+  test(cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s + 10));
+  test(cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s + 10), a);
 
-    test(s, s+1);
-    test(s, s+1, A());
-
-    test(s, s+10);
-    test(s, s+10, A());
-
-    test(s, s+50);
-    test(s, s+50, A());
-
-    test(cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s));
-    test(cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s), A());
-
-    test(cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s+1));
-    test(cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s+1), A());
-
-    test(cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s+10));
-    test(cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s+10), A());
+  test(cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s + 50));
+  test(cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s + 50), a);
+}
 
-    test(cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s+50));
-    test(cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s+50), A());
-  }
+TEST_CONSTEXPR_CXX20 bool test() {
+  test<test_allocator<char>>(test_allocator<char>(2));
+#if TEST_STD_VER >= 11
+  test<min_allocator<char>>(min_allocator<char>());
+  test<fancy_pointer_allocator<char>>(fancy_pointer_allocator<char>());
 #endif
   {
-      static_assert((!std::is_constructible<std::string, std::string,
-                                            std::string>::value),
-                    "");
-      static_assert(
-          (!std::is_constructible<std::string, std::string, std::string,
-                                  std::allocator<char> >::value),
-          "");
+    static_assert((!std::is_constructible<std::string, std::string, std::string>::value), "");
+    static_assert((!std::is_constructible<std::string, std::string, std::string, std::allocator<char> >::value), "");
   }
 
   return true;
 }
 
-int main(int, char**)
-{
+int main(int, char**) {
   test();
 #if TEST_STD_VER > 17
   static_assert(test());
diff --git a/libcxx/test/std/strings/basic.string/string.cons/iter_alloc_deduction.pass.cpp b/libcxx/test/std/strings/basic.string/string.cons/iter_alloc_deduction.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.cons/iter_alloc_deduction.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.cons/iter_alloc_deduction.pass.cpp
@@ -34,78 +34,79 @@
 using NotAnInputIterator = std::back_insert_iterator<std::basic_string<char16_t>>;
 
 template <typename T>
-struct NotAnAllocator { typedef T value_type; };
+struct NotAnAllocator {
+  typedef T value_type;
+};
 
 template <class Iter, class Alloc, class = void>
-struct CanDeduce : std::false_type { };
+struct CanDeduce : std::false_type {};
 
 template <class Iter, class Alloc>
-struct CanDeduce<Iter, Alloc, decltype((void)
-  std::basic_string{std::declval<Iter>(), std::declval<Iter>(), std::declval<Alloc>()}
-)> : std::true_type { };
+struct CanDeduce<Iter,
+                 Alloc,
+                 decltype((void)std::basic_string{std::declval<Iter>(), std::declval<Iter>(), std::declval<Alloc>()})>
+    : std::true_type {};
 
-static_assert( CanDeduce<int*, std::allocator<int>>::value);
+static_assert(CanDeduce<int*, std::allocator<int>>::value);
 static_assert(!CanDeduce<NotAnIterator, std::allocator<char>>::value);
 static_assert(!CanDeduce<NotAnInputIterator, std::allocator<char16_t>>::value);
 static_assert(!CanDeduce<wchar_t const*, NotAnAllocator<wchar_t>>::value);
 
+template <class CharT, template <class> class Alloc>
+TEST_CONSTEXPR_CXX20 void
+test_string(const CharT* s,
+            const std::basic_string<CharT, std::char_traits<CharT>, Alloc<CharT>>& s1,
+            const std::size_t string_size) {
+  using S = std::basic_string<CharT, std::char_traits<CharT>, Alloc<CharT>>;
+  static_assert(std::is_same_v<typename S::value_type, CharT>, "");
+  static_assert(std::is_same_v<typename S::traits_type, std::char_traits<CharT>>, "");
+  static_assert(std::is_same_v<typename S::allocator_type, Alloc<CharT>>, "");
+  assert(s1.size() == string_size);
+  assert(s1.compare(0, s1.size(), s, s1.size()) == 0);
+}
+
 TEST_CONSTEXPR_CXX20 bool test() {
+  const std::size_t string_size = 10;
   {
     const char* s = "12345678901234";
-    std::basic_string s1(s, s+10);  // Can't use {} here
-    using S = decltype(s1); // what type did we get?
-    static_assert(std::is_same_v<S::value_type,                      char>,  "");
-    static_assert(std::is_same_v<S::traits_type,    std::char_traits<char>>, "");
-    static_assert(std::is_same_v<S::allocator_type,   std::allocator<char>>, "");
-    assert(s1.size() == 10);
-    assert(s1.compare(0, s1.size(), s, s1.size()) == 0);
+    std::basic_string s1(s, s + string_size); // Can't use {} here
+    test_string<char, std::allocator>(s, s1, string_size);
   }
   {
     const char* s = "12345678901234";
-    std::basic_string s1{s, s+10, std::allocator<char>{}};
-    using S = decltype(s1); // what type did we get?
-    static_assert(std::is_same_v<S::value_type,                      char>,  "");
-    static_assert(std::is_same_v<S::traits_type,    std::char_traits<char>>, "");
-    static_assert(std::is_same_v<S::allocator_type,   std::allocator<char>>, "");
-    assert(s1.size() == 10);
-    assert(s1.compare(0, s1.size(), s, s1.size()) == 0);
+    std::basic_string s1{s, s + 10, std::allocator<char>{}};
+    test_string<char, std::allocator>(s, s1, string_size);
   }
   {
     const wchar_t* s = L"12345678901234";
-    std::basic_string s1{s, s+10, test_allocator<wchar_t>{}};
-    using S = decltype(s1); // what type did we get?
-    static_assert(std::is_same_v<S::value_type,                      wchar_t>,  "");
-    static_assert(std::is_same_v<S::traits_type,    std::char_traits<wchar_t>>, "");
-    static_assert(std::is_same_v<S::allocator_type,   test_allocator<wchar_t>>, "");
-    assert(s1.size() == 10);
-    assert(s1.compare(0, s1.size(), s, s1.size()) == 0);
+    std::basic_string s1{s, s + string_size, test_allocator<wchar_t>{}};
+    test_string<wchar_t, test_allocator>(s, s1, string_size);
+  }
+  {
+    const char16_t* s = u"12345678901234";
+    std::basic_string s1{s, s + string_size, min_allocator<char16_t>{}};
+    test_string<char16_t, min_allocator>(s, s1, string_size);
   }
   {
     const char16_t* s = u"12345678901234";
-    std::basic_string s1{s, s+10, min_allocator<char16_t>{}};
-    using S = decltype(s1); // what type did we get?
-    static_assert(std::is_same_v<S::value_type,                      char16_t>,  "");
-    static_assert(std::is_same_v<S::traits_type,    std::char_traits<char16_t>>, "");
-    static_assert(std::is_same_v<S::allocator_type,    min_allocator<char16_t>>, "");
-    assert(s1.size() == 10);
-    assert(s1.compare(0, s1.size(), s, s1.size()) == 0);
+    std::basic_string s1{s, s + string_size, fancy_pointer_allocator<char16_t>{}};
+    test_string<char16_t, fancy_pointer_allocator>(s, s1, string_size);
+  }
+  {
+    const char32_t* s = U"12345678901234";
+    std::basic_string s1{s, s + string_size, explicit_allocator<char32_t>{}};
+    test_string<char32_t, explicit_allocator>(s, s1, string_size);
   }
   {
     const char32_t* s = U"12345678901234";
-    std::basic_string s1{s, s+10, explicit_allocator<char32_t>{}};
-    using S = decltype(s1); // what type did we get?
-    static_assert(std::is_same_v<S::value_type,                        char32_t>,  "");
-    static_assert(std::is_same_v<S::traits_type,      std::char_traits<char32_t>>, "");
-    static_assert(std::is_same_v<S::allocator_type, explicit_allocator<char32_t>>, "");
-    assert(s1.size() == 10);
-    assert(s1.compare(0, s1.size(), s, s1.size()) == 0);
+    std::basic_string s1{s, s + string_size, fancy_pointer_allocator<char32_t>{}};
+    test_string<char32_t, fancy_pointer_allocator>(s, s1, string_size);
   }
 
   return true;
 }
 
-int main(int, char**)
-{
+int main(int, char**) {
   test();
 #if TEST_STD_VER > 17
   static_assert(test());
diff --git a/libcxx/test/std/strings/basic.string/string.cons/move.pass.cpp b/libcxx/test/std/strings/basic.string/string.cons/move.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.cons/move.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.cons/move.pass.cpp
@@ -20,39 +20,43 @@
 #include "min_allocator.h"
 
 template <class S>
-TEST_CONSTEXPR_CXX20 void
-test(S s0)
-{
-    S s1 = s0;
-    S s2 = std::move(s0);
-    LIBCPP_ASSERT(s2.__invariants());
-    LIBCPP_ASSERT(s0.__invariants());
-    assert(s2 == s1);
-    assert(s2.capacity() >= s2.size());
-    assert(s2.get_allocator() == s1.get_allocator());
+TEST_CONSTEXPR_CXX20 void test(S s0) {
+  S s1 = s0;
+  S s2 = std::move(s0);
+  LIBCPP_ASSERT(s2.__invariants());
+  LIBCPP_ASSERT(s0.__invariants());
+  assert(s2 == s1);
+  assert(s2.capacity() >= s2.size());
+  assert(s2.get_allocator() == s1.get_allocator());
+}
+
+template <class CharT, template <class> class Alloc>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  typedef Alloc<CharT> A;
+  using S = std::basic_string<CharT, std::char_traits<CharT>, A>;
+  test(S(A{}));
+  test(S("1", A()));
+  test(S("1234567890123456789012345678901234567890123456789012345678901234567890", A()));
+}
+
+template <>
+TEST_CONSTEXPR_CXX20 void test_string<char, test_allocator>() {
+  using A = test_allocator<char>;
+  using S = std::basic_string<char, std::char_traits<char>, A>;
+  test(S(A(3)));
+  test(S("1", A(5)));
+  test(S("1234567890123456789012345678901234567890123456789012345678901234567890", A(7)));
 }
 
 TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef test_allocator<char> A;
-    typedef std::basic_string<char, std::char_traits<char>, A> S;
-    test(S(A(3)));
-    test(S("1", A(5)));
-    test(S("1234567890123456789012345678901234567890123456789012345678901234567890", A(7)));
-  }
-  {
-    typedef min_allocator<char> A;
-    typedef std::basic_string<char, std::char_traits<char>, A> S;
-    test(S(A{}));
-    test(S("1", A()));
-    test(S("1234567890123456789012345678901234567890123456789012345678901234567890", A()));
-  }
+  test_string<char, std::allocator>();
+  test_string<char, test_allocator>();
+  test_string<char, fancy_pointer_allocator>();
 
   return true;
 }
 
-int main(int, char**)
-{
+int main(int, char**) {
   test();
 #if TEST_STD_VER > 17
   static_assert(test());
diff --git a/libcxx/test/std/strings/basic.string/string.cons/move_alloc.pass.cpp b/libcxx/test/std/strings/basic.string/string.cons/move_alloc.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.cons/move_alloc.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.cons/move_alloc.pass.cpp
@@ -20,64 +20,68 @@
 #include "min_allocator.h"
 
 template <class S>
-TEST_CONSTEXPR_CXX20 void
-test(S s0, const typename S::allocator_type& a)
-{
-    S s1 = s0;
-    S s2(std::move(s0), a);
-    LIBCPP_ASSERT(s2.__invariants());
-    LIBCPP_ASSERT(s0.__invariants());
-    assert(s2 == s1);
-    assert(s2.capacity() >= s2.size());
-    assert(s2.get_allocator() == a);
+TEST_CONSTEXPR_CXX20 void test(S s0, const typename S::allocator_type& a) {
+  S s1 = s0;
+  S s2(std::move(s0), a);
+  LIBCPP_ASSERT(s2.__invariants());
+  LIBCPP_ASSERT(s0.__invariants());
+  assert(s2 == s1);
+  assert(s2.capacity() >= s2.size());
+  assert(s2.get_allocator() == a);
 }
 
-TEST_CONSTEXPR_CXX20 bool test() {
+template <class CharT, template <class> class Alloc>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  using A = Alloc<CharT>;
+  using S = std::basic_string<CharT, std::char_traits<CharT>, A>;
+#if TEST_STD_VER > 14
+  static_assert((noexcept(S{})), "");
+#elif TEST_STD_VER >= 11
+  static_assert((noexcept(S()) == std::is_nothrow_move_constructible<A>::value), "");
+#endif
+  test(S(), A());
+  test(S("1"), A());
+  test(S("1234567890123456789012345678901234567890123456789012345678901234567890"), A());
+}
+
+template <>
+TEST_CONSTEXPR_CXX20 void test_string<char, test_allocator>() {
   test_allocator_statistics alloc_stats;
+  typedef test_allocator<char> A;
+  typedef std::basic_string<char, std::char_traits<char>, A> S;
   {
-    typedef test_allocator<char> A;
-    typedef std::basic_string<char, std::char_traits<char>, A> S;
 #if TEST_STD_VER > 14
-    static_assert((noexcept(S{})), "" );
+    static_assert((noexcept(S{})), "");
 #elif TEST_STD_VER >= 11
-    static_assert((noexcept(S()) == std::is_nothrow_move_constructible<A>::value), "" );
+    static_assert((noexcept(S()) == std::is_nothrow_move_constructible<A>::value), "");
 #endif
     test(S(), A(3, &alloc_stats));
     test(S("1"), A(5, &alloc_stats));
     test(S("1234567890123456789012345678901234567890123456789012345678901234567890"), A(7, &alloc_stats));
   }
 
-    int alloc_count = alloc_stats.alloc_count;
-  {
-    typedef test_allocator<char> A;
-    typedef std::basic_string<char, std::char_traits<char>, A> S;
-#if TEST_STD_VER > 14
-    static_assert((noexcept(S{})), "" );
-#elif TEST_STD_VER >= 11
-    static_assert((noexcept(S()) == std::is_nothrow_move_constructible<A>::value), "" );
-#endif
-    S s1 ( "Twas brillig, and the slivy toves did gyre and gymbal in the wabe", A(&alloc_stats));
-    S s2 (std::move(s1), A(1, &alloc_stats));
-  }
-    assert ( alloc_stats.alloc_count == alloc_count );
+  int alloc_count = alloc_stats.alloc_count;
   {
-    typedef min_allocator<char> A;
-    typedef std::basic_string<char, std::char_traits<char>, A> S;
 #if TEST_STD_VER > 14
-    static_assert((noexcept(S{})), "" );
+    static_assert((noexcept(S{})), "");
 #elif TEST_STD_VER >= 11
-    static_assert((noexcept(S()) == std::is_nothrow_move_constructible<A>::value), "" );
+    static_assert((noexcept(S()) == std::is_nothrow_move_constructible<A>::value), "");
 #endif
-    test(S(), A());
-    test(S("1"), A());
-    test(S("1234567890123456789012345678901234567890123456789012345678901234567890"), A());
+    S s1("Twas brillig, and the slivy toves did gyre and gymbal in the wabe", A(&alloc_stats));
+    S s2(std::move(s1), A(1, &alloc_stats));
   }
+  assert(alloc_stats.alloc_count == alloc_count);
+}
+
+TEST_CONSTEXPR_CXX20 bool test() {
+  test_string<char, test_allocator>();
+  test_string<char, min_allocator>();
+  test_string<char, fancy_pointer_allocator>();
 
   return true;
 }
 
-int main(int, char**)
-{
+int main(int, char**) {
   test();
 #if TEST_STD_VER > 17
   static_assert(test());
diff --git a/libcxx/test/std/strings/basic.string/string.cons/move_assign_noexcept.pass.cpp b/libcxx/test/std/strings/basic.string/string.cons/move_assign_noexcept.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.cons/move_assign_noexcept.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.cons/move_assign_noexcept.pass.cpp
@@ -27,39 +27,36 @@
 #include "test_allocator.h"
 
 template <class T>
-struct some_alloc
-{
-    typedef T value_type;
-    some_alloc(const some_alloc&);
-    T *allocate(size_t);
+struct some_alloc {
+  typedef T value_type;
+  some_alloc(const some_alloc&);
+  T* allocate(size_t);
 };
 
 template <class T>
-struct some_alloc2
-{
-    typedef T value_type;
+struct some_alloc2 {
+  typedef T value_type;
 
-    some_alloc2() {}
-    some_alloc2(const some_alloc2&);
-    T *allocate(size_t);
-    void deallocate(void*, unsigned) {}
+  some_alloc2() {}
+  some_alloc2(const some_alloc2&);
+  T* allocate(size_t);
+  void deallocate(void*, unsigned) {}
 
-    typedef std::false_type propagate_on_container_move_assignment;
-    typedef std::true_type is_always_equal;
+  typedef std::false_type propagate_on_container_move_assignment;
+  typedef std::true_type is_always_equal;
 };
 
 template <class T>
-struct some_alloc3
-{
-    typedef T value_type;
+struct some_alloc3 {
+  typedef T value_type;
 
-    some_alloc3() {}
-    some_alloc3(const some_alloc3&);
-    T *allocate(size_t);
-    void deallocate(void*, unsigned) {}
+  some_alloc3() {}
+  some_alloc3(const some_alloc3&);
+  T* allocate(size_t);
+  void deallocate(void*, unsigned) {}
 
-    typedef std::false_type propagate_on_container_move_assignment;
-    typedef std::false_type is_always_equal;
+  typedef std::false_type propagate_on_container_move_assignment;
+  typedef std::false_type is_always_equal;
 };
 
 TEST_CONSTEXPR_CXX20 bool test() {
@@ -71,20 +68,24 @@
     typedef std::basic_string<char, std::char_traits<char>, test_allocator<char>> C;
     static_assert(!std::is_nothrow_move_assignable<C>::value, "");
   }
+  {
+    typedef std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>> C;
+    static_assert(std::is_nothrow_move_assignable<C>::value, "");
+  }
   {
     typedef std::basic_string<char, std::char_traits<char>, some_alloc<char>> C;
 #if TEST_STD_VER > 14
     // if the allocators are always equal, then the move assignment can be noexcept
-    static_assert( std::is_nothrow_move_assignable<C>::value, "");
+    static_assert(std::is_nothrow_move_assignable<C>::value, "");
 #else
-      static_assert(!std::is_nothrow_move_assignable<C>::value, "");
+    static_assert(!std::is_nothrow_move_assignable<C>::value, "");
 #endif
   }
 #if TEST_STD_VER > 14
   {
     //  POCMA is false, always equal
     typedef std::basic_string<char, std::char_traits<char>, some_alloc2<char>> C;
-    static_assert( std::is_nothrow_move_assignable<C>::value, "");
+    static_assert(std::is_nothrow_move_assignable<C>::value, "");
   }
   {
     //  POCMA is false, not always equal
@@ -96,8 +97,7 @@
   return true;
 }
 
-int main(int, char**)
-{
+int main(int, char**) {
   test();
 #if TEST_STD_VER > 17
   static_assert(test());
diff --git a/libcxx/test/std/strings/basic.string/string.cons/move_assignment.pass.cpp b/libcxx/test/std/strings/basic.string/string.cons/move_assignment.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.cons/move_assignment.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.cons/move_assignment.pass.cpp
@@ -21,15 +21,13 @@
 #include "min_allocator.h"
 
 template <class S>
-TEST_CONSTEXPR_CXX20 void
-test(S s1, S s2)
-{
-    S s0 = s2;
-    s1 = std::move(s2);
-    LIBCPP_ASSERT(s1.__invariants());
-    LIBCPP_ASSERT(s2.__invariants());
-    assert(s1 == s0);
-    assert(s1.capacity() >= s1.size());
+TEST_CONSTEXPR_CXX20 void test(S s1, S s2) {
+  S s0 = s2;
+  s1   = std::move(s2);
+  LIBCPP_ASSERT(s1.__invariants());
+  LIBCPP_ASSERT(s2.__invariants());
+  assert(s1 == s0);
+  assert(s1.capacity() >= s1.size());
 }
 
 template <class S>
@@ -55,13 +53,13 @@
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
 }
 
-int main(int, char**)
-{
+int main(int, char**) {
   test();
 #if TEST_STD_VER > 17
   static_assert(test());
diff --git a/libcxx/test/std/strings/basic.string/string.cons/move_noexcept.pass.cpp b/libcxx/test/std/strings/basic.string/string.cons/move_noexcept.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.cons/move_noexcept.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.cons/move_noexcept.pass.cpp
@@ -21,24 +21,27 @@
 #include "test_macros.h"
 #include "test_allocator.h"
 
-int main(int, char**)
-{
-    {
-        typedef std::string C;
-        static_assert(std::is_nothrow_move_constructible<C>::value, "");
-    }
-    {
-        typedef std::basic_string<char, std::char_traits<char>, test_allocator<char>> C;
-        static_assert(std::is_nothrow_move_constructible<C>::value, "");
-    }
-    {
-        typedef std::basic_string<char, std::char_traits<char>, limited_allocator<char, 10>> C;
+int main(int, char**) {
+  {
+    typedef std::string C;
+    static_assert(std::is_nothrow_move_constructible<C>::value, "");
+  }
+  {
+    typedef std::basic_string<char, std::char_traits<char>, test_allocator<char>> C;
+    static_assert(std::is_nothrow_move_constructible<C>::value, "");
+  }
+  {
+    typedef std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>> C;
+    static_assert(std::is_nothrow_move_constructible<C>::value, "");
+  }
+  {
+    typedef std::basic_string<char, std::char_traits<char>, limited_allocator<char, 10>> C;
 #if TEST_STD_VER <= 14
-        static_assert(!std::is_nothrow_move_constructible<C>::value, "");
+    static_assert(!std::is_nothrow_move_constructible<C>::value, "");
 #else
-        static_assert( std::is_nothrow_move_constructible<C>::value, "");
+    static_assert(std::is_nothrow_move_constructible<C>::value, "");
 #endif
-    }
+  }
 
   return 0;
 }
diff --git a/libcxx/test/std/strings/basic.string/string.cons/pointer_alloc.pass.cpp b/libcxx/test/std/strings/basic.string/string.cons/pointer_alloc.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.cons/pointer_alloc.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.cons/pointer_alloc.pass.cpp
@@ -21,75 +21,58 @@
 #include "min_allocator.h"
 
 template <class charT>
-TEST_CONSTEXPR_CXX20 void
-test(const charT* s)
-{
-    typedef std::basic_string<charT, std::char_traits<charT>, test_allocator<charT> > S;
-    typedef typename S::traits_type T;
-    typedef typename S::allocator_type A;
-    std::size_t n = T::length(s);
-    S s2(s);
-    LIBCPP_ASSERT(s2.__invariants());
-    assert(s2.size() == n);
-    assert(T::compare(s2.data(), s, n) == 0);
-    assert(s2.get_allocator() == A());
-    assert(s2.capacity() >= s2.size());
+TEST_CONSTEXPR_CXX20 void test(const charT* s) {
+  typedef std::basic_string<charT, std::char_traits<charT>, test_allocator<charT> > S;
+  typedef typename S::traits_type T;
+  typedef typename S::allocator_type A;
+  std::size_t n = T::length(s);
+  S s2(s);
+  LIBCPP_ASSERT(s2.__invariants());
+  assert(s2.size() == n);
+  assert(T::compare(s2.data(), s, n) == 0);
+  assert(s2.get_allocator() == A());
+  assert(s2.capacity() >= s2.size());
 }
 
-template <class charT, class A>
-TEST_CONSTEXPR_CXX20 void
-test(const charT* s, const A& a)
-{
-    typedef std::basic_string<charT, std::char_traits<charT>, A> S;
-    typedef typename S::traits_type T;
-    std::size_t n = T::length(s);
-    S s2(s, a);
-    LIBCPP_ASSERT(s2.__invariants());
-    assert(s2.size() == n);
-    assert(T::compare(s2.data(), s, n) == 0);
-    assert(s2.get_allocator() == a);
-    assert(s2.capacity() >= s2.size());
+template <class charT, class Alloc>
+TEST_CONSTEXPR_CXX20 void test(const charT* s, const Alloc& a) {
+  typedef std::basic_string<charT, std::char_traits<charT>, Alloc> S;
+  typedef typename S::traits_type T;
+  std::size_t n = T::length(s);
+  S s2(s, a);
+  LIBCPP_ASSERT(s2.__invariants());
+  assert(s2.size() == n);
+  assert(T::compare(s2.data(), s, n) == 0);
+  assert(s2.get_allocator() == a);
+  assert(s2.capacity() >= s2.size());
 }
 
-TEST_CONSTEXPR_CXX20 bool test() {
-    {
-    typedef test_allocator<char> A;
+template <class Alloc>
+TEST_CONSTEXPR_CXX20 void test(const Alloc& a) {
+  test("");
+  test("", a);
 
-    test("");
-    test("", A(2));
+  test("1");
+  test("1", a);
 
-    test("1");
-    test("1", A(2));
+  test("1234567980");
+  test("1234567980", a);
 
-    test("1234567980");
-    test("1234567980", A(2));
+  test("123456798012345679801234567980123456798012345679801234567980");
+  test("123456798012345679801234567980123456798012345679801234567980", a);
+}
 
-    test("123456798012345679801234567980123456798012345679801234567980");
-    test("123456798012345679801234567980123456798012345679801234567980", A(2));
-    }
+TEST_CONSTEXPR_CXX20 bool test() {
+  test<test_allocator<char>>(test_allocator<char>(2));
 #if TEST_STD_VER >= 11
-    {
-    typedef min_allocator<char> A;
-
-    test("");
-    test("", A());
-
-    test("1");
-    test("1", A());
-
-    test("1234567980");
-    test("1234567980", A());
-
-    test("123456798012345679801234567980123456798012345679801234567980");
-    test("123456798012345679801234567980123456798012345679801234567980", A());
-    }
+  test<min_allocator<char>>(min_allocator<char>());
+  test<fancy_pointer_allocator<char>>(fancy_pointer_allocator<char>());
 #endif
 
   return true;
 }
 
-int main(int, char**)
-{
+int main(int, char**) {
   test();
 #if TEST_STD_VER > 17
   static_assert(test());
diff --git a/libcxx/test/std/strings/basic.string/string.cons/pointer_assignment.pass.cpp b/libcxx/test/std/strings/basic.string/string.cons/pointer_assignment.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.cons/pointer_assignment.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.cons/pointer_assignment.pass.cpp
@@ -16,17 +16,16 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
-TEST_CONSTEXPR_CXX20 void
-test(S s1, const typename S::value_type* s2)
-{
-    typedef typename S::traits_type T;
-    s1 = s2;
-    LIBCPP_ASSERT(s1.__invariants());
-    assert(s1.size() == T::length(s2));
-    assert(T::compare(s1.data(), s2, s1.size()) == 0);
-    assert(s1.capacity() >= s1.size());
+TEST_CONSTEXPR_CXX20 void test(S s1, const typename S::value_type* s2) {
+  typedef typename S::traits_type T;
+  s1 = s2;
+  LIBCPP_ASSERT(s1.__invariants());
+  assert(s1.size() == T::length(s2));
+  assert(T::compare(s1.data(), s2, s1.size()) == 0);
+  assert(s1.capacity() >= s1.size());
 }
 
 template <class S>
@@ -37,28 +36,26 @@
   test(S("1"), "2");
   test(S("1"), "2");
 
-  test(S(),
-        "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz");
-  test(S("123456789"),
-        "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz");
+  test(S(), "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz");
+  test(S("123456789"), "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz");
   test(S("1234567890123456789012345678901234567890123456789012345678901234567890"),
-        "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz");
+       "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz");
   test(S("1234567890123456789012345678901234567890123456789012345678901234567890"
-          "1234567890123456789012345678901234567890123456789012345678901234567890"),
-        "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz");
+         "1234567890123456789012345678901234567890123456789012345678901234567890"),
+       "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz");
 }
 
 TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
-  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
 }
 
-int main(int, char**)
-{
+int main(int, char**) {
   test();
 #if TEST_STD_VER > 17
   static_assert(test());
diff --git a/libcxx/test/std/strings/basic.string/string.cons/pointer_size_alloc.pass.cpp b/libcxx/test/std/strings/basic.string/string.cons/pointer_size_alloc.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.cons/pointer_size_alloc.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.cons/pointer_size_alloc.pass.cpp
@@ -19,67 +19,51 @@
 #include "test_allocator.h"
 #include "min_allocator.h"
 
-template <class charT>
-TEST_CONSTEXPR_CXX20 void
-test(const charT* s, unsigned n)
-{
-    typedef std::basic_string<charT, std::char_traits<charT>, test_allocator<charT> > S;
-    typedef typename S::traits_type T;
-    typedef typename S::allocator_type A;
-    S s2(s, n);
-    LIBCPP_ASSERT(s2.__invariants());
-    assert(s2.size() == n);
-    assert(T::compare(s2.data(), s, n) == 0);
-    assert(s2.get_allocator() == A());
-    assert(s2.capacity() >= s2.size());
+template <class CharT>
+TEST_CONSTEXPR_CXX20 void test(const CharT* s, unsigned n) {
+  typedef std::basic_string<CharT, std::char_traits<CharT>, test_allocator<CharT> > S;
+  typedef typename S::traits_type T;
+  typedef typename S::allocator_type A;
+  S s2(s, n);
+  LIBCPP_ASSERT(s2.__invariants());
+  assert(s2.size() == n);
+  assert(T::compare(s2.data(), s, n) == 0);
+  assert(s2.get_allocator() == A());
+  assert(s2.capacity() >= s2.size());
 }
 
-template <class charT, class A>
-TEST_CONSTEXPR_CXX20 void
-test(const charT* s, unsigned n, const A& a)
-{
-    typedef std::basic_string<charT, std::char_traits<charT>, A> S;
-    typedef typename S::traits_type T;
-    S s2(s, n, a);
-    LIBCPP_ASSERT(s2.__invariants());
-    assert(s2.size() == n);
-    assert(T::compare(s2.data(), s, n) == 0);
-    assert(s2.get_allocator() == a);
-    assert(s2.capacity() >= s2.size());
+template <class CharT, class Alloc>
+TEST_CONSTEXPR_CXX20 void test(const CharT* s, unsigned n, const Alloc& a) {
+  typedef std::basic_string<CharT, std::char_traits<CharT>, Alloc> S;
+  typedef typename S::traits_type T;
+  S s2(s, n, a);
+  LIBCPP_ASSERT(s2.__invariants());
+  assert(s2.size() == n);
+  assert(T::compare(s2.data(), s, n) == 0);
+  assert(s2.get_allocator() == a);
+  assert(s2.capacity() >= s2.size());
 }
 
-TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef test_allocator<char> A;
+template <class Alloc>
+TEST_CONSTEXPR_CXX20 void test(const Alloc& a) {
+  test("", 0);
+  test("", 0, a);
 
-    test("", 0);
-    test("", 0, A(2));
+  test("1", 1);
+  test("1", 1, a);
 
-    test("1", 1);
-    test("1", 1, A(2));
+  test("1234567980", 10);
+  test("1234567980", 10, a);
 
-    test("1234567980", 10);
-    test("1234567980", 10, A(2));
+  test("123456798012345679801234567980123456798012345679801234567980", 60);
+  test("123456798012345679801234567980123456798012345679801234567980", 60, a);
+}
 
-    test("123456798012345679801234567980123456798012345679801234567980", 60);
-    test("123456798012345679801234567980123456798012345679801234567980", 60, A(2));
-  }
+TEST_CONSTEXPR_CXX20 bool test() {
+  test<test_allocator<char>>(test_allocator<char>(2));
 #if TEST_STD_VER >= 11
-  {
-    typedef min_allocator<char> A;
-
-    test("", 0);
-    test("", 0, A());
-
-    test("1", 1);
-    test("1", 1, A());
-
-    test("1234567980", 10);
-    test("1234567980", 10, A());
-
-    test("123456798012345679801234567980123456798012345679801234567980", 60);
-    test("123456798012345679801234567980123456798012345679801234567980", 60, A());
-  }
+  test<min_allocator<char>>(min_allocator<char>());
+  test<fancy_pointer_allocator<char>>(fancy_pointer_allocator<char>());
 #endif
 
 #if TEST_STD_VER >= 11
@@ -93,8 +77,7 @@
   return true;
 }
 
-int main(int, char**)
-{
+int main(int, char**) {
   test();
 #if TEST_STD_VER > 17
   static_assert(test());
diff --git a/libcxx/test/std/strings/basic.string/string.cons/size_char_alloc.pass.cpp b/libcxx/test/std/strings/basic.string/string.cons/size_char_alloc.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.cons/size_char_alloc.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.cons/size_char_alloc.pass.cpp
@@ -21,110 +21,105 @@
 #include "min_allocator.h"
 
 template <class charT>
-TEST_CONSTEXPR_CXX20 void
-test(unsigned n, charT c)
-{
-    typedef std::basic_string<charT, std::char_traits<charT>, test_allocator<charT> > S;
-    typedef typename S::allocator_type A;
-    S s2(n, c);
-    LIBCPP_ASSERT(s2.__invariants());
-    assert(s2.size() == n);
-    for (unsigned i = 0; i < n; ++i)
-        assert(s2[i] == c);
-    assert(s2.get_allocator() == A());
-    assert(s2.capacity() >= s2.size());
+TEST_CONSTEXPR_CXX20 void test(unsigned n, charT c) {
+  typedef std::basic_string<charT, std::char_traits<charT>, test_allocator<charT> > S;
+  typedef typename S::allocator_type A;
+  S s2(n, c);
+  LIBCPP_ASSERT(s2.__invariants());
+  assert(s2.size() == n);
+  for (unsigned i = 0; i < n; ++i)
+    assert(s2[i] == c);
+  assert(s2.get_allocator() == A());
+  assert(s2.capacity() >= s2.size());
 }
 
-template <class charT, class A>
-TEST_CONSTEXPR_CXX20 void
-test(unsigned n, charT c, const A& a)
-{
-    typedef std::basic_string<charT, std::char_traits<charT>, A> S;
-    S s2(n, c, a);
-    LIBCPP_ASSERT(s2.__invariants());
-    assert(s2.size() == n);
-    for (unsigned i = 0; i < n; ++i)
-        assert(s2[i] == c);
-    assert(s2.get_allocator() == a);
-    assert(s2.capacity() >= s2.size());
+template <class charT, class Alloc>
+TEST_CONSTEXPR_CXX20 void test(unsigned n, charT c, const Alloc& a) {
+  typedef std::basic_string<charT, std::char_traits<charT>, Alloc> S;
+  S s2(n, c, a);
+  LIBCPP_ASSERT(s2.__invariants());
+  assert(s2.size() == n);
+  for (unsigned i = 0; i < n; ++i)
+    assert(s2[i] == c);
+  assert(s2.get_allocator() == a);
+  assert(s2.capacity() >= s2.size());
 }
 
 template <class Tp>
-TEST_CONSTEXPR_CXX20 void
-test(Tp n, Tp c)
-{
-    typedef char charT;
-    typedef std::basic_string<charT, std::char_traits<charT>, test_allocator<charT> > S;
-    typedef typename S::allocator_type A;
-    S s2(n, c);
-    LIBCPP_ASSERT(s2.__invariants());
-    assert(s2.size() == static_cast<std::size_t>(n));
-    for (int i = 0; i < n; ++i)
-        assert(s2[i] == c);
-    assert(s2.get_allocator() == A());
-    assert(s2.capacity() >= s2.size());
+TEST_CONSTEXPR_CXX20 void test(Tp n, Tp c) {
+  typedef char charT;
+  typedef std::basic_string<charT, std::char_traits<charT>, test_allocator<charT> > S;
+  typedef typename S::allocator_type A;
+  S s2(n, c);
+  LIBCPP_ASSERT(s2.__invariants());
+  assert(s2.size() == static_cast<std::size_t>(n));
+  for (int i = 0; i < n; ++i)
+    assert(s2[i] == c);
+  assert(s2.get_allocator() == A());
+  assert(s2.capacity() >= s2.size());
 }
 
 template <class Tp, class A>
-TEST_CONSTEXPR_CXX20 void
-test(Tp n, Tp c, const A& a)
-{
-    typedef char charT;
-    typedef std::basic_string<charT, std::char_traits<charT>, A> S;
-    S s2(n, c, a);
-    LIBCPP_ASSERT(s2.__invariants());
-    assert(s2.size() == static_cast<std::size_t>(n));
-    for (int i = 0; i < n; ++i)
-        assert(s2[i] == c);
-    assert(s2.get_allocator() == a);
-    assert(s2.capacity() >= s2.size());
+TEST_CONSTEXPR_CXX20 void test(Tp n, Tp c, const A& a) {
+  typedef char charT;
+  typedef std::basic_string<charT, std::char_traits<charT>, A> S;
+  S s2(n, c, a);
+  LIBCPP_ASSERT(s2.__invariants());
+  assert(s2.size() == static_cast<std::size_t>(n));
+  for (int i = 0; i < n; ++i)
+    assert(s2[i] == c);
+  assert(s2.get_allocator() == a);
+  assert(s2.capacity() >= s2.size());
 }
 
-TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef test_allocator<char> A;
+template <class A>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  test(0, 'a');
+  test(0, 'a', A());
 
-    test(0, 'a');
-    test(0, 'a', A(2));
+  test(1, 'a');
+  test(1, 'a', A());
 
-    test(1, 'a');
-    test(1, 'a', A(2));
+  test(10, 'a');
+  test(10, 'a', A());
 
-    test(10, 'a');
-    test(10, 'a', A(2));
+  test(100, 'a');
+  test(100, 'a', A());
 
-    test(100, 'a');
-    test(100, 'a', A(2));
+  test(static_cast<char>(100), static_cast<char>(65));
+  test(static_cast<char>(100), static_cast<char>(65), A());
+}
 
-    test(static_cast<char>(100), static_cast<char>(65));
-    test(static_cast<char>(100), static_cast<char>(65), A(3));
-  }
-#if TEST_STD_VER >= 11
-  {
-    typedef min_allocator<char> A;
+template <>
+TEST_CONSTEXPR_CXX20 void test_string<test_allocator<char>>() {
+  using A = test_allocator<char>;
+  test(0, 'a');
+  test(0, 'a', A(2));
 
-    test(0, 'a');
-    test(0, 'a', A());
+  test(1, 'a');
+  test(1, 'a', A(2));
 
-    test(1, 'a');
-    test(1, 'a', A());
+  test(10, 'a');
+  test(10, 'a', A(2));
 
-    test(10, 'a');
-    test(10, 'a', A());
+  test(100, 'a');
+  test(100, 'a', A(2));
 
-    test(100, 'a');
-    test(100, 'a', A());
+  test(static_cast<char>(100), static_cast<char>(65));
+  test(static_cast<char>(100), static_cast<char>(65), A(3));
+}
 
-    test(static_cast<char>(100), static_cast<char>(65));
-    test(static_cast<char>(100), static_cast<char>(65), A());
-  }
+TEST_CONSTEXPR_CXX20 bool test() {
+  test_string<test_allocator<char>>();
+#if TEST_STD_VER >= 11
+  test_string<min_allocator<char>>();
+  test_string<fancy_pointer_allocator<char>>();
 #endif
 
   return true;
 }
 
-int main(int, char**)
-{
+int main(int, char**) {
   test();
 #if TEST_STD_VER > 17
   static_assert(test());
diff --git a/libcxx/test/std/strings/basic.string/string.cons/string_view.pass.cpp b/libcxx/test/std/strings/basic.string/string.cons/string_view.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.cons/string_view.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.cons/string_view.pass.cpp
@@ -24,13 +24,11 @@
 static_assert(!std::is_convertible<std::string_view, std::string const&>::value, "");
 static_assert(!std::is_convertible<std::string_view, std::string>::value, "");
 
-template <class charT>
-TEST_CONSTEXPR_CXX20 void
-test(std::basic_string_view<charT> sv)
-{
-    typedef std::basic_string<charT, std::char_traits<charT>, test_allocator<charT> > S;
-    typedef typename S::traits_type T;
-    typedef typename S::allocator_type A;
+template <class CharT>
+TEST_CONSTEXPR_CXX20 void test(std::basic_string_view<CharT> sv) {
+  typedef std::basic_string<CharT, std::char_traits<CharT>, test_allocator<CharT> > S;
+  typedef typename S::traits_type T;
+  typedef typename S::allocator_type A;
   {
     S s2(sv);
     LIBCPP_ASSERT(s2.__invariants());
@@ -50,12 +48,10 @@
   }
 }
 
-template <class charT, class A>
-TEST_CONSTEXPR_CXX20 void
-test(std::basic_string_view<charT> sv, const A& a)
-{
-    typedef std::basic_string<charT, std::char_traits<charT>, A> S;
-    typedef typename S::traits_type T;
+template <class CharT, class Alloc>
+TEST_CONSTEXPR_CXX20 void test(std::basic_string_view<CharT> sv, const Alloc& a) {
+  typedef std::basic_string<CharT, std::char_traits<CharT>, Alloc> S;
+  typedef typename S::traits_type T;
   {
     S s2(sv, a);
     LIBCPP_ASSERT(s2.__invariants());
@@ -75,47 +71,34 @@
   }
 }
 
-TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef test_allocator<char> A;
-    typedef std::basic_string_view<char, std::char_traits<char> > SV;
-
-    test(SV(""));
-    test(SV(""), A(2));
+template <class Alloc>
+TEST_CONSTEXPR_CXX20 void test_string(const Alloc& a) {
+  typedef std::basic_string_view<char, std::char_traits<char> > SV;
 
-    test(SV("1"));
-    test(SV("1") ,A(2));
-
-    test(SV("1234567980"));
-    test(SV("1234567980"), A(2));
-
-    test(SV("123456798012345679801234567980123456798012345679801234567980"));
-    test(SV("123456798012345679801234567980123456798012345679801234567980"), A(2));
-  }
-#if TEST_STD_VER >= 11
-  {
-    typedef min_allocator<char> A;
-    typedef std::basic_string_view<char, std::char_traits<char> > SV;
+  test(SV(""));
+  test(SV(""), a);
 
-    test(SV(""));
-    test(SV(""), A());
+  test(SV("1"));
+  test(SV("1"), a);
 
-    test(SV("1"));
-    test(SV("1") ,A());
+  test(SV("1234567980"));
+  test(SV("1234567980"), a);
 
-    test(SV("1234567980"));
-    test(SV("1234567980"), A());
+  test(SV("123456798012345679801234567980123456798012345679801234567980"));
+  test(SV("123456798012345679801234567980123456798012345679801234567980"), a);
+}
 
-    test(SV("123456798012345679801234567980123456798012345679801234567980"));
-    test(SV("123456798012345679801234567980123456798012345679801234567980"), A());
-  }
+TEST_CONSTEXPR_CXX20 bool test() {
+  test_string<test_allocator<char>>(test_allocator<char>(2));
+#if TEST_STD_VER >= 11
+  test_string<min_allocator<char>>(min_allocator<char>());
+  test_string<fancy_pointer_allocator<char>>(fancy_pointer_allocator<char>());
 #endif
 
   return true;
 }
 
-int main(int, char**)
-{
+int main(int, char**) {
   test();
 #if TEST_STD_VER > 17
   static_assert(test());
diff --git a/libcxx/test/std/strings/basic.string/string.cons/string_view_assignment.pass.cpp b/libcxx/test/std/strings/basic.string/string.cons/string_view_assignment.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.cons/string_view_assignment.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.cons/string_view_assignment.pass.cpp
@@ -15,17 +15,16 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S, class SV>
-TEST_CONSTEXPR_CXX20 void
-test(S s1, SV sv)
-{
-    typedef typename S::traits_type T;
-    s1 = sv;
-    LIBCPP_ASSERT(s1.__invariants());
-    assert(s1.size() == sv.size());
-    assert(T::compare(s1.data(), sv.data(), s1.size()) == 0);
-    assert(s1.capacity() >= s1.size());
+TEST_CONSTEXPR_CXX20 void test(S s1, SV sv) {
+  typedef typename S::traits_type T;
+  s1 = sv;
+  LIBCPP_ASSERT(s1.__invariants());
+  assert(s1.size() == sv.size());
+  assert(T::compare(s1.data(), sv.data(), s1.size()) == 0);
+  assert(s1.capacity() >= s1.size());
 }
 
 template <class S>
@@ -52,13 +51,13 @@
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
 }
 
-int main(int, char**)
-{
+int main(int, char**) {
   test();
 #if TEST_STD_VER > 17
   static_assert(test());
diff --git a/libcxx/test/std/strings/basic.string/string.cons/string_view_deduction.pass.cpp b/libcxx/test/std/strings/basic.string/string.cons/string_view_deduction.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.cons/string_view_deduction.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.cons/string_view_deduction.pass.cpp
@@ -88,6 +88,16 @@
     assert(s1.size() == sv.size());
     assert(s1.compare(0, s1.size(), sv.data(), s1.size()) == 0);
   }
+  {
+    std::u8string_view sv = u8"12345678901234";
+    std::basic_string s1{sv, fancy_pointer_allocator<char8_t>{}};
+    using S = decltype(s1); // what type did we get?
+    static_assert(std::is_same_v<S::value_type, char8_t>, "");
+    static_assert(std::is_same_v<S::traits_type, std::char_traits<char8_t>>, "");
+    static_assert(std::is_same_v<S::allocator_type, fancy_pointer_allocator<char8_t>>, "");
+    assert(s1.size() == sv.size());
+    assert(s1.compare(0, s1.size(), sv.data(), s1.size()) == 0);
+  }
 #endif
   {
     std::u16string_view sv = u"12345678901234";
@@ -99,6 +109,16 @@
     assert(s1.size() == sv.size());
     assert(s1.compare(0, s1.size(), sv.data(), s1.size()) == 0);
   }
+  {
+    std::u16string_view sv = u"12345678901234";
+    std::basic_string s1{sv, fancy_pointer_allocator<char16_t>{}};
+    using S = decltype(s1); // what type did we get?
+    static_assert(std::is_same_v<S::value_type, char16_t>, "");
+    static_assert(std::is_same_v<S::traits_type, std::char_traits<char16_t>>, "");
+    static_assert(std::is_same_v<S::allocator_type, fancy_pointer_allocator<char16_t>>, "");
+    assert(s1.size() == sv.size());
+    assert(s1.compare(0, s1.size(), sv.data(), s1.size()) == 0);
+  }
   {
     std::u32string_view sv = U"12345678901234";
     std::basic_string s1{sv, explicit_allocator<char32_t>{}};
diff --git a/libcxx/test/std/strings/basic.string/string.cons/string_view_size_size_deduction.pass.cpp b/libcxx/test/std/strings/basic.string/string.cons/string_view_size_size_deduction.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.cons/string_view_size_size_deduction.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.cons/string_view_size_size_deduction.pass.cpp
@@ -36,89 +36,85 @@
 #include "min_allocator.h"
 
 template <class StringView, class Size, class Allocator, class = void>
-struct CanDeduce : std::false_type { };
+struct CanDeduce : std::false_type {};
 
 template <class StringView, class Size, class Allocator>
-struct CanDeduce<StringView, Size, Allocator, decltype((void)
-  std::basic_string{std::declval<StringView>(), std::declval<Size>(), std::declval<Size>(), std::declval<Allocator>()}
-)> : std::true_type { };
+struct CanDeduce<
+    StringView,
+    Size,
+    Allocator,
+    decltype((void)std::basic_string{
+        std::declval<StringView>(), std::declval<Size>(), std::declval<Size>(), std::declval<Allocator>()})>
+    : std::true_type {};
 
-struct NotAnAllocator { };
-static_assert( CanDeduce<std::string_view, std::size_t, std::allocator<char>>::value);
+struct NotAnAllocator {};
+static_assert(CanDeduce<std::string_view, std::size_t, std::allocator<char>>::value);
 static_assert(!CanDeduce<std::string_view, std::size_t, NotAnAllocator>::value);
 
+template <class CharT, template <class> class Alloc>
+TEST_CONSTEXPR_CXX20 void
+test_string(const std::basic_string_view<CharT, std::char_traits<CharT>>& sv,
+            const std::basic_string<CharT, std::char_traits<CharT>, Alloc<CharT>>& s1,
+            const std::size_t string_size) {
+  using S = std::basic_string<CharT, std::char_traits<CharT>, Alloc<CharT>>;
+  static_assert(std::is_same_v<typename S::value_type, CharT>, "");
+  static_assert(std::is_same_v<typename S::traits_type, std::char_traits<CharT>>, "");
+  static_assert(std::is_same_v<typename S::allocator_type, Alloc<CharT>>, "");
+  assert(s1.size() == string_size);
+  assert(s1.compare(0, s1.size(), sv.data(), s1.size()) == 0);
+}
+
 TEST_CONSTEXPR_CXX20 bool test() {
   {
     std::string_view sv = "12345678901234";
     std::basic_string s1{sv, 0, 4};
-    using S = decltype(s1); // what type did we get?
-    static_assert(std::is_same_v<S::value_type,                      char>,  "");
-    static_assert(std::is_same_v<S::traits_type,    std::char_traits<char>>, "");
-    static_assert(std::is_same_v<S::allocator_type,   std::allocator<char>>, "");
-    assert(s1.size() == 4);
-    assert(s1.compare(0, s1.size(), sv.data(), s1.size()) == 0);
+    test_string<char, std::allocator>(sv, s1, 4);
   }
 
   {
     std::string_view sv = "12345678901234";
     std::basic_string s1{sv, 0, 4, std::allocator<char>{}};
-    using S = decltype(s1); // what type did we get?
-    static_assert(std::is_same_v<S::value_type,                      char>,  "");
-    static_assert(std::is_same_v<S::traits_type,    std::char_traits<char>>, "");
-    static_assert(std::is_same_v<S::allocator_type,   std::allocator<char>>, "");
-    assert(s1.size() == 4);
-    assert(s1.compare(0, s1.size(), sv.data(), s1.size()) == 0);
+    test_string<char, std::allocator>(sv, s1, 4);
   }
 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
   {
     std::wstring_view sv = L"12345678901234";
     std::basic_string s1{sv, 0, 4, test_allocator<wchar_t>{}};
-    using S = decltype(s1); // what type did we get?
-    static_assert(std::is_same_v<S::value_type,                      wchar_t>,  "");
-    static_assert(std::is_same_v<S::traits_type,    std::char_traits<wchar_t>>, "");
-    static_assert(std::is_same_v<S::allocator_type,   test_allocator<wchar_t>>, "");
-    assert(s1.size() == 4);
-    assert(s1.compare(0, s1.size(), sv.data(), s1.size()) == 0);
+    test_string<wchar_t, test_allocator>(sv, s1, 4);
   }
 #endif
 #ifndef TEST_HAS_NO_CHAR8_T
   {
     std::u8string_view sv = u8"12345678901234";
     std::basic_string s1{sv, 0, 4, min_allocator<char8_t>{}};
-    using S = decltype(s1); // what type did we get?
-    static_assert(std::is_same_v<S::value_type,                      char8_t>,  "");
-    static_assert(std::is_same_v<S::traits_type,    std::char_traits<char8_t>>, "");
-    static_assert(std::is_same_v<S::allocator_type,    min_allocator<char8_t>>, "");
-    assert(s1.size() == 4);
-    assert(s1.compare(0, s1.size(), sv.data(), s1.size()) == 0);
+    test_string<char8_t, min_allocator>(sv, s1, 4);
+  }
+  {
+    std::u8string_view sv = u8"12345678901234";
+    std::basic_string s1{sv, 0, 4, fancy_pointer_allocator<char8_t>{}};
+    test_string<char8_t, fancy_pointer_allocator>(sv, s1, 4);
   }
 #endif
   {
     std::u16string_view sv = u"12345678901234";
     std::basic_string s1{sv, 0, 4, min_allocator<char16_t>{}};
-    using S = decltype(s1); // what type did we get?
-    static_assert(std::is_same_v<S::value_type,                      char16_t>,  "");
-    static_assert(std::is_same_v<S::traits_type,    std::char_traits<char16_t>>, "");
-    static_assert(std::is_same_v<S::allocator_type,    min_allocator<char16_t>>, "");
-    assert(s1.size() == 4);
-    assert(s1.compare(0, s1.size(), sv.data(), s1.size()) == 0);
+    test_string<char16_t, min_allocator>(sv, s1, 4);
+  }
+  {
+    std::u16string_view sv = u"12345678901234";
+    std::basic_string s1{sv, 0, 4, fancy_pointer_allocator<char16_t>{}};
+    test_string<char16_t, fancy_pointer_allocator>(sv, s1, 4);
   }
   {
     std::u32string_view sv = U"12345678901234";
     std::basic_string s1{sv, 0, 4, explicit_allocator<char32_t>{}};
-    using S = decltype(s1); // what type did we get?
-    static_assert(std::is_same_v<S::value_type,                        char32_t>,  "");
-    static_assert(std::is_same_v<S::traits_type,      std::char_traits<char32_t>>, "");
-    static_assert(std::is_same_v<S::allocator_type, explicit_allocator<char32_t>>, "");
-    assert(s1.size() == 4);
-    assert(s1.compare(0, s1.size(), sv.data(), s1.size()) == 0);
+    test_string<char32_t, explicit_allocator>(sv, s1, 4);
   }
 
   return true;
 }
 
-int main(int, char**)
-{
+int main(int, char**) {
   test();
 #if TEST_STD_VER > 17
   static_assert(test());
diff --git a/libcxx/test/std/strings/basic.string/string.cons/substr.pass.cpp b/libcxx/test/std/strings/basic.string/string.cons/substr.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.cons/substr.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.cons/substr.pass.cpp
@@ -28,201 +28,191 @@
 #include "min_allocator.h"
 
 template <class S>
-TEST_CONSTEXPR_CXX20 void
-test(S str, unsigned pos)
-{
-    typedef typename S::traits_type T;
-    typedef typename S::allocator_type A;
-
-    if (pos <= str.size())
-    {
-        S s2(str, pos);
-        LIBCPP_ASSERT(s2.__invariants());
-        typename S::size_type rlen = str.size() - pos;
-        assert(s2.size() == rlen);
-        assert(T::compare(s2.data(), str.data() + pos, rlen) == 0);
-        assert(s2.get_allocator() == A());
-        assert(s2.capacity() >= s2.size());
-    }
+TEST_CONSTEXPR_CXX20 void test(S str, unsigned pos) {
+  typedef typename S::traits_type T;
+  typedef typename S::allocator_type A;
+
+  if (pos <= str.size()) {
+    S s2(str, pos);
+    LIBCPP_ASSERT(s2.__invariants());
+    typename S::size_type rlen = str.size() - pos;
+    assert(s2.size() == rlen);
+    assert(T::compare(s2.data(), str.data() + pos, rlen) == 0);
+    assert(s2.get_allocator() == A());
+    assert(s2.capacity() >= s2.size());
+  }
 #ifndef TEST_HAS_NO_EXCEPTIONS
-    else if (!TEST_IS_CONSTANT_EVALUATED)
-    {
-        try
-        {
-            S s2(str, pos);
-            assert(false);
-        }
-        catch (std::out_of_range&)
-        {
-            assert(pos > str.size());
-        }
+  else if (!TEST_IS_CONSTANT_EVALUATED) {
+    try {
+      S s2(str, pos);
+      assert(false);
+    } catch (std::out_of_range&) {
+      assert(pos > str.size());
     }
+  }
 #endif
 }
 
 template <class S>
-TEST_CONSTEXPR_CXX20 void
-test(S str, unsigned pos, unsigned n)
-{
-    typedef typename S::traits_type T;
-    typedef typename S::allocator_type A;
-    if (pos <= str.size())
-    {
-        S s2(str, pos, n);
-        LIBCPP_ASSERT(s2.__invariants());
-        typename S::size_type rlen = std::min<typename S::size_type>(str.size() - pos, n);
-        assert(s2.size() == rlen);
-        assert(T::compare(s2.data(), str.data() + pos, rlen) == 0);
-        assert(s2.get_allocator() == A());
-        assert(s2.capacity() >= s2.size());
-    }
+TEST_CONSTEXPR_CXX20 void test(S str, unsigned pos, unsigned n) {
+  typedef typename S::traits_type T;
+  typedef typename S::allocator_type A;
+  if (pos <= str.size()) {
+    S s2(str, pos, n);
+    LIBCPP_ASSERT(s2.__invariants());
+    typename S::size_type rlen = std::min<typename S::size_type>(str.size() - pos, n);
+    assert(s2.size() == rlen);
+    assert(T::compare(s2.data(), str.data() + pos, rlen) == 0);
+    assert(s2.get_allocator() == A());
+    assert(s2.capacity() >= s2.size());
+  }
 #ifndef TEST_HAS_NO_EXCEPTIONS
-    else if (!TEST_IS_CONSTANT_EVALUATED)
-    {
-        try
-        {
-            S s2(str, pos, n);
-            assert(false);
-        }
-        catch (std::out_of_range&)
-        {
-            assert(pos > str.size());
-        }
+  else if (!TEST_IS_CONSTANT_EVALUATED) {
+    try {
+      S s2(str, pos, n);
+      assert(false);
+    } catch (std::out_of_range&) {
+      assert(pos > str.size());
     }
+  }
 #endif
 }
 
 template <class S>
-TEST_CONSTEXPR_CXX20 void
-test(S str, unsigned pos, unsigned n, const typename S::allocator_type& a)
-{
-    typedef typename S::traits_type T;
-
-    if (pos <= str.size())
-    {
-        S s2(str, pos, n, a);
-        LIBCPP_ASSERT(s2.__invariants());
-        typename S::size_type rlen = std::min<typename S::size_type>(str.size() - pos, n);
-        assert(s2.size() == rlen);
-        assert(T::compare(s2.data(), str.data() + pos, rlen) == 0);
-        assert(s2.get_allocator() == a);
-        assert(s2.capacity() >= s2.size());
-    }
+TEST_CONSTEXPR_CXX20 void test(S str, unsigned pos, unsigned n, const typename S::allocator_type& a) {
+  typedef typename S::traits_type T;
+
+  if (pos <= str.size()) {
+    S s2(str, pos, n, a);
+    LIBCPP_ASSERT(s2.__invariants());
+    typename S::size_type rlen = std::min<typename S::size_type>(str.size() - pos, n);
+    assert(s2.size() == rlen);
+    assert(T::compare(s2.data(), str.data() + pos, rlen) == 0);
+    assert(s2.get_allocator() == a);
+    assert(s2.capacity() >= s2.size());
+  }
 #ifndef TEST_HAS_NO_EXCEPTIONS
-    else if (!TEST_IS_CONSTANT_EVALUATED)
-    {
-        try
-        {
-            S s2(str, pos, n, a);
-            assert(false);
-        }
-        catch (std::out_of_range&)
-        {
-            assert(pos > str.size());
-        }
+  else if (!TEST_IS_CONSTANT_EVALUATED) {
+    try {
+      S s2(str, pos, n, a);
+      assert(false);
+    } catch (std::out_of_range&) {
+      assert(pos > str.size());
     }
+  }
 #endif
 }
 
-void test_lwg2583()
-{
+void test_lwg2583() {
 #if TEST_STD_VER >= 11 && !defined(TEST_HAS_NO_EXCEPTIONS)
-    typedef std::basic_string<char, std::char_traits<char>, test_allocator<char>> StringA;
-    std::vector<StringA, std::scoped_allocator_adaptor<test_allocator<StringA>>> vs;
-    StringA s{"1234"};
-    vs.emplace_back(s, 2);
-
-    try { vs.emplace_back(s, 5); }
-    catch (const std::out_of_range&) { return; }
-    assert(false);
+  typedef std::basic_string<char, std::char_traits<char>, test_allocator<char>> StringA;
+  std::vector<StringA, std::scoped_allocator_adaptor<test_allocator<StringA>>> vs;
+  StringA s{"1234"};
+  vs.emplace_back(s, 2);
+
+  try {
+    vs.emplace_back(s, 5);
+  } catch (const std::out_of_range&) {
+    return;
+  }
+  assert(false);
 #endif
 }
 
+template <class CharT, template <class> class Alloc>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  using A = Alloc<CharT>;
+  using S = std::basic_string<CharT, std::char_traits<CharT>, A>;
+
+  test(S(A()), 0);
+  test(S(A()), 1);
+  test(S("1", A()), 0);
+  test(S("1", A()), 1);
+  test(S("1", A()), 2);
+  test(S("1234567890123456789012345678901234567890123456789012345678901234567890", A()), 0);
+  test(S("1234567890123456789012345678901234567890123456789012345678901234567890", A()), 5);
+  test(S("1234567890123456789012345678901234567890123456789012345678901234567890", A()), 50);
+  test(S("1234567890123456789012345678901234567890123456789012345678901234567890", A()), 500);
+
+  test(S(A()), 0, 0);
+  test(S(A()), 0, 1);
+  test(S(A()), 1, 0);
+  test(S(A()), 1, 1);
+  test(S(A()), 1, 2);
+  test(S("1", A()), 0, 0);
+  test(S("1", A()), 0, 1);
+  test(S("1234567890123456789012345678901234567890123456789012345678901234567890", A()), 50, 0);
+  test(S("1234567890123456789012345678901234567890123456789012345678901234567890", A()), 50, 1);
+  test(S("1234567890123456789012345678901234567890123456789012345678901234567890", A()), 50, 10);
+  test(S("1234567890123456789012345678901234567890123456789012345678901234567890", A()), 50, 100);
+
+  test(S(A()), 0, 0, A());
+  test(S(A()), 0, 1, A());
+  test(S(A()), 1, 0, A());
+  test(S(A()), 1, 1, A());
+  test(S(A()), 1, 2, A());
+  test(S("1", A()), 0, 0, A());
+  test(S("1", A()), 0, 1, A());
+  test(S("1234567890123456789012345678901234567890123456789012345678901234567890", A()), 50, 0, A());
+  test(S("1234567890123456789012345678901234567890123456789012345678901234567890", A()), 50, 1, A());
+  test(S("1234567890123456789012345678901234567890123456789012345678901234567890", A()), 50, 10, A());
+  test(S("1234567890123456789012345678901234567890123456789012345678901234567890", A()), 50, 100, A());
+}
+
+template <>
+TEST_CONSTEXPR_CXX20 void test_string<char, test_allocator>() {
+  using A = test_allocator<char>;
+  using S = std::basic_string<char, std::char_traits<char>, A>;
+
+  test(S(A(3)), 0);
+  test(S(A(3)), 1);
+  test(S("1", A(5)), 0);
+  test(S("1", A(5)), 1);
+  test(S("1", A(5)), 2);
+  test(S("1234567890123456789012345678901234567890123456789012345678901234567890", A(7)), 0);
+  test(S("1234567890123456789012345678901234567890123456789012345678901234567890", A(7)), 5);
+  test(S("1234567890123456789012345678901234567890123456789012345678901234567890", A(7)), 50);
+  test(S("1234567890123456789012345678901234567890123456789012345678901234567890", A(7)), 500);
+
+  test(S(A(3)), 0, 0);
+  test(S(A(3)), 0, 1);
+  test(S(A(3)), 1, 0);
+  test(S(A(3)), 1, 1);
+  test(S(A(3)), 1, 2);
+  test(S("1", A(5)), 0, 0);
+  test(S("1", A(5)), 0, 1);
+  test(S("1234567890123456789012345678901234567890123456789012345678901234567890", A(7)), 50, 0);
+  test(S("1234567890123456789012345678901234567890123456789012345678901234567890", A(7)), 50, 1);
+  test(S("1234567890123456789012345678901234567890123456789012345678901234567890", A(7)), 50, 10);
+  test(S("1234567890123456789012345678901234567890123456789012345678901234567890", A(7)), 50, 100);
+
+  test(S(A(3)), 0, 0, A(4));
+  test(S(A(3)), 0, 1, A(4));
+  test(S(A(3)), 1, 0, A(4));
+  test(S(A(3)), 1, 1, A(4));
+  test(S(A(3)), 1, 2, A(4));
+  test(S("1", A(5)), 0, 0, A(6));
+  test(S("1", A(5)), 0, 1, A(6));
+  test(S("1234567890123456789012345678901234567890123456789012345678901234567890", A(7)), 50, 0, A(8));
+  test(S("1234567890123456789012345678901234567890123456789012345678901234567890", A(7)), 50, 1, A(8));
+  test(S("1234567890123456789012345678901234567890123456789012345678901234567890", A(7)), 50, 10, A(8));
+  test(S("1234567890123456789012345678901234567890123456789012345678901234567890", A(7)), 50, 100, A(8));
+}
+
 TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef test_allocator<char> A;
-    typedef std::basic_string<char, std::char_traits<char>, A> S;
-
-    test(S(A(3)), 0);
-    test(S(A(3)), 1);
-    test(S("1", A(5)), 0);
-    test(S("1", A(5)), 1);
-    test(S("1", A(5)), 2);
-    test(S("1234567890123456789012345678901234567890123456789012345678901234567890", A(7)), 0);
-    test(S("1234567890123456789012345678901234567890123456789012345678901234567890", A(7)), 5);
-    test(S("1234567890123456789012345678901234567890123456789012345678901234567890", A(7)), 50);
-    test(S("1234567890123456789012345678901234567890123456789012345678901234567890", A(7)), 500);
-
-    test(S(A(3)), 0, 0);
-    test(S(A(3)), 0, 1);
-    test(S(A(3)), 1, 0);
-    test(S(A(3)), 1, 1);
-    test(S(A(3)), 1, 2);
-    test(S("1", A(5)), 0, 0);
-    test(S("1", A(5)), 0, 1);
-    test(S("1234567890123456789012345678901234567890123456789012345678901234567890", A(7)), 50, 0);
-    test(S("1234567890123456789012345678901234567890123456789012345678901234567890", A(7)), 50, 1);
-    test(S("1234567890123456789012345678901234567890123456789012345678901234567890", A(7)), 50, 10);
-    test(S("1234567890123456789012345678901234567890123456789012345678901234567890", A(7)), 50, 100);
-
-    test(S(A(3)), 0, 0, A(4));
-    test(S(A(3)), 0, 1, A(4));
-    test(S(A(3)), 1, 0, A(4));
-    test(S(A(3)), 1, 1, A(4));
-    test(S(A(3)), 1, 2, A(4));
-    test(S("1", A(5)), 0, 0, A(6));
-    test(S("1", A(5)), 0, 1, A(6));
-    test(S("1234567890123456789012345678901234567890123456789012345678901234567890", A(7)), 50, 0, A(8));
-    test(S("1234567890123456789012345678901234567890123456789012345678901234567890", A(7)), 50, 1, A(8));
-    test(S("1234567890123456789012345678901234567890123456789012345678901234567890", A(7)), 50, 10, A(8));
-    test(S("1234567890123456789012345678901234567890123456789012345678901234567890", A(7)), 50, 100, A(8));
-  }
+  test_string<char, std::allocator>();
+  test_string<char, test_allocator>();
 #if TEST_STD_VER >= 11
   {
-    typedef min_allocator<char> A;
-    typedef std::basic_string<char, std::char_traits<char>, A> S;
-
-    test(S(A()), 0);
-    test(S(A()), 1);
-    test(S("1", A()), 0);
-    test(S("1", A()), 1);
-    test(S("1", A()), 2);
-    test(S("1234567890123456789012345678901234567890123456789012345678901234567890", A()), 0);
-    test(S("1234567890123456789012345678901234567890123456789012345678901234567890", A()), 5);
-    test(S("1234567890123456789012345678901234567890123456789012345678901234567890", A()), 50);
-    test(S("1234567890123456789012345678901234567890123456789012345678901234567890", A()), 500);
-
-    test(S(A()), 0, 0);
-    test(S(A()), 0, 1);
-    test(S(A()), 1, 0);
-    test(S(A()), 1, 1);
-    test(S(A()), 1, 2);
-    test(S("1", A()), 0, 0);
-    test(S("1", A()), 0, 1);
-    test(S("1234567890123456789012345678901234567890123456789012345678901234567890", A()), 50, 0);
-    test(S("1234567890123456789012345678901234567890123456789012345678901234567890", A()), 50, 1);
-    test(S("1234567890123456789012345678901234567890123456789012345678901234567890", A()), 50, 10);
-    test(S("1234567890123456789012345678901234567890123456789012345678901234567890", A()), 50, 100);
-
-    test(S(A()), 0, 0, A());
-    test(S(A()), 0, 1, A());
-    test(S(A()), 1, 0, A());
-    test(S(A()), 1, 1, A());
-    test(S(A()), 1, 2, A());
-    test(S("1", A()), 0, 0, A());
-    test(S("1", A()), 0, 1, A());
-    test(S("1234567890123456789012345678901234567890123456789012345678901234567890", A()), 50, 0, A());
-    test(S("1234567890123456789012345678901234567890123456789012345678901234567890", A()), 50, 1, A());
-    test(S("1234567890123456789012345678901234567890123456789012345678901234567890", A()), 50, 10, A());
-    test(S("1234567890123456789012345678901234567890123456789012345678901234567890", A()), 50, 100, A());
+    test_string<char, min_allocator>();
+    test_string<char, fancy_pointer_allocator>();
   }
 #endif
 
   return true;
 }
 
-int main(int, char**)
-{
+int main(int, char**) {
   test();
 #if TEST_STD_VER > 17
   static_assert(test());
diff --git a/libcxx/test/std/strings/basic.string/string.contains/contains.char.pass.cpp b/libcxx/test/std/strings/basic.string/string.contains/contains.char.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.contains/contains.char.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.contains/contains.char.pass.cpp
@@ -15,28 +15,31 @@
 #include <cassert>
 
 #include "test_macros.h"
+#include "test_allocator.h"
 
-constexpr bool test()
-{
-    using S = std::string;
+template <class S>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  S s1{};
+  S s2{"abcde", 5};
 
-    S s1 {};
-    S s2 {"abcde", 5};
+  ASSERT_NOEXCEPT(s1.contains('e'));
 
-    ASSERT_NOEXCEPT(s1.contains('e'));
+  assert(!s1.contains('c'));
+  assert(!s1.contains('e'));
+  assert(!s1.contains('x'));
+  assert(s2.contains('c'));
+  assert(s2.contains('e'));
+  assert(!s2.contains('x'));
+}
 
-    assert(!s1.contains('c'));
-    assert(!s1.contains('e'));
-    assert(!s1.contains('x'));
-    assert( s2.contains('c'));
-    assert( s2.contains('e'));
-    assert(!s2.contains('x'));
+TEST_CONSTEXPR_CXX20 bool test() {
+  test_string<std::string>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 
-    return true;
+  return true;
 }
 
-int main(int, char**)
-{
+int main(int, char**) {
   test();
   static_assert(test());
 
diff --git a/libcxx/test/std/strings/basic.string/string.contains/contains.ptr.pass.cpp b/libcxx/test/std/strings/basic.string/string.contains/contains.ptr.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.contains/contains.ptr.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.contains/contains.ptr.pass.cpp
@@ -15,58 +15,61 @@
 #include <cassert>
 
 #include "test_macros.h"
+#include "test_allocator.h"
 
-constexpr bool test()
-{
-    using S = std::string;
+template <class S>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  const char* s = "abcde";
+  S s0;
+  S s1{s + 4, 1};
+  S s3{s + 2, 3};
+  S sNot{"xyz", 3};
 
-    const char* s = "abcde";
-    S s0;
-    S s1 {s + 4, 1};
-    S s3 {s + 2, 3};
-    S sNot {"xyz", 3};
+  assert(s0.contains(""));
+  assert(!s0.contains("e"));
 
-    assert(s0.contains(""));
-    assert(!s0.contains("e"));
+  assert(s1.contains(""));
+  assert(!s1.contains("d"));
+  assert(s1.contains("e"));
+  assert(!s1.contains("de"));
+  assert(!s1.contains("cd"));
+  assert(!s1.contains("cde"));
+  assert(!s1.contains("bcde"));
+  assert(!s1.contains("abcde"));
+  assert(!s1.contains("xyz"));
 
-    assert( s1.contains(""));
-    assert(!s1.contains("d"));
-    assert( s1.contains("e"));
-    assert(!s1.contains("de"));
-    assert(!s1.contains("cd"));
-    assert(!s1.contains("cde"));
-    assert(!s1.contains("bcde"));
-    assert(!s1.contains("abcde"));
-    assert(!s1.contains("xyz"));
+  assert(s3.contains(""));
+  assert(s3.contains("d"));
+  assert(s3.contains("e"));
+  assert(s3.contains("de"));
+  assert(s3.contains("cd"));
+  assert(!s3.contains("ce"));
+  assert(s3.contains("cde"));
+  assert(!s3.contains("edc"));
+  assert(!s3.contains("bcde"));
+  assert(!s3.contains("abcde"));
+  assert(!s3.contains("xyz"));
 
-    assert( s3.contains(""));
-    assert( s3.contains("d"));
-    assert( s3.contains("e"));
-    assert( s3.contains("de"));
-    assert( s3.contains("cd"));
-    assert(!s3.contains("ce"));
-    assert( s3.contains("cde"));
-    assert(!s3.contains("edc"));
-    assert(!s3.contains("bcde"));
-    assert(!s3.contains("abcde"));
-    assert(!s3.contains("xyz"));
+  assert(sNot.contains(""));
+  assert(!sNot.contains("d"));
+  assert(!sNot.contains("e"));
+  assert(!sNot.contains("de"));
+  assert(!sNot.contains("cd"));
+  assert(!sNot.contains("cde"));
+  assert(!sNot.contains("bcde"));
+  assert(!sNot.contains("abcde"));
+  assert(sNot.contains("xyz"));
+  assert(!sNot.contains("zyx"));
+}
 
-    assert( sNot.contains(""));
-    assert(!sNot.contains("d"));
-    assert(!sNot.contains("e"));
-    assert(!sNot.contains("de"));
-    assert(!sNot.contains("cd"));
-    assert(!sNot.contains("cde"));
-    assert(!sNot.contains("bcde"));
-    assert(!sNot.contains("abcde"));
-    assert( sNot.contains("xyz"));
-    assert(!sNot.contains("zyx"));
+TEST_CONSTEXPR_CXX20 bool test() {
+  test_string<std::string>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 
-    return true;
+  return true;
 }
 
-int main(int, char**)
-{
+int main(int, char**) {
   test();
   static_assert(test());
 
diff --git a/libcxx/test/std/strings/basic.string/string.contains/contains.string_view.pass.cpp b/libcxx/test/std/strings/basic.string/string.contains/contains.string_view.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.contains/contains.string_view.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.contains/contains.string_view.pass.cpp
@@ -15,79 +15,84 @@
 #include <cassert>
 
 #include "test_macros.h"
+#include "test_allocator.h"
+
+template <class CharT, template <class> class Alloc>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  using S  = std::basic_string<CharT, std::char_traits<CharT>, Alloc<CharT>>;
+  using SV = std::basic_string_view< CharT, std::char_traits<CharT>>;
+
+  const char* s = "abcde";
+  S s0;
+  S s1{s + 1, 1};
+  S s3{s + 1, 3};
+  S s5{s, 5};
+  S sNot{"xyz", 3};
+
+  SV sv0;
+  SV sv1{s + 1, 1};
+  SV sv2{s + 1, 2};
+  SV sv3{s + 1, 3};
+  SV sv4{s + 1, 4};
+  SV sv5{s, 5};
+  SV svNot{"xyz", 3};
+  SV svNot2{"bd", 2};
+  SV svNot3{"dcb", 3};
+
+  ASSERT_NOEXCEPT(s0.contains(sv0));
+
+  assert(s0.contains(sv0));
+  assert(!s0.contains(sv1));
+
+  assert(s1.contains(sv0));
+  assert(s1.contains(sv1));
+  assert(!s1.contains(sv2));
+  assert(!s1.contains(sv3));
+  assert(!s1.contains(sv4));
+  assert(!s1.contains(sv5));
+  assert(!s1.contains(svNot));
+  assert(!s1.contains(svNot2));
+  assert(!s1.contains(svNot3));
+
+  assert(s3.contains(sv0));
+  assert(s3.contains(sv1));
+  assert(s3.contains(sv2));
+  assert(s3.contains(sv3));
+  assert(!s3.contains(sv4));
+  assert(!s3.contains(sv5));
+  assert(!s3.contains(svNot));
+  assert(!s3.contains(svNot2));
+  assert(!s3.contains(svNot3));
+
+  assert(s5.contains(sv0));
+  assert(s5.contains(sv1));
+  assert(s5.contains(sv2));
+  assert(s5.contains(sv3));
+  assert(s5.contains(sv4));
+  assert(s5.contains(sv5));
+  assert(!s5.contains(svNot));
+  assert(!s5.contains(svNot2));
+  assert(!s5.contains(svNot3));
+
+  assert(sNot.contains(sv0));
+  assert(!sNot.contains(sv1));
+  assert(!sNot.contains(sv2));
+  assert(!sNot.contains(sv3));
+  assert(!sNot.contains(sv4));
+  assert(!sNot.contains(sv5));
+  assert(sNot.contains(svNot));
+  assert(!sNot.contains(svNot2));
+  assert(!sNot.contains(svNot3));
+}
+
+TEST_CONSTEXPR_CXX20 bool test() {
+  test_string<char, std::allocator>();
+  test_string<char, fancy_pointer_allocator>();
 
-constexpr bool test()
-{
-    using S = std::string;
-    using SV = std::string_view;
-
-    const char* s = "abcde";
-    S s0;
-    S s1 {s + 1, 1};
-    S s3 {s + 1, 3};
-    S s5 {s    , 5};
-    S sNot {"xyz", 3};
-
-    SV sv0;
-    SV sv1 {s + 1, 1};
-    SV sv2 {s + 1, 2};
-    SV sv3 {s + 1, 3};
-    SV sv4 {s + 1, 4};
-    SV sv5 {s    , 5};
-    SV svNot  {"xyz", 3};
-    SV svNot2 {"bd" , 2};
-    SV svNot3 {"dcb", 3};
-
-    ASSERT_NOEXCEPT(s0.contains(sv0));
-
-    assert( s0.contains(sv0));
-    assert(!s0.contains(sv1));
-
-    assert( s1.contains(sv0));
-    assert( s1.contains(sv1));
-    assert(!s1.contains(sv2));
-    assert(!s1.contains(sv3));
-    assert(!s1.contains(sv4));
-    assert(!s1.contains(sv5));
-    assert(!s1.contains(svNot));
-    assert(!s1.contains(svNot2));
-    assert(!s1.contains(svNot3));
-
-    assert( s3.contains(sv0));
-    assert( s3.contains(sv1));
-    assert( s3.contains(sv2));
-    assert( s3.contains(sv3));
-    assert(!s3.contains(sv4));
-    assert(!s3.contains(sv5));
-    assert(!s3.contains(svNot));
-    assert(!s3.contains(svNot2));
-    assert(!s3.contains(svNot3));
-
-    assert( s5.contains(sv0));
-    assert( s5.contains(sv1));
-    assert( s5.contains(sv2));
-    assert( s5.contains(sv3));
-    assert( s5.contains(sv4));
-    assert( s5.contains(sv5));
-    assert(!s5.contains(svNot));
-    assert(!s5.contains(svNot2));
-    assert(!s5.contains(svNot3));
-
-    assert( sNot.contains(sv0));
-    assert(!sNot.contains(sv1));
-    assert(!sNot.contains(sv2));
-    assert(!sNot.contains(sv3));
-    assert(!sNot.contains(sv4));
-    assert(!sNot.contains(sv5));
-    assert( sNot.contains(svNot));
-    assert(!sNot.contains(svNot2));
-    assert(!sNot.contains(svNot3));
-
-    return true;
+  return true;
 }
 
-int main(int, char**)
-{
+int main(int, char**) {
   test();
   static_assert(test());
 
diff --git a/libcxx/test/std/strings/basic.string/string.ends_with/ends_with.char.pass.cpp b/libcxx/test/std/strings/basic.string/string.ends_with/ends_with.char.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.ends_with/ends_with.char.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ends_with/ends_with.char.pass.cpp
@@ -15,26 +15,29 @@
 #include <cassert>
 
 #include "test_macros.h"
+#include "test_allocator.h"
 
-constexpr bool test() {
-  {
-    typedef std::string S;
-    S  s1 {};
-    S  s2 { "abcde", 5 };
+template <class S>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  S s1{};
+  S s2{"abcde", 5};
 
-    ASSERT_NOEXCEPT(s1.ends_with('e'));
+  ASSERT_NOEXCEPT(s1.ends_with('e'));
 
-    assert (!s1.ends_with('e'));
-    assert (!s1.ends_with('x'));
-    assert ( s2.ends_with('e'));
-    assert (!s2.ends_with('x'));
-  }
+  assert(!s1.ends_with('e'));
+  assert(!s1.ends_with('x'));
+  assert(s2.ends_with('e'));
+  assert(!s2.ends_with('x'));
+}
+
+TEST_CONSTEXPR_CXX20 bool test() {
+  test_string<std::string>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 
   return true;
 }
 
-int main(int, char**)
-{
+int main(int, char**) {
   test();
   static_assert(test());
 
diff --git a/libcxx/test/std/strings/basic.string/string.ends_with/ends_with.ptr.pass.cpp b/libcxx/test/std/strings/basic.string/string.ends_with/ends_with.ptr.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.ends_with/ends_with.ptr.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ends_with/ends_with.ptr.pass.cpp
@@ -15,49 +15,53 @@
 #include <cassert>
 
 #include "test_macros.h"
+#include "test_allocator.h"
 
-constexpr bool test() {
-  {
-    typedef std::string S;
-    const char *s = "abcde";
+template <class S>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  const char* s = "abcde";
 
-    S   s0;
-    S   s1  { s + 4, 1 };
-    S   s2  { s + 3, 2 };
-//  S   s3  { s + 2, 3 };
-//  S   s4  { s + 1, 4 };
-//  S   s5  { s,     5 };
-    S  sNot { "def", 3 };
+  S s0;
+  S s1{s + 4, 1};
+  S s2{s + 3, 2};
+  //  S   s3  { s + 2, 3 };
+  //  S   s4  { s + 1, 4 };
+  //  S   s5  { s,     5 };
+  S sNot{"def", 3};
 
-    LIBCPP_ASSERT_NOEXCEPT(s0.ends_with(""));
+  LIBCPP_ASSERT_NOEXCEPT(s0.ends_with(""));
 
-    assert ( s0.ends_with(""));
-    assert (!s0.ends_with("e"));
+  assert(s0.ends_with(""));
+  assert(!s0.ends_with("e"));
 
-    assert ( s1.ends_with(""));
-    assert ( s1.ends_with("e"));
-    assert (!s1.ends_with("de"));
-    assert (!s1.ends_with("cde"));
-    assert (!s1.ends_with("bcde"));
-    assert (!s1.ends_with("abcde"));
-    assert (!s1.ends_with("def"));
+  assert(s1.ends_with(""));
+  assert(s1.ends_with("e"));
+  assert(!s1.ends_with("de"));
+  assert(!s1.ends_with("cde"));
+  assert(!s1.ends_with("bcde"));
+  assert(!s1.ends_with("abcde"));
+  assert(!s1.ends_with("def"));
 
-    assert ( s2.ends_with(""));
-    assert ( s2.ends_with("e"));
-    assert ( s2.ends_with("de"));
-    assert (!s2.ends_with("cde"));
-    assert (!s2.ends_with("bcde"));
-    assert (!s2.ends_with("abcde"));
-    assert (!s2.ends_with("def"));
+  assert(s2.ends_with(""));
+  assert(s2.ends_with("e"));
+  assert(s2.ends_with("de"));
+  assert(!s2.ends_with("cde"));
+  assert(!s2.ends_with("bcde"));
+  assert(!s2.ends_with("abcde"));
+  assert(!s2.ends_with("def"));
 
-    assert ( sNot.ends_with(""));
-    assert (!sNot.ends_with("e"));
-    assert (!sNot.ends_with("de"));
-    assert (!sNot.ends_with("cde"));
-    assert (!sNot.ends_with("bcde"));
-    assert (!sNot.ends_with("abcde"));
-    assert ( sNot.ends_with("def"));
-  }
+  assert(sNot.ends_with(""));
+  assert(!sNot.ends_with("e"));
+  assert(!sNot.ends_with("de"));
+  assert(!sNot.ends_with("cde"));
+  assert(!sNot.ends_with("bcde"));
+  assert(!sNot.ends_with("abcde"));
+  assert(sNot.ends_with("def"));
+}
+
+TEST_CONSTEXPR_CXX20 bool test() {
+  test_string<std::string>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 
   return true;
 }
diff --git a/libcxx/test/std/strings/basic.string/string.ends_with/ends_with.string_view.pass.cpp b/libcxx/test/std/strings/basic.string/string.ends_with/ends_with.string_view.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.ends_with/ends_with.string_view.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ends_with/ends_with.string_view.pass.cpp
@@ -15,58 +15,63 @@
 #include <cassert>
 
 #include "test_macros.h"
+#include "test_allocator.h"
 
-constexpr bool test() {
-  {
-    typedef std::string S;
-    typedef std::string_view SV;
-    const char *s = "abcde";
-
-    S   s0;
-    S   s1  { s + 4, 1 };
-    S   s2  { s + 3, 2 };
-//  S   s3  { s + 2, 3 };
-//  S   s4  { s + 1, 4 };
-//  S   s5  { s,     5 };
-    S  sNot { "def", 3 };
-
-    SV  sv0;
-    SV  sv1 { s + 4, 1 };
-    SV  sv2 { s + 3, 2 };
-    SV  sv3 { s + 2, 3 };
-    SV  sv4 { s + 1, 4 };
-    SV  sv5 { s    , 5 };
-    SV svNot {"def", 3 };
-
-    ASSERT_NOEXCEPT(s0.ends_with(sv0));
-
-    assert ( s0.ends_with(sv0));
-    assert (!s0.ends_with(sv1));
-
-    assert ( s1.ends_with(sv0));
-    assert ( s1.ends_with(sv1));
-    assert (!s1.ends_with(sv2));
-    assert (!s1.ends_with(sv3));
-    assert (!s1.ends_with(sv4));
-    assert (!s1.ends_with(sv5));
-    assert (!s1.ends_with(svNot));
-
-    assert ( s2.ends_with(sv0));
-    assert ( s2.ends_with(sv1));
-    assert ( s2.ends_with(sv2));
-    assert (!s2.ends_with(sv3));
-    assert (!s2.ends_with(sv4));
-    assert (!s2.ends_with(sv5));
-    assert (!s2.ends_with(svNot));
-
-    assert ( sNot.ends_with(sv0));
-    assert (!sNot.ends_with(sv1));
-    assert (!sNot.ends_with(sv2));
-    assert (!sNot.ends_with(sv3));
-    assert (!sNot.ends_with(sv4));
-    assert (!sNot.ends_with(sv5));
-    assert ( sNot.ends_with(svNot));
-  }
+template <class CharT, template <class> class Alloc>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  using S       = std::basic_string<CharT, std::char_traits<CharT>, Alloc<CharT>>;
+  using SV      = std::basic_string_view< CharT, std::char_traits<CharT>>;
+  const char* s = "abcde";
+
+  S s0;
+  S s1{s + 4, 1};
+  S s2{s + 3, 2};
+  //  S   s3  { s + 2, 3 };
+  //  S   s4  { s + 1, 4 };
+  //  S   s5  { s,     5 };
+  S sNot{"def", 3};
+
+  SV sv0;
+  SV sv1{s + 4, 1};
+  SV sv2{s + 3, 2};
+  SV sv3{s + 2, 3};
+  SV sv4{s + 1, 4};
+  SV sv5{s, 5};
+  SV svNot{"def", 3};
+
+  ASSERT_NOEXCEPT(s0.ends_with(sv0));
+
+  assert(s0.ends_with(sv0));
+  assert(!s0.ends_with(sv1));
+
+  assert(s1.ends_with(sv0));
+  assert(s1.ends_with(sv1));
+  assert(!s1.ends_with(sv2));
+  assert(!s1.ends_with(sv3));
+  assert(!s1.ends_with(sv4));
+  assert(!s1.ends_with(sv5));
+  assert(!s1.ends_with(svNot));
+
+  assert(s2.ends_with(sv0));
+  assert(s2.ends_with(sv1));
+  assert(s2.ends_with(sv2));
+  assert(!s2.ends_with(sv3));
+  assert(!s2.ends_with(sv4));
+  assert(!s2.ends_with(sv5));
+  assert(!s2.ends_with(svNot));
+
+  assert(sNot.ends_with(sv0));
+  assert(!sNot.ends_with(sv1));
+  assert(!sNot.ends_with(sv2));
+  assert(!sNot.ends_with(sv3));
+  assert(!sNot.ends_with(sv4));
+  assert(!sNot.ends_with(sv5));
+  assert(sNot.ends_with(svNot));
+}
+
+TEST_CONSTEXPR_CXX20 bool test() {
+  test_string<char, std::allocator>();
+  test_string<char, fancy_pointer_allocator>();
 
   return true;
 }
diff --git a/libcxx/test/std/strings/basic.string/string.iterators/begin.pass.cpp b/libcxx/test/std/strings/basic.string/string.iterators/begin.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.iterators/begin.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.iterators/begin.pass.cpp
@@ -16,40 +16,36 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
-TEST_CONSTEXPR_CXX20 void
-test(S s)
-{
-    const S& cs = s;
-    typename S::iterator b = s.begin();
-    typename S::const_iterator cb = cs.begin();
-    if (!s.empty())
-    {
-        assert(*b == s[0]);
-    }
-    assert(b == cb);
+TEST_CONSTEXPR_CXX20 void test(S s) {
+  const S& cs                   = s;
+  typename S::iterator b        = s.begin();
+  typename S::const_iterator cb = cs.begin();
+  if (!s.empty()) {
+    assert(*b == s[0]);
+  }
+  assert(b == cb);
+}
+
+template <class S>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  test(S());
+  test(S("123"));
 }
 
 TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    test(S());
-    test(S("123"));
-  }
+  test_string<std::string>();
 #if TEST_STD_VER >= 11
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    test(S());
-    test(S("123"));
-  }
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
 }
 
-int main(int, char**)
-{
+int main(int, char**) {
   test();
 #if TEST_STD_VER > 17
   static_assert(test());
diff --git a/libcxx/test/std/strings/basic.string/string.iterators/cbegin.pass.cpp b/libcxx/test/std/strings/basic.string/string.iterators/cbegin.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.iterators/cbegin.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.iterators/cbegin.pass.cpp
@@ -15,38 +15,34 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
-TEST_CONSTEXPR_CXX20 void
-test(const S& s)
-{
-    typename S::const_iterator cb = s.cbegin();
-    if (!s.empty())
-    {
-        assert(*cb == s[0]);
-    }
-    assert(cb == s.begin());
+TEST_CONSTEXPR_CXX20 void test(const S& s) {
+  typename S::const_iterator cb = s.cbegin();
+  if (!s.empty()) {
+    assert(*cb == s[0]);
+  }
+  assert(cb == s.begin());
+}
+
+template <class S>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  test(S());
+  test(S("123"));
 }
 
 TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    test(S());
-    test(S("123"));
-  }
+  test_string<std::string>();
 #if TEST_STD_VER >= 11
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    test(S());
-    test(S("123"));
-  }
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
 }
 
-int main(int, char**)
-{
+int main(int, char**) {
   test();
 #if TEST_STD_VER > 17
   static_assert(test());
diff --git a/libcxx/test/std/strings/basic.string/string.iterators/cend.pass.cpp b/libcxx/test/std/strings/basic.string/string.iterators/cend.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.iterators/cend.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.iterators/cend.pass.cpp
@@ -15,34 +15,31 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
-TEST_CONSTEXPR_CXX20 void
-test(const S& s)
-{
-    typename S::const_iterator ce = s.cend();
-    assert(ce == s.end());
+TEST_CONSTEXPR_CXX20 void test(const S& s) {
+  typename S::const_iterator ce = s.cend();
+  assert(ce == s.end());
+}
+
+template <class S>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  test(S());
+  test(S("123"));
 }
 
 TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    test(S());
-    test(S("123"));
-  }
+  test_string<std::string>();
 #if TEST_STD_VER >= 11
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    test(S());
-    test(S("123"));
-  }
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
 }
 
-int main(int, char**)
-{
+int main(int, char**) {
   test();
 #if TEST_STD_VER > 17
   static_assert(test());
diff --git a/libcxx/test/std/strings/basic.string/string.iterators/crbegin.pass.cpp b/libcxx/test/std/strings/basic.string/string.iterators/crbegin.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.iterators/crbegin.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.iterators/crbegin.pass.cpp
@@ -15,38 +15,34 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
-TEST_CONSTEXPR_CXX20 void
-test(const S& s)
-{
-    typename S::const_reverse_iterator cb = s.crbegin();
-    if (!s.empty())
-    {
-        assert(*cb == s.back());
-    }
-    assert(cb == s.rbegin());
+TEST_CONSTEXPR_CXX20 void test(const S& s) {
+  typename S::const_reverse_iterator cb = s.crbegin();
+  if (!s.empty()) {
+    assert(*cb == s.back());
+  }
+  assert(cb == s.rbegin());
+}
+
+template <class S>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  test(S());
+  test(S("123"));
 }
 
 TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    test(S());
-    test(S("123"));
-  }
+  test_string<std::string>();
 #if TEST_STD_VER >= 11
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    test(S());
-    test(S("123"));
-  }
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
 }
 
-int main(int, char**)
-{
+int main(int, char**) {
   test();
 #if TEST_STD_VER > 17
   static_assert(test());
diff --git a/libcxx/test/std/strings/basic.string/string.iterators/crend.pass.cpp b/libcxx/test/std/strings/basic.string/string.iterators/crend.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.iterators/crend.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.iterators/crend.pass.cpp
@@ -15,34 +15,31 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
-TEST_CONSTEXPR_CXX20 void
-test(const S& s)
-{
-    typename S::const_reverse_iterator ce = s.crend();
-    assert(ce == s.rend());
+TEST_CONSTEXPR_CXX20 void test(const S& s) {
+  typename S::const_reverse_iterator ce = s.crend();
+  assert(ce == s.rend());
+}
+
+template <class S>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  test(S());
+  test(S("123"));
 }
 
 TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    test(S());
-    test(S("123"));
-  }
+  test_string<std::string>();
 #if TEST_STD_VER >= 11
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    test(S());
-    test(S("123"));
-  }
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
 }
 
-int main(int, char**)
-{
+int main(int, char**) {
   test();
 #if TEST_STD_VER > 17
   static_assert(test());
diff --git a/libcxx/test/std/strings/basic.string/string.iterators/end.pass.cpp b/libcxx/test/std/strings/basic.string/string.iterators/end.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.iterators/end.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.iterators/end.pass.cpp
@@ -17,42 +17,38 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
-TEST_CONSTEXPR_CXX20 void
-test(S s)
-{
-    const S& cs = s;
-    typename S::iterator e = s.end();
-    typename S::const_iterator ce = cs.end();
-    if (s.empty())
-    {
-        assert(e == s.begin());
-        assert(ce == cs.begin());
-    }
-    assert(static_cast<std::size_t>(e - s.begin()) == s.size());
-    assert(static_cast<std::size_t>(ce - cs.begin()) == cs.size());
+TEST_CONSTEXPR_CXX20 void test(S s) {
+  const S& cs                   = s;
+  typename S::iterator e        = s.end();
+  typename S::const_iterator ce = cs.end();
+  if (s.empty()) {
+    assert(e == s.begin());
+    assert(ce == cs.begin());
+  }
+  assert(static_cast<std::size_t>(e - s.begin()) == s.size());
+  assert(static_cast<std::size_t>(ce - cs.begin()) == cs.size());
+}
+
+template <class S>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  test(S());
+  test(S("123"));
 }
 
 TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    test(S());
-    test(S("123"));
-  }
+  test_string<std::string>();
 #if TEST_STD_VER >= 11
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    test(S());
-    test(S("123"));
-  }
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
 }
 
-int main(int, char**)
-{
+int main(int, char**) {
   test();
 #if TEST_STD_VER > 17
   static_assert(test());
diff --git a/libcxx/test/std/strings/basic.string/string.iterators/rbegin.pass.cpp b/libcxx/test/std/strings/basic.string/string.iterators/rbegin.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.iterators/rbegin.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.iterators/rbegin.pass.cpp
@@ -16,40 +16,36 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
-TEST_CONSTEXPR_CXX20 void
-test(S s)
-{
-    const S& cs = s;
-    typename S::reverse_iterator b = s.rbegin();
-    typename S::const_reverse_iterator cb = cs.rbegin();
-    if (!s.empty())
-    {
-        assert(*b == s.back());
-    }
-    assert(b == cb);
+TEST_CONSTEXPR_CXX20 void test(S s) {
+  const S& cs                           = s;
+  typename S::reverse_iterator b        = s.rbegin();
+  typename S::const_reverse_iterator cb = cs.rbegin();
+  if (!s.empty()) {
+    assert(*b == s.back());
+  }
+  assert(b == cb);
+}
+
+template <class S>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  test(S());
+  test(S("123"));
 }
 
 TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    test(S());
-    test(S("123"));
-  }
+  test_string<std::string>();
 #if TEST_STD_VER >= 11
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    test(S());
-    test(S("123"));
-  }
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
 }
 
-int main(int, char**)
-{
+int main(int, char**) {
   test();
 #if TEST_STD_VER > 17
   static_assert(test());
diff --git a/libcxx/test/std/strings/basic.string/string.iterators/rend.pass.cpp b/libcxx/test/std/strings/basic.string/string.iterators/rend.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.iterators/rend.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.iterators/rend.pass.cpp
@@ -17,42 +17,38 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
-TEST_CONSTEXPR_CXX20 void
-test(S s)
-{
-    const S& cs = s;
-    typename S::reverse_iterator e = s.rend();
-    typename S::const_reverse_iterator ce = cs.rend();
-    if (s.empty())
-    {
-        assert(e == s.rbegin());
-        assert(ce == cs.rbegin());
-    }
-    assert(static_cast<std::size_t>(e - s.rbegin()) == s.size());
-    assert(static_cast<std::size_t>(ce - cs.rbegin()) == cs.size());
+TEST_CONSTEXPR_CXX20 void test(S s) {
+  const S& cs                           = s;
+  typename S::reverse_iterator e        = s.rend();
+  typename S::const_reverse_iterator ce = cs.rend();
+  if (s.empty()) {
+    assert(e == s.rbegin());
+    assert(ce == cs.rbegin());
+  }
+  assert(static_cast<std::size_t>(e - s.rbegin()) == s.size());
+  assert(static_cast<std::size_t>(ce - cs.rbegin()) == cs.size());
+}
+
+template <class S>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  test(S());
+  test(S("123"));
 }
 
 TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    test(S());
-    test(S("123"));
-  }
+  test_string<std::string>();
 #if TEST_STD_VER >= 11
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    test(S());
-    test(S("123"));
-  }
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
 }
 
-int main(int, char**)
-{
+int main(int, char**) {
   test();
 #if TEST_STD_VER > 17
   static_assert(test());
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/robust_against_adl.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/robust_against_adl.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.modifiers/robust_against_adl.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/robust_against_adl.pass.cpp
@@ -12,6 +12,7 @@
 #include <string>
 
 #include "test_macros.h"
+#include "test_allocator.h"
 
 struct Incomplete;
 template<class T> struct Holder { T t; };
@@ -23,14 +24,22 @@
     TEST_CONSTEXPR operator char() const { return ch_; }
 };
 
-TEST_CONSTEXPR_CXX20 bool test() {
-  std::string s;
+template <class S>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  S s;
   Charlike<Holder<Incomplete> > a[] = {'m', 'a', 'h', 'i'};
-  s.append(a, a+4);
-  s.assign(a, a+4);
-  s.insert(s.begin(), a, a+4);
-  s.replace(s.begin(), s.begin()+4, a, a+4);
+  s.append(a, a + 4);
+  s.assign(a, a + 4);
+  s.insert(s.begin(), a, a + 4);
+  s.replace(s.begin(), s.begin() + 4, a, a + 4);
   assert(s == "mahimahi");
+}
+
+TEST_CONSTEXPR_CXX20 bool test() {
+  test_string<std::string>();
+#if TEST_STD_VER >= 11
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
+#endif
 
   return true;
 }
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_append/T_size_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_append/T_size_size.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_append/T_size_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_append/T_size_size.pass.cpp
@@ -18,56 +18,43 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S, class SV>
-TEST_CONSTEXPR_CXX20 void
-test(S s, SV sv, typename S::size_type pos, typename S::size_type n, S expected)
-{
-    if (pos <= sv.size())
-    {
-        s.append(sv, pos, n);
-        LIBCPP_ASSERT(s.__invariants());
-        assert(s == expected);
-    }
+TEST_CONSTEXPR_CXX20 void test(S s, SV sv, typename S::size_type pos, typename S::size_type n, S expected) {
+  if (pos <= sv.size()) {
+    s.append(sv, pos, n);
+    LIBCPP_ASSERT(s.__invariants());
+    assert(s == expected);
+  }
 #ifndef TEST_HAS_NO_EXCEPTIONS
-    else if (!TEST_IS_CONSTANT_EVALUATED)
-    {
-        try
-        {
-            s.append(sv, pos, n);
-            assert(false);
-        }
-        catch (std::out_of_range&)
-        {
-            assert(pos > sv.size());
-        }
+  else if (!TEST_IS_CONSTANT_EVALUATED) {
+    try {
+      s.append(sv, pos, n);
+      assert(false);
+    } catch (std::out_of_range&) {
+      assert(pos > sv.size());
     }
+  }
 #endif
 }
 
 template <class S, class SV>
-TEST_CONSTEXPR_CXX20 void
-test_npos(S s, SV sv, typename S::size_type pos, S expected)
-{
-    if (pos <= sv.size())
-    {
-        s.append(sv, pos);
-        LIBCPP_ASSERT(s.__invariants());
-        assert(s == expected);
-    }
+TEST_CONSTEXPR_CXX20 void test_npos(S s, SV sv, typename S::size_type pos, S expected) {
+  if (pos <= sv.size()) {
+    s.append(sv, pos);
+    LIBCPP_ASSERT(s.__invariants());
+    assert(s == expected);
+  }
 #ifndef TEST_HAS_NO_EXCEPTIONS
-    else if (!TEST_IS_CONSTANT_EVALUATED)
-    {
-        try
-        {
-            s.append(sv, pos);
-            assert(false);
-        }
-        catch (std::out_of_range&)
-        {
-            assert(pos > sv.size());
-        }
+  else if (!TEST_IS_CONSTANT_EVALUATED) {
+    try {
+      s.append(sv, pos);
+      assert(false);
+    } catch (std::out_of_range&) {
+      assert(pos > sv.size());
     }
+  }
 #endif
 }
 
@@ -101,6 +88,7 @@
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   {
@@ -177,8 +165,7 @@
   return true;
 }
 
-int main(int, char**)
-{
+int main(int, char**) {
   test();
 #if TEST_STD_VER > 17
   static_assert(test());
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_append/initializer_list.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_append/initializer_list.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_append/initializer_list.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_append/initializer_list.pass.cpp
@@ -17,25 +17,26 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
+
+template <class S>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  S s("123");
+  s.append({'a', 'b', 'c'});
+  assert(s == "123abc");
+}
 
 TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    std::string s("123");
-    s.append({'a', 'b', 'c'});
-    assert(s == "123abc");
-  }
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    S s("123");
-    s.append({'a', 'b', 'c'});
-    assert(s == "123abc");
-  }
+  test_string<std::string>();
+#if TEST_STD_VER >= 11
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
+#endif
 
   return true;
 }
 
-int main(int, char**)
-{
+int main(int, char**) {
   test();
 #if TEST_STD_VER > 17
   static_assert(test());
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_append/iterator.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_append/iterator.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_append/iterator.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_append/iterator.pass.cpp
@@ -17,18 +17,19 @@
 #include "test_macros.h"
 #include "test_iterators.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S, class It>
-TEST_CONSTEXPR_CXX20 void
-test(S s, It first, It last, S expected)
-{
-    s.append(first, last);
-    LIBCPP_ASSERT(s.__invariants());
-    assert(s == expected);
+TEST_CONSTEXPR_CXX20 void test(S s, It first, It last, S expected) {
+  s.append(first, last);
+  LIBCPP_ASSERT(s.__invariants());
+  assert(s == expected);
 }
 
 #ifndef TEST_HAS_NO_EXCEPTIONS
-struct Widget { operator char() const { throw 42; } };
+struct Widget {
+  operator char() const { throw 42; }
+};
 
 template <class S, class It>
 TEST_CONSTEXPR_CXX20 void
@@ -115,6 +116,7 @@
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
 #ifndef TEST_HAS_NO_EXCEPTIONS
@@ -162,38 +164,42 @@
   }
 
   { // regression-test appending to self in sneaky ways
-    std::string s_short = "hello";
-    std::string s_long = "Lorem ipsum dolor sit amet, consectetur/";
-    std::string s_othertype = "hello";
-    std::string s_sneaky = "hello";
+    typedef std::string S;
+    S s_short     = "hello";
+    S s_long      = "Lorem ipsum dolor sit amet, consectetur/";
+    S s_othertype = "hello";
+    S s_sneaky    = "hello";
 
-    test(s_short, s_short.data() + s_short.size(), s_short.data() + s_short.size() + 1,
-         std::string("hello\0", 6));
-    test(s_long, s_long.data() + s_long.size(), s_long.data() + s_long.size() + 1,
-         std::string("Lorem ipsum dolor sit amet, consectetur/\0", 41));
+    test(s_short, s_short.data() + s_short.size(), s_short.data() + s_short.size() + 1, S("hello\0", 6));
+    test(s_long,
+         s_long.data() + s_long.size(),
+         s_long.data() + s_long.size() + 1,
+         S("Lorem ipsum dolor sit amet, consectetur/\0", 41));
 
     s_sneaky.reserve(12);
-    test(s_sneaky, s_sneaky.data(), s_sneaky.data() + 6, std::string("hellohello\0", 11));
+    test(s_sneaky, s_sneaky.data(), s_sneaky.data() + 6, S("hellohello\0", 11));
 
-     if (!TEST_IS_CONSTANT_EVALUATED) {
-       const unsigned char *first = reinterpret_cast<const unsigned char*>(s_othertype.data());
-       test(s_othertype, first + 2, first + 5, std::string("hellollo"));
-     }
+    if (!TEST_IS_CONSTANT_EVALUATED) {
+      const unsigned char* first = reinterpret_cast<const unsigned char*>(s_othertype.data());
+      test(s_othertype, first + 2, first + 5, S("hellollo"));
+    }
   }
 
   { // test with a move iterator that returns char&&
+    typedef std::string S;
     typedef forward_iterator<const char*> It;
     typedef std::move_iterator<It> MoveIt;
     const char p[] = "ABCD";
-    std::string s;
+    S s;
     s.append(MoveIt(It(std::begin(p))), MoveIt(It(std::end(p) - 1)));
     assert(s == "ABCD");
   }
   { // test with a move iterator that returns char&&
+    typedef std::string S;
     typedef const char* It;
     typedef std::move_iterator<It> MoveIt;
     const char p[] = "ABCD";
-    std::string s;
+    S s;
     s.append(MoveIt(It(std::begin(p))), MoveIt(It(std::end(p) - 1)));
     assert(s == "ABCD");
   }
@@ -201,8 +207,7 @@
   return true;
 }
 
-int main(int, char**)
-{
+int main(int, char**) {
   test();
 #if TEST_STD_VER > 17
   static_assert(test());
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_append/pointer.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_append/pointer.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_append/pointer.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_append/pointer.pass.cpp
@@ -16,14 +16,13 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
-TEST_CONSTEXPR_CXX20 void
-test(S s, const typename S::value_type* str, S expected)
-{
-    s.append(str);
-    LIBCPP_ASSERT(s.__invariants());
-    assert(s == expected);
+TEST_CONSTEXPR_CXX20 void test(S s, const typename S::value_type* str, S expected) {
+  s.append(str);
+  LIBCPP_ASSERT(s.__invariants());
+  assert(s == expected);
 }
 
 template <class S>
@@ -46,6 +45,7 @@
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   { // test appending to self
@@ -66,8 +66,7 @@
   return true;
 }
 
-int main(int, char**)
-{
+int main(int, char**) {
   test();
 #if TEST_STD_VER > 17
   static_assert(test());
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_append/pointer_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_append/pointer_size.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_append/pointer_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_append/pointer_size.pass.cpp
@@ -17,14 +17,13 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
-TEST_CONSTEXPR_CXX20 void
-test(S s, const typename S::value_type* str, typename S::size_type n, S expected)
-{
-    s.append(str, n);
-    LIBCPP_ASSERT(s.__invariants());
-    assert(s == expected);
+TEST_CONSTEXPR_CXX20 void test(S s, const typename S::value_type* str, typename S::size_type n, S expected) {
+  s.append(str, n);
+  LIBCPP_ASSERT(s.__invariants());
+  assert(s == expected);
 }
 
 template <class S>
@@ -51,6 +50,7 @@
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   { // test appending to self
@@ -72,8 +72,7 @@
   return true;
 }
 
-int main(int, char**)
-{
+int main(int, char**) {
   test();
 #if TEST_STD_VER > 17
   static_assert(test());
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_append/push_back.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_append/push_back.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_append/push_back.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_append/push_back.pass.cpp
@@ -15,40 +15,35 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
-struct veryLarge
-{
+struct veryLarge {
   long long a;
   char b;
 };
 
 template <class S>
-TEST_CONSTEXPR_CXX20 void
-test(S s, typename S::value_type c, S expected)
-{
-    s.push_back(c);
-    LIBCPP_ASSERT(s.__invariants());
-    assert(s == expected);
+TEST_CONSTEXPR_CXX20 void test(S s, typename S::value_type c, S expected) {
+  s.push_back(c);
+  LIBCPP_ASSERT(s.__invariants());
+  assert(s == expected);
+}
+
+template <class S>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  test(S(), 'a', S(1, 'a'));
+  test(S("12345"), 'a', S("12345a"));
+  test(S("12345678901234567890"), 'a', S("12345678901234567890a"));
 }
 
 TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    test(S(), 'a', S(1, 'a'));
-    test(S("12345"), 'a', S("12345a"));
-    test(S("12345678901234567890"), 'a', S("12345678901234567890a"));
-  }
+  test_string<std::string>();
 #if TEST_STD_VER >= 11
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    test(S(), 'a', S(1, 'a'));
-    test(S("12345"), 'a', S("12345a"));
-    test(S("12345678901234567890"), 'a', S("12345678901234567890a"));
-  }
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
-
   {
-// https://llvm.org/PR31454
+    // https://llvm.org/PR31454
     std::basic_string<veryLarge> s;
     veryLarge vl = {};
     s.push_back(vl);
@@ -59,8 +54,7 @@
   return true;
 }
 
-int main(int, char**)
-{
+int main(int, char**) {
   test();
 #if TEST_STD_VER > 17
   static_assert(test());
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_append/size_char.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_append/size_char.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_append/size_char.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_append/size_char.pass.cpp
@@ -16,14 +16,13 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
-TEST_CONSTEXPR_CXX20 void
-test(S s, typename S::size_type n, typename S::value_type c, S expected)
-{
-    s.append(n, c);
-    LIBCPP_ASSERT(s.__invariants());
-    assert(s == expected);
+TEST_CONSTEXPR_CXX20 void test(S s, typename S::size_type n, typename S::value_type c, S expected) {
+  s.append(n, c);
+  LIBCPP_ASSERT(s.__invariants());
+  assert(s == expected);
 }
 
 template <class S>
@@ -45,14 +44,13 @@
 TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
-  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
-
   return true;
 }
 
-int main(int, char**)
-{
+int main(int, char**) {
   test();
 #if TEST_STD_VER > 17
   static_assert(test());
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_append/string.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_append/string.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_append/string.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_append/string.pass.cpp
@@ -16,14 +16,13 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
-TEST_CONSTEXPR_CXX20 void
-test(S s, S str, S expected)
-{
-    s.append(str);
-    LIBCPP_ASSERT(s.__invariants());
-    assert(s == expected);
+TEST_CONSTEXPR_CXX20 void test(S s, S str, S expected) {
+  s.append(str);
+  LIBCPP_ASSERT(s.__invariants());
+  assert(s == expected);
 }
 
 template <class S>
@@ -54,6 +53,7 @@
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
 #if TEST_STD_VER >= 11
@@ -68,8 +68,7 @@
   return true;
 }
 
-int main(int, char**)
-{
+int main(int, char**) {
   test();
 #if TEST_STD_VER > 17
   static_assert(test());
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_append/string_size_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_append/string_size_size.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_append/string_size_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_append/string_size_size.pass.cpp
@@ -18,56 +18,43 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
-TEST_CONSTEXPR_CXX20 void
-test(S s, S str, typename S::size_type pos, typename S::size_type n, S expected)
-{
-    if (pos <= str.size())
-    {
-        s.append(str, pos, n);
-        LIBCPP_ASSERT(s.__invariants());
-        assert(s == expected);
-    }
+TEST_CONSTEXPR_CXX20 void test(S s, S str, typename S::size_type pos, typename S::size_type n, S expected) {
+  if (pos <= str.size()) {
+    s.append(str, pos, n);
+    LIBCPP_ASSERT(s.__invariants());
+    assert(s == expected);
+  }
 #ifndef TEST_HAS_NO_EXCEPTIONS
-    else if (!TEST_IS_CONSTANT_EVALUATED)
-    {
-        try
-        {
-            s.append(str, pos, n);
-            assert(false);
-        }
-        catch (std::out_of_range&)
-        {
-            assert(pos > str.size());
-        }
+  else if (!TEST_IS_CONSTANT_EVALUATED) {
+    try {
+      s.append(str, pos, n);
+      assert(false);
+    } catch (std::out_of_range&) {
+      assert(pos > str.size());
     }
+  }
 #endif
 }
 
 template <class S>
-TEST_CONSTEXPR_CXX20 void
-test_npos(S s, S str, typename S::size_type pos, S expected)
-{
-    if (pos <= str.size())
-    {
-        s.append(str, pos);
-        LIBCPP_ASSERT(s.__invariants());
-        assert(s == expected);
-    }
+TEST_CONSTEXPR_CXX20 void test_npos(S s, S str, typename S::size_type pos, S expected) {
+  if (pos <= str.size()) {
+    s.append(str, pos);
+    LIBCPP_ASSERT(s.__invariants());
+    assert(s == expected);
+  }
 #ifndef TEST_HAS_NO_EXCEPTIONS
-    else if (!TEST_IS_CONSTANT_EVALUATED)
-    {
-        try
-        {
-            s.append(str, pos);
-            assert(false);
-        }
-        catch (std::out_of_range&)
-        {
-            assert(pos > str.size());
-        }
+  else if (!TEST_IS_CONSTANT_EVALUATED) {
+    try {
+      s.append(str, pos);
+      assert(false);
+    } catch (std::out_of_range&) {
+      assert(pos > str.size());
     }
+  }
 #endif
 }
 
@@ -100,6 +87,7 @@
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   {
@@ -116,8 +104,7 @@
   return true;
 }
 
-int main(int, char**)
-{
+int main(int, char**) {
   test();
 #if TEST_STD_VER > 17
   static_assert(test());
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_append/string_view.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_append/string_view.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_append/string_view.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_append/string_view.pass.cpp
@@ -17,14 +17,13 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S, class SV>
-TEST_CONSTEXPR_CXX20 void
-test(S s, SV sv, S expected)
-{
-    s.append(sv);
-    LIBCPP_ASSERT(s.__invariants());
-    assert(s == expected);
+TEST_CONSTEXPR_CXX20 void test(S s, SV sv, S expected) {
+  s.append(sv);
+  LIBCPP_ASSERT(s.__invariants());
+  assert(s == expected);
 }
 
 template <class S>
@@ -56,13 +55,12 @@
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
-
   return true;
 }
 
-int main(int, char**)
-{
+int main(int, char**) {
   test();
 #if TEST_STD_VER > 17
   static_assert(test());
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/T_size_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/T_size_size.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/T_size_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/T_size_size.pass.cpp
@@ -17,6 +17,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S, class SV>
 TEST_CONSTEXPR_CXX20 void
@@ -100,6 +101,7 @@
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   {
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/initializer_list.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/initializer_list.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/initializer_list.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/initializer_list.pass.cpp
@@ -17,19 +17,21 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
+
+template <class S>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  S s("123");
+  s.assign({'a', 'b', 'c'});
+  assert(s == "abc");
+}
 
 TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    std::string s("123");
-    s.assign({'a', 'b', 'c'});
-    assert(s == "abc");
-  }
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    S s("123");
-    s.assign({'a', 'b', 'c'});
-    assert(s == "abc");
-  }
+  test_string<std::string>();
+#if TEST_STD_VER >= 11
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
+#endif
 
   return true;
 }
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/iterator.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/iterator.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/iterator.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/iterator.pass.cpp
@@ -17,6 +17,7 @@
 #include "test_macros.h"
 #include "test_iterators.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S, class It>
 TEST_CONSTEXPR_CXX20 void
@@ -115,6 +116,7 @@
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
 #ifndef TEST_HAS_NO_EXCEPTIONS
@@ -123,16 +125,16 @@
     typedef ThrowingIterator<char> TIter;
     typedef cpp17_input_iterator<TIter> IIter;
     const char* s = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
-    test_exceptions(S(), IIter(TIter(s, s+10, 4, TIter::TAIncrement)), IIter(TIter()));
-    test_exceptions(S(), IIter(TIter(s, s+10, 5, TIter::TADereference)), IIter(TIter()));
-    test_exceptions(S(), IIter(TIter(s, s+10, 6, TIter::TAComparison)), IIter(TIter()));
+    test_exceptions(S(), IIter(TIter(s, s + 10, 4, TIter::TAIncrement)), IIter(TIter()));
+    test_exceptions(S(), IIter(TIter(s, s + 10, 5, TIter::TADereference)), IIter(TIter()));
+    test_exceptions(S(), IIter(TIter(s, s + 10, 6, TIter::TAComparison)), IIter(TIter()));
 
-    test_exceptions(S(), TIter(s, s+10, 4, TIter::TAIncrement), TIter());
-    test_exceptions(S(), TIter(s, s+10, 5, TIter::TADereference), TIter());
-    test_exceptions(S(), TIter(s, s+10, 6, TIter::TAComparison), TIter());
+    test_exceptions(S(), TIter(s, s + 10, 4, TIter::TAIncrement), TIter());
+    test_exceptions(S(), TIter(s, s + 10, 5, TIter::TADereference), TIter());
+    test_exceptions(S(), TIter(s, s + 10, 6, TIter::TAComparison), TIter());
 
     Widget w[100];
-    test_exceptions(S(), w, w+100);
+    test_exceptions(S(), w, w + 100);
   }
 #endif
 
@@ -163,9 +165,10 @@
   }
 
   { // regression-test assigning to self in sneaky ways
-    std::string sneaky = "hello";
+    typedef std::string S;
+    S sneaky = "hello";
     sneaky.resize(sneaky.capacity(), 'x');
-    std::string expected = sneaky + std::string(1, '\0');
+    S expected = sneaky + S(1, '\0');
     test(sneaky, sneaky.data(), sneaky.data() + sneaky.size() + 1, expected);
   }
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/pointer.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/pointer.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/pointer.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/pointer.pass.cpp
@@ -16,6 +16,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -46,6 +47,7 @@
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   { // test assignment to self
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/pointer_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/pointer_size.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/pointer_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/pointer_size.pass.cpp
@@ -17,6 +17,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -51,6 +52,7 @@
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   { // test assign to self
@@ -69,6 +71,7 @@
     s_long.assign(s_long.data() + 2, 8 );
     assert(s_long == "rem ipsu");
   }
+
   return true;
 }
 
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/rv_string.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/rv_string.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/rv_string.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/rv_string.pass.cpp
@@ -17,6 +17,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -55,6 +56,7 @@
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/size_char.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/size_char.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/size_char.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/size_char.pass.cpp
@@ -16,6 +16,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -46,6 +47,7 @@
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/string.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/string.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/string.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/string.pass.cpp
@@ -37,74 +37,54 @@
     assert(s.get_allocator() == a);
 }
 
-TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    test(S(), S(), S());
-    test(S(), S("12345"), S("12345"));
-    test(S(), S("1234567890"), S("1234567890"));
-    test(S(), S("12345678901234567890"), S("12345678901234567890"));
-
-    test(S("12345"), S(), S());
-    test(S("12345"), S("12345"), S("12345"));
-    test(S("12345"), S("1234567890"), S("1234567890"));
-    test(S("12345"), S("12345678901234567890"), S("12345678901234567890"));
-
-    test(S("1234567890"), S(), S());
-    test(S("1234567890"), S("12345"), S("12345"));
-    test(S("1234567890"), S("1234567890"), S("1234567890"));
-    test(S("1234567890"), S("12345678901234567890"), S("12345678901234567890"));
-
-    test(S("12345678901234567890"), S(), S());
-    test(S("12345678901234567890"), S("12345"), S("12345"));
-    test(S("12345678901234567890"), S("1234567890"), S("1234567890"));
-    test(S("12345678901234567890"), S("12345678901234567890"),
-         S("12345678901234567890"));
-
-    testAlloc(S(), S(), std::allocator<char>());
-    testAlloc(S(), S("12345"), std::allocator<char>());
-    testAlloc(S(), S("1234567890"), std::allocator<char>());
-    testAlloc(S(), S("12345678901234567890"), std::allocator<char>());
-  }
+template <class CharT, template <class> class Alloc>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  using A = Alloc<CharT>;
+  using S = std::basic_string<CharT, std::char_traits<CharT>, A>;
+
+  test(S(), S(), S());
+  test(S(), S("12345"), S("12345"));
+  test(S(), S("1234567890"), S("1234567890"));
+  test(S(), S("12345678901234567890"), S("12345678901234567890"));
+
+  test(S("12345"), S(), S());
+  test(S("12345"), S("12345"), S("12345"));
+  test(S("12345"), S("1234567890"), S("1234567890"));
+  test(S("12345"), S("12345678901234567890"), S("12345678901234567890"));
+
+  test(S("1234567890"), S(), S());
+  test(S("1234567890"), S("12345"), S("12345"));
+  test(S("1234567890"), S("1234567890"), S("1234567890"));
+  test(S("1234567890"), S("12345678901234567890"), S("12345678901234567890"));
+
+  test(S("12345678901234567890"), S(), S());
+  test(S("12345678901234567890"), S("12345"), S("12345"));
+  test(S("12345678901234567890"), S("1234567890"), S("1234567890"));
+  test(S("12345678901234567890"), S("12345678901234567890"), S("12345678901234567890"));
+
+  testAlloc(S(), S(), Alloc<CharT>());
+  testAlloc(S(), S("12345"), Alloc<CharT>());
+  testAlloc(S(), S("1234567890"), Alloc<CharT>());
+  testAlloc(S(), S("12345678901234567890"), Alloc<CharT>());
+}
 
-  { //  LWG#5579 make sure assign takes the allocators where appropriate
-    typedef other_allocator<char> A;  // has POCCA --> true
-    typedef std::basic_string<char, std::char_traits<char>, A> S;
-    testAlloc(S(A(5)), S(A(3)), A(3));
-    testAlloc(S(A(5)), S("1"), A());
-    testAlloc(S(A(5)), S("1", A(7)), A(7));
-    testAlloc(S(A(5)), S("1234567890123456789012345678901234567890123456789012345678901234567890", A(7)), A(7));
-  }
+template <>
+TEST_CONSTEXPR_CXX20 void test_string<char, other_allocator>() {
+  //  LWG#5579 make sure assign takes the allocators where appropriate
+  using A = other_allocator<char>;
+  using S = std::basic_string<char, std::char_traits<char>, A>;
+  testAlloc(S(A(5)), S(A(3)), A(3));
+  testAlloc(S(A(5)), S("1"), A());
+  testAlloc(S(A(5)), S("1", A(7)), A(7));
+  testAlloc(S(A(5)), S("1234567890123456789012345678901234567890123456789012345678901234567890", A(7)), A(7));
+}
 
+TEST_CONSTEXPR_CXX20 bool test() {
+  test_string<char, std::allocator>();
+  test_string<char, other_allocator>(); // has POCCA --> true
 #if TEST_STD_VER >= 11
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    test(S(), S(), S());
-    test(S(), S("12345"), S("12345"));
-    test(S(), S("1234567890"), S("1234567890"));
-    test(S(), S("12345678901234567890"), S("12345678901234567890"));
-
-    test(S("12345"), S(), S());
-    test(S("12345"), S("12345"), S("12345"));
-    test(S("12345"), S("1234567890"), S("1234567890"));
-    test(S("12345"), S("12345678901234567890"), S("12345678901234567890"));
-
-    test(S("1234567890"), S(), S());
-    test(S("1234567890"), S("12345"), S("12345"));
-    test(S("1234567890"), S("1234567890"), S("1234567890"));
-    test(S("1234567890"), S("12345678901234567890"), S("12345678901234567890"));
-
-    test(S("12345678901234567890"), S(), S());
-    test(S("12345678901234567890"), S("12345"), S("12345"));
-    test(S("12345678901234567890"), S("1234567890"), S("1234567890"));
-    test(S("12345678901234567890"), S("12345678901234567890"),
-         S("12345678901234567890"));
-
-    testAlloc(S(), S(), min_allocator<char>());
-    testAlloc(S(), S("12345"), min_allocator<char>());
-    testAlloc(S(), S("1234567890"), min_allocator<char>());
-    testAlloc(S(), S("12345678901234567890"), min_allocator<char>());
-  }
+  test_string<char, min_allocator>();
+  test_string<char, fancy_pointer_allocator>();
 #endif
 #if TEST_STD_VER > 14
   {
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/string_size_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/string_size_size.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/string_size_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/string_size_size.pass.cpp
@@ -18,6 +18,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -100,6 +101,7 @@
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   {
@@ -112,7 +114,6 @@
     test_npos(S(), S("12345"), 5, S(""));
     test_npos(S(), S("12345"), 6, S("not happening"));
   }
-
   return true;
 }
 
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/string_view.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/string_view.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/string_view.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/string_view.pass.cpp
@@ -74,6 +74,7 @@
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_copy/copy.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_copy/copy.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_copy/copy.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_copy/copy.pass.cpp
@@ -17,6 +17,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -116,8 +117,8 @@
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
-
   return true;
 }
 
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_erase/iter.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_erase/iter.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_erase/iter.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_erase/iter.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -48,6 +49,7 @@
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_erase/iter_iter.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_erase/iter_iter.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_erase/iter_iter.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_erase/iter_iter.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -91,8 +92,8 @@
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
-
   return true;
 }
 
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_erase/pop_back.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_erase/pop_back.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_erase/pop_back.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_erase/pop_back.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -37,6 +38,7 @@
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_erase/size_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_erase/size_size.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_erase/size_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_erase/size_size.pass.cpp
@@ -17,6 +17,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -196,6 +197,7 @@
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/iter_char.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/iter_char.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/iter_char.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/iter_char.pass.cpp
@@ -16,6 +16,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -55,6 +56,7 @@
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/iter_initializer_list.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/iter_initializer_list.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/iter_initializer_list.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/iter_initializer_list.pass.cpp
@@ -18,21 +18,20 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
+
+template <class S>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  S s("123456");
+  typename S::iterator i = s.insert(s.begin() + 3, {'a', 'b', 'c'});
+  assert(i - s.begin() == 3);
+  assert(s == "123abc456");
+}
 
 TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    std::string s("123456");
-    std::string::iterator i = s.insert(s.begin() + 3, {'a', 'b', 'c'});
-    assert(i - s.begin() == 3);
-    assert(s == "123abc456");
-  }
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    S s("123456");
-    S::iterator i = s.insert(s.begin() + 3, {'a', 'b', 'c'});
-    assert(i - s.begin() == 3);
-    assert(s == "123abc456");
-  }
+  test_string<std::string>();
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 
   return true;
 }
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/iter_iter_iter.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/iter_iter_iter.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/iter_iter_iter.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/iter_iter_iter.pass.cpp
@@ -17,6 +17,7 @@
 #include "test_macros.h"
 #include "test_iterators.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S, class It>
 TEST_CONSTEXPR_CXX20 void
@@ -106,6 +107,7 @@
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
 #ifndef TEST_HAS_NO_EXCEPTIONS
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/iter_size_char.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/iter_size_char.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/iter_size_char.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/iter_size_char.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -100,6 +101,7 @@
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/size_T_size_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/size_T_size_size.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/size_T_size_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/size_T_size_size.pass.cpp
@@ -19,6 +19,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S, class SV>
 TEST_CONSTEXPR_CXX20 void
@@ -1905,6 +1906,8 @@
 #if TEST_STD_VER >= 11
   test<std::basic_string<char, std::char_traits<char>, min_allocator<char>>,
        std::basic_string_view<char, std::char_traits<char>>>();
+  test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>,
+       std::basic_string_view<char, std::char_traits<char>>>();
 #endif
 
   return 0;
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/size_pointer.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/size_pointer.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/size_pointer.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/size_pointer.pass.cpp
@@ -17,6 +17,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -135,6 +136,7 @@
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   { // test inserting into self
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/size_pointer_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/size_pointer_size.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/size_pointer_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/size_pointer_size.pass.cpp
@@ -17,6 +17,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -372,7 +373,6 @@
     test(S("abcdefghijklmnopqrst"), 21, "12345678901234567890", 19, S("can't happen"));
     test(S("abcdefghijklmnopqrst"), 21, "12345678901234567890", 20, S("can't happen"));
   }
-
   { // test inserting into self
     S s_short = "123/";
     S s_long  = "Lorem ipsum dolor sit amet, consectetur/";
@@ -396,11 +396,13 @@
   test<std::string>();
 #if TEST_STD_VER >= 11
   test<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
 #if TEST_STD_VER > 17
   static_assert(test<std::string>());
   static_assert(test<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>());
+  static_assert(test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>());
 #endif
 
   return 0;
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/size_size_char.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/size_size_char.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/size_size_char.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/size_size_char.pass.cpp
@@ -17,6 +17,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -136,6 +137,7 @@
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/size_string.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/size_string.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/size_string.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/size_string.pass.cpp
@@ -17,6 +17,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -135,6 +136,7 @@
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
 #if TEST_STD_VER >= 11
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/size_string_size_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/size_string_size_size.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/size_string_size_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/size_string_size_size.pass.cpp
@@ -19,6 +19,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -1863,6 +1864,7 @@
   test<std::string>();
 #if TEST_STD_VER >= 11
   test<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return 0;
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/string_view.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/string_view.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/string_view.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/string_view.pass.cpp
@@ -17,6 +17,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S, class SV>
 TEST_CONSTEXPR_CXX20 void
@@ -136,6 +137,7 @@
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   { // test inserting into self
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_op_plus_equal/char.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_op_plus_equal/char.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_op_plus_equal/char.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_op_plus_equal/char.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -25,22 +26,19 @@
     assert(s == expected);
 }
 
+template <class S>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  test(S(), 'a', S("a"));
+  test(S("12345"), 'a', S("12345a"));
+  test(S("1234567890"), 'a', S("1234567890a"));
+  test(S("12345678901234567890"), 'a', S("12345678901234567890a"));
+}
+
 TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    test(S(), 'a', S("a"));
-    test(S("12345"), 'a', S("12345a"));
-    test(S("1234567890"), 'a', S("1234567890a"));
-    test(S("12345678901234567890"), 'a', S("12345678901234567890a"));
-  }
+  test_string<std::string>();
 #if TEST_STD_VER >= 11
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    test(S(), 'a', S("a"));
-    test(S("12345"), 'a', S("12345a"));
-    test(S("1234567890"), 'a', S("1234567890a"));
-    test(S("12345678901234567890"), 'a', S("12345678901234567890a"));
-  }
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_op_plus_equal/initializer_list.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_op_plus_equal/initializer_list.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_op_plus_equal/initializer_list.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_op_plus_equal/initializer_list.pass.cpp
@@ -17,20 +17,19 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
-TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    std::string s("123");
-    s += {'a', 'b', 'c'};
-    assert(s == "123abc");
-  }
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    S s("123");
-    s += {'a', 'b', 'c'};
-    assert(s == "123abc");
-  }
+template <class S>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  S s("123");
+  s += {'a', 'b', 'c'};
+  assert(s == "123abc");
+}
 
+TEST_CONSTEXPR_CXX20 bool test() {
+  test_string<std::string>();
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
   return true;
 }
 
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_op_plus_equal/pointer.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_op_plus_equal/pointer.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_op_plus_equal/pointer.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_op_plus_equal/pointer.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -53,6 +54,7 @@
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_op_plus_equal/string.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_op_plus_equal/string.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_op_plus_equal/string.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_op_plus_equal/string.pass.cpp
@@ -16,6 +16,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -54,9 +55,7 @@
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
-#endif
-
-#if TEST_STD_VER >= 11
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
   { // LWG 2946
     std::string s;
     s += {"abc", 1};
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_initializer_list.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_initializer_list.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_initializer_list.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_initializer_list.pass.cpp
@@ -17,19 +17,19 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
+
+template <class S>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  S s("123def456");
+  s.replace(s.cbegin() + 3, s.cbegin() + 6, {'a', 'b', 'c'});
+  assert(s == "123abc456");
+}
 
 TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    std::string s("123def456");
-    s.replace(s.cbegin() + 3, s.cbegin() + 6, {'a', 'b', 'c'});
-    assert(s == "123abc456");
-  }
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    S s("123def456");
-    s.replace(s.cbegin() + 3, s.cbegin() + 6, {'a', 'b', 'c'});
-    assert(s == "123abc456");
-  }
+  test_string<std::string>();
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 
   return true;
 }
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_iter_iter.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_iter_iter.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_iter_iter.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_iter_iter.pass.cpp
@@ -19,6 +19,7 @@
 #include "test_macros.h"
 #include "min_allocator.h"
 #include "test_iterators.h"
+#include "test_allocator.h"
 
 template <class S, class It>
 TEST_CONSTEXPR_CXX20 void
@@ -1075,7 +1076,8 @@
   test<std::string>();
 #if TEST_STD_VER >= 11
   test<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return 0;
-}
+}
\ No newline at end of file
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_pointer.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_pointer.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_pointer.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_pointer.pass.cpp
@@ -19,6 +19,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -287,36 +288,25 @@
     return true;
 }
 
+template <class S>
 TEST_CONSTEXPR_CXX20 void test() {
-  {
-    typedef std::string S;
-    test0<S>();
-    test1<S>();
-    test2<S>();
-#if TEST_STD_VER > 17
-    static_assert(test0<S>());
-    static_assert(test1<S>());
-    static_assert(test2<S>());
-#endif
-  }
-#if TEST_STD_VER >= 11
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    test0<S>();
-    test1<S>();
-    test2<S>();
+  test0<S>();
+  test1<S>();
+  test2<S>();
 #if TEST_STD_VER > 17
     static_assert(test0<S>());
     static_assert(test1<S>());
     static_assert(test2<S>());
-#endif
-  }
 #endif
 }
 
 int main(int, char**)
 {
-  test();
+  test<std::string>();
+#if TEST_STD_VER >= 11
+  test<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
+#endif
 
   return 0;
 }
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_pointer_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_pointer_size.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_pointer_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_pointer_size.pass.cpp
@@ -17,6 +17,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -1011,7 +1012,8 @@
   test<std::string>();
 #if TEST_STD_VER >= 11
   test<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return 0;
-}
+}
\ No newline at end of file
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_size_char.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_size_char.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_size_char.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_size_char.pass.cpp
@@ -17,6 +17,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -265,20 +266,18 @@
     test(S("abcdefghijklmnopqrst"), 20, 0, 20, '3', S("abcdefghijklmnopqrst33333333333333333333"));
 }
 
+template <class S>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  test0<S>();
+  test1<S>();
+  test2<S>();
+}
+
 TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    test0<S>();
-    test1<S>();
-    test2<S>();
-  }
+  test_string<std::string>();
 #if TEST_STD_VER >= 11
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    test0<S>();
-    test1<S>();
-    test2<S>();
-  }
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_string.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_string.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_string.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_string.pass.cpp
@@ -17,6 +17,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -298,6 +299,7 @@
   test<std::string>();
 #if TEST_STD_VER >= 11
   test<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return 0;
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_string_view.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_string_view.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_string_view.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_string_view.pass.cpp
@@ -17,6 +17,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S, class SV>
 TEST_CONSTEXPR_CXX20 void
@@ -270,38 +271,27 @@
     return true;
 }
 
+template <class CharT, template <class> class Alloc>
 TEST_CONSTEXPR_CXX20 void test() {
-  {
-    typedef std::string S;
-    typedef std::string_view SV;
-    test0<S, SV>();
-    test1<S, SV>();
-    test2<S, SV>();
+  using S  = std::basic_string<CharT, std::char_traits<CharT>, Alloc<CharT>>;
+  using SV = std::basic_string_view<CharT, std::char_traits<CharT>>;
+  test0<S, SV>();
+  test1<S, SV>();
+  test2<S, SV>();
 #if TEST_STD_VER > 17
     static_assert(test0<S, SV>());
     static_assert(test1<S, SV>());
     static_assert(test2<S, SV>());
-#endif
-  }
-#if TEST_STD_VER >= 11
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    typedef std::string_view SV;
-    test0<S, SV>();
-    test1<S, SV>();
-    test2<S, SV>();
-#if TEST_STD_VER > 17
-    static_assert(test0<S, SV>());
-    static_assert(test1<S, SV>());
-    static_assert(test2<S, SV>());
-#endif
-  }
 #endif
 }
 
 int main(int, char**)
 {
-  test();
+  test<char, std::allocator>();
+#if TEST_STD_VER >= 11
+  test<char, min_allocator>();
+  test<char, fancy_pointer_allocator>();
+#endif
 
   return 0;
 }
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/size_size_T_size_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/size_size_T_size_size.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/size_size_T_size_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/size_size_T_size_size.pass.cpp
@@ -21,6 +21,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S, class SV>
 TEST_CONSTEXPR_CXX20 void
@@ -6016,8 +6017,10 @@
     return true;
 }
 
-template <class S, class SV>
-TEST_CONSTEXPR_CXX20 bool test() {
+template <class CharT, template <class> class Alloc>
+void test() {
+  using S  = std::basic_string<CharT, std::char_traits<CharT>, Alloc<CharT>>;
+  using SV = std::basic_string_view<CharT, std::char_traits<CharT>>;
   test0<S, SV>();
   test1<S, SV>();
   test2<S, SV>();
@@ -6133,16 +6136,14 @@
   static_assert(test54<S, SV>());
   static_assert(test55<S, SV>());
 #endif
-
-  return true;
 }
 
 int main(int, char**)
 {
-  test<std::string, std::string_view>();
+  test<char, std::allocator>();
 #if TEST_STD_VER >= 11
-  test<std::basic_string<char, std::char_traits<char>, min_allocator<char>>,
-       std::basic_string_view<char, std::char_traits<char>>>();
+  test<char, min_allocator>();
+  test<char, fancy_pointer_allocator>();
 #endif
 
   return 0;
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/size_size_pointer.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/size_size_pointer.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/size_size_pointer.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/size_size_pointer.pass.cpp
@@ -18,6 +18,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -388,6 +389,7 @@
   test<std::string>();
 #if TEST_STD_VER >= 11
   test<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return 0;
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/size_size_pointer_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/size_size_pointer_size.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/size_size_pointer_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/size_size_pointer_size.pass.cpp
@@ -18,6 +18,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -1357,6 +1358,7 @@
   test<std::string>();
 #if TEST_STD_VER >= 11
   test<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return 0;
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/size_size_size_char.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/size_size_size_char.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/size_size_size_char.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/size_size_size_char.pass.cpp
@@ -18,6 +18,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -388,6 +389,7 @@
   test<std::string>();
 #if TEST_STD_VER >= 11
   test<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return 0;
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/size_size_string.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/size_size_string.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/size_size_string.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/size_size_string.pass.cpp
@@ -18,6 +18,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -396,6 +397,7 @@
   test<std::string>();
 #if TEST_STD_VER >= 11
   test<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
   return 0;
 }
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/size_size_string_size_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/size_size_string_size_size.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/size_size_string_size_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/size_size_string_size_size.pass.cpp
@@ -20,6 +20,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -5972,7 +5973,7 @@
 }
 
 template <class S>
-void test() {
+TEST_CONSTEXPR_CXX20 void test() {
   test0<S>();
   test1<S>();
   test2<S>();
@@ -6095,6 +6096,7 @@
   test<std::string>();
 #if TEST_STD_VER >= 11
   test<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return 0;
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/size_size_string_view.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/size_size_string_view.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/size_size_string_view.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/size_size_string_view.pass.cpp
@@ -18,6 +18,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S, class SV>
 TEST_CONSTEXPR_CXX20 void
@@ -368,26 +369,26 @@
     return true;
 }
 
-template <class S>
+template <class CharT, template <class> class Alloc>
 void test() {
-  {
-    typedef std::string_view SV;
-    test0<S, SV>();
-    test1<S, SV>();
-    test2<S, SV>();
+  using S  = std::basic_string<CharT, std::char_traits<CharT>, Alloc<CharT>>;
+  using SV = std::basic_string_view<CharT, std::char_traits<CharT>>;
+  test0<S, SV>();
+  test1<S, SV>();
+  test2<S, SV>();
 #if TEST_STD_VER > 17
     static_assert(test0<S, SV>());
     static_assert(test1<S, SV>());
     static_assert(test2<S, SV>());
 #endif
-  }
 }
 
 int main(int, char**)
 {
-  test<std::string>();
+  test<char, std::allocator>();
 #if TEST_STD_VER >= 11
-  test<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test<char, min_allocator>();
+  test<char, fancy_pointer_allocator>();
 #endif
 
   return 0;
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_swap/swap.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_swap/swap.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_swap/swap.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_swap/swap.pass.cpp
@@ -17,6 +17,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -55,6 +56,7 @@
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string.io/get_line.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string.io/get_line.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string.io/get_line.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string.io/get_line.pass.cpp
@@ -19,69 +19,48 @@
 
 #include "min_allocator.h"
 #include "test_macros.h"
+#include "test_allocator.h"
 
-int main(int, char**)
-{
-    {
-        std::istringstream in(" abc\n  def\n   ghij");
-        std::string s("initial text");
-        std::getline(in, s);
-        assert(in.good());
-        assert(s == " abc");
-        std::getline(in, s);
-        assert(in.good());
-        assert(s == "  def");
-        std::getline(in, s);
-        assert(in.eof());
-        assert(s == "   ghij");
-    }
+template <template <class> class Alloc>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  using S  = std::basic_string<char, std::char_traits<char>, Alloc<char>>;
+  using WS = std::basic_string<wchar_t, std::char_traits<wchar_t>, Alloc<wchar_t>>;
+  {
+    std::istringstream in(" abc\n  def\n   ghij");
+    S s("initial text");
+    std::getline(in, s);
+    assert(in.good());
+    assert(s == " abc");
+    std::getline(in, s);
+    assert(in.good());
+    assert(s == "  def");
+    std::getline(in, s);
+    assert(in.eof());
+    assert(s == "   ghij");
+  }
 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
-    {
-        std::wistringstream in(L" abc\n  def\n   ghij");
-        std::wstring s(L"initial text");
-        std::getline(in, s);
-        assert(in.good());
-        assert(s == L" abc");
-        std::getline(in, s);
-        assert(in.good());
-        assert(s == L"  def");
-        std::getline(in, s);
-        assert(in.eof());
-        assert(s == L"   ghij");
-    }
+  {
+    std::wistringstream in(L" abc\n  def\n   ghij");
+    WS s(L"initial text");
+    std::getline(in, s);
+    assert(in.good());
+    assert(s == L" abc");
+    std::getline(in, s);
+    assert(in.good());
+    assert(s == L"  def");
+    std::getline(in, s);
+    assert(in.eof());
+    assert(s == L"   ghij");
+  }
 #endif
+}
+
+int main(int, char**) {
+  test_string<std::allocator>();
 #if TEST_STD_VER >= 11
-    {
-        typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-        std::istringstream in(" abc\n  def\n   ghij");
-        S s("initial text");
-        std::getline(in, s);
-        assert(in.good());
-        assert(s == " abc");
-        std::getline(in, s);
-        assert(in.good());
-        assert(s == "  def");
-        std::getline(in, s);
-        assert(in.eof());
-        assert(s == "   ghij");
-    }
-#ifndef TEST_HAS_NO_WIDE_CHARACTERS
-    {
-        typedef std::basic_string<wchar_t, std::char_traits<wchar_t>, min_allocator<wchar_t>> S;
-        std::wistringstream in(L" abc\n  def\n   ghij");
-        S s(L"initial text");
-        std::getline(in, s);
-        assert(in.good());
-        assert(s == L" abc");
-        std::getline(in, s);
-        assert(in.good());
-        assert(s == L"  def");
-        std::getline(in, s);
-        assert(in.eof());
-        assert(s == L"   ghij");
-    }
-#endif // TEST_HAS_NO_WIDE_CHARACTERS
-#endif // TEST_STD_VER >= 11
+  test_string<min_allocator>();
+  test_string<fancy_pointer_allocator>();
+#endif
 #ifndef TEST_HAS_NO_EXCEPTIONS
     {
         std::basic_stringbuf<char> sb("hello");
@@ -165,6 +144,4 @@
     }
 #endif
 #endif // TEST_HAS_NO_EXCEPTIONS
-
-    return 0;
 }
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string.io/get_line_delim.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string.io/get_line_delim.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string.io/get_line_delim.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string.io/get_line_delim.pass.cpp
@@ -19,81 +19,54 @@
 
 #include "min_allocator.h"
 #include "test_macros.h"
+#include "test_allocator.h"
 
-int main(int, char**)
-{
-    {
-        std::istringstream in(" abc*  def**   ghij");
-        std::string s("initial text");
-        std::getline(in, s, '*');
-        assert(in.good());
-        assert(s == " abc");
-        std::getline(in, s, '*');
-        assert(in.good());
-        assert(s == "  def");
-        std::getline(in, s, '*');
-        assert(in.good());
-        assert(s == "");
-        std::getline(in, s, '*');
-        assert(in.eof());
-        assert(s == "   ghij");
-    }
+template <template <class> class Alloc>
+void test_string() {
+  using S  = std::basic_string<char, std::char_traits<char>, Alloc<char>>;
+  using WS = std::basic_string<wchar_t, std::char_traits<wchar_t>, Alloc<wchar_t>>;
+  {
+    std::istringstream in(" abc*  def**   ghij");
+    S s("initial text");
+    std::getline(in, s, '*');
+    assert(in.good());
+    assert(s == " abc");
+    std::getline(in, s, '*');
+    assert(in.good());
+    assert(s == "  def");
+    std::getline(in, s, '*');
+    assert(in.good());
+    assert(s == "");
+    std::getline(in, s, '*');
+    assert(in.eof());
+    assert(s == "   ghij");
+  }
 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
-    {
-        std::wistringstream in(L" abc*  def**   ghij");
-        std::wstring s(L"initial text");
-        std::getline(in, s, L'*');
-        assert(in.good());
-        assert(s == L" abc");
-        std::getline(in, s, L'*');
-        assert(in.good());
-        assert(s == L"  def");
-        std::getline(in, s, L'*');
-        assert(in.good());
-        assert(s == L"");
-        std::getline(in, s, L'*');
-        assert(in.eof());
-        assert(s == L"   ghij");
-    }
+  {
+    std::wistringstream in(L" abc*  def**   ghij");
+    WS s(L"initial text");
+    std::getline(in, s, L'*');
+    assert(in.good());
+    assert(s == L" abc");
+    std::getline(in, s, L'*');
+    assert(in.good());
+    assert(s == L"  def");
+    std::getline(in, s, L'*');
+    assert(in.good());
+    assert(s == L"");
+    std::getline(in, s, L'*');
+    assert(in.eof());
+    assert(s == L"   ghij");
+  }
 #endif
+}
+
+int main(int, char**) {
+  test_string<std::allocator>();
 #if TEST_STD_VER >= 11
-    {
-        typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-        std::istringstream in(" abc*  def**   ghij");
-        S s("initial text");
-        std::getline(in, s, '*');
-        assert(in.good());
-        assert(s == " abc");
-        std::getline(in, s, '*');
-        assert(in.good());
-        assert(s == "  def");
-        std::getline(in, s, '*');
-        assert(in.good());
-        assert(s == "");
-        std::getline(in, s, '*');
-        assert(in.eof());
-        assert(s == "   ghij");
-    }
-#ifndef TEST_HAS_NO_WIDE_CHARACTERS
-    {
-        typedef std::basic_string<wchar_t, std::char_traits<wchar_t>, min_allocator<wchar_t>> S;
-        std::wistringstream in(L" abc*  def**   ghij");
-        S s(L"initial text");
-        std::getline(in, s, L'*');
-        assert(in.good());
-        assert(s == L" abc");
-        std::getline(in, s, L'*');
-        assert(in.good());
-        assert(s == L"  def");
-        std::getline(in, s, L'*');
-        assert(in.good());
-        assert(s == L"");
-        std::getline(in, s, L'*');
-        assert(in.eof());
-        assert(s == L"   ghij");
-    }
-#endif // TEST_HAS_NO_WIDE_CHARACTERS
-#endif // TEST_STD_VER >= 11
+  test_string<min_allocator>();
+  test_string<fancy_pointer_allocator>();
+#endif
 #ifndef TEST_HAS_NO_EXCEPTIONS
     {
         std::basic_stringbuf<char> sb("hello");
@@ -176,6 +149,4 @@
     }
 #endif // TEST_HAS_NO_WIDE_CHARACTERS
 #endif // TEST_HAS_NO_EXCEPTIONS
-
-    return 0;
 }
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string.io/get_line_delim_rv.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string.io/get_line_delim_rv.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string.io/get_line_delim_rv.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string.io/get_line_delim_rv.pass.cpp
@@ -19,35 +19,30 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
-int main(int, char**)
-{
-    {
-        std::string s("initial text");
-        std::getline(std::istringstream(" abc*  def*   ghij"), s, '*');
-        assert(s == " abc");
-    }
-#ifndef TEST_HAS_NO_WIDE_CHARACTERS
-    {
-        std::wstring s(L"initial text");
-        std::getline(std::wistringstream(L" abc*  def*   ghij"), s, L'*');
-        assert(s == L" abc");
-    }
-#endif
-    {
-        typedef std::basic_string<char, std::char_traits<char>, min_allocator<char> > S;
-        S s("initial text");
-        std::getline(std::istringstream(" abc*  def*   ghij"), s, '*');
-        assert(s == " abc");
-    }
+template <template <class> class Alloc>
+void test() {
+  {
+    using S = std::basic_string<char, std::char_traits<char>, Alloc<char>>;
+    S s("initial text");
+    std::getline(std::istringstream(" abc*  def*   ghij"), s, '*');
+    assert(s == " abc");
+  }
 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
     {
-        typedef std::basic_string<wchar_t, std::char_traits<wchar_t>, min_allocator<wchar_t> > S;
-        S s(L"initial text");
-        std::getline(std::wistringstream(L" abc*  def*   ghij"), s, L'*');
-        assert(s == L" abc");
+      using WS = std::basic_string<wchar_t, std::char_traits<wchar_t>, Alloc<wchar_t>>;
+      WS s(L"initial text");
+      std::getline(std::wistringstream(L" abc*  def*   ghij"), s, L'*');
+      assert(s == L" abc");
     }
 #endif
+}
+
+int main(int, char**) {
+  test<std::allocator>();
+  test<min_allocator>();
+  test<fancy_pointer_allocator>();
 
   return 0;
 }
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string.io/get_line_rv.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string.io/get_line_rv.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string.io/get_line_rv.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string.io/get_line_rv.pass.cpp
@@ -19,35 +19,33 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
-int main(int, char**)
-{
-    {
-        std::string s("initial text");
-        std::getline(std::istringstream(" abc\n  def\n   ghij"), s);
-        assert(s == " abc");
-    }
+template <template <class> class Alloc>
+void test() {
+  {
+    using S = std::basic_string<char, std::char_traits<char>, Alloc<char> >;
+    S s("initial text");
+    std::getline(std::istringstream(" abc\n  def\n   ghij"), s);
+    assert(s == " abc");
+  }
 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
     {
-        std::wstring s(L"initial text");
-        std::getline(std::wistringstream(L" abc\n  def\n   ghij"), s);
-        assert(s == L" abc");
-    }
-#endif
-    {
-        typedef std::basic_string<char, std::char_traits<char>, min_allocator<char> > S;
-        S s("initial text");
-        std::getline(std::istringstream(" abc\n  def\n   ghij"), s);
-        assert(s == " abc");
-    }
-#ifndef TEST_HAS_NO_WIDE_CHARACTERS
-    {
-        typedef std::basic_string<wchar_t, std::char_traits<wchar_t>, min_allocator<wchar_t> > S;
-        S s(L"initial text");
-        std::getline(std::wistringstream(L" abc\n  def\n   ghij"), s);
-        assert(s == L" abc");
+      using WS = std::basic_string<wchar_t, std::char_traits<wchar_t>, Alloc<wchar_t>>;
+      WS s(L"initial text");
+      std::getline(std::wistringstream(L" abc\n  def\n   ghij"), s);
+      assert(s == L" abc");
     }
 #endif
+}
+
+int main(int, char**) {
+  test<std::allocator>();
+  test<min_allocator>();
+
+#if TEST_STD_VER >= 11
+  test<fancy_pointer_allocator>();
+#endif // TEST_STD_VER >= 11
 
   return 0;
 }
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string.io/stream_extract.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string.io/stream_extract.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string.io/stream_extract.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string.io/stream_extract.pass.cpp
@@ -19,35 +19,38 @@
 
 #include "min_allocator.h"
 #include "test_macros.h"
+#include "test_allocator.h"
 
-int main(int, char**)
-{
-    {
-        std::istringstream in("a bc defghij");
-        std::string s("initial text");
-        in >> s;
-        assert(in.good());
-        assert(s == "a");
-        assert(in.peek() == ' ');
-        in >> s;
-        assert(in.good());
-        assert(s == "bc");
-        assert(in.peek() == ' ');
-        in.width(3);
-        in >> s;
-        assert(in.good());
-        assert(s == "def");
-        assert(in.peek() == 'g');
-        in >> s;
-        assert(in.eof());
-        assert(s == "ghij");
-        in >> s;
-        assert(in.fail());
-    }
+template <template <class> class Alloc>
+void test_string() {
+  using S  = std::basic_string<char, std::char_traits<char>, Alloc<char>>;
+  using WS = std::basic_string<wchar_t, std::char_traits<wchar_t>, Alloc<wchar_t>>;
+  {
+    std::istringstream in("a bc defghij");
+    S s("initial text");
+    in >> s;
+    assert(in.good());
+    assert(s == "a");
+    assert(in.peek() == ' ');
+    in >> s;
+    assert(in.good());
+    assert(s == "bc");
+    assert(in.peek() == ' ');
+    in.width(3);
+    in >> s;
+    assert(in.good());
+    assert(s == "def");
+    assert(in.peek() == 'g');
+    in >> s;
+    assert(in.eof());
+    assert(s == "ghij");
+    in >> s;
+    assert(in.fail());
+  }
 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
     {
         std::wistringstream in(L"a bc defghij");
-        std::wstring s(L"initial text");
+        WS s(L"initial text");
         in >> s;
         assert(in.good());
         assert(s == L"a");
@@ -68,6 +71,14 @@
         assert(in.fail());
     }
 #endif
+}
+
+int main(int, char**) {
+  test_string<std::allocator>();
+#if TEST_STD_VER >= 11
+  test_string<min_allocator>();
+  test_string<fancy_pointer_allocator>();
+#endif
 #ifndef TEST_HAS_NO_EXCEPTIONS
     {
         std::stringbuf sb;
@@ -106,56 +117,6 @@
         assert(threw);
     }
 #endif // TEST_HAS_NO_EXCEPTIONS
-#if TEST_STD_VER >= 11
-    {
-        typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-        std::istringstream in("a bc defghij");
-        S s("initial text");
-        in >> s;
-        assert(in.good());
-        assert(s == "a");
-        assert(in.peek() == ' ');
-        in >> s;
-        assert(in.good());
-        assert(s == "bc");
-        assert(in.peek() == ' ');
-        in.width(3);
-        in >> s;
-        assert(in.good());
-        assert(s == "def");
-        assert(in.peek() == 'g');
-        in >> s;
-        assert(in.eof());
-        assert(s == "ghij");
-        in >> s;
-        assert(in.fail());
-    }
-#ifndef TEST_HAS_NO_WIDE_CHARACTERS
-    {
-        typedef std::basic_string<wchar_t, std::char_traits<wchar_t>, min_allocator<wchar_t>> S;
-        std::wistringstream in(L"a bc defghij");
-        S s(L"initial text");
-        in >> s;
-        assert(in.good());
-        assert(s == L"a");
-        assert(in.peek() == L' ');
-        in >> s;
-        assert(in.good());
-        assert(s == L"bc");
-        assert(in.peek() == L' ');
-        in.width(3);
-        in >> s;
-        assert(in.good());
-        assert(s == L"def");
-        assert(in.peek() == L'g');
-        in >> s;
-        assert(in.eof());
-        assert(s == L"ghij");
-        in >> s;
-        assert(in.fail());
-    }
-#endif // TEST_HAS_NO_WIDE_CHARACTERS
-#endif // TEST_STD_VER >= 11
 
-  return 0;
+    return 0;
 }
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string.io/stream_insert.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string.io/stream_insert.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string.io/stream_insert.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string.io/stream_insert.pass.cpp
@@ -19,78 +19,54 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
-int main(int, char**)
-{
-    {
-        std::ostringstream out;
-        std::string s("some text");
-        out << s;
-        assert(out.good());
-        assert(s == out.str());
-    }
-    {
-        std::ostringstream out;
-        std::string s("some text");
-        out.width(12);
-        out << s;
-        assert(out.good());
-        assert("   " + s == out.str());
-    }
+template <template <class> class Alloc>
+void test() {
+  using S  = std::basic_string<char, std::char_traits<char>, Alloc<char>>;
+  using OS = std::basic_ostringstream<char, std::char_traits<char>, Alloc<char>>;
+  {
+    OS out;
+    S s("some text");
+    out << s;
+    assert(out.good());
+    assert(s == out.str());
+  }
+  {
+    OS out;
+    S s("some text");
+    out.width(12);
+    out << s;
+    assert(out.good());
+    assert("   " + s == out.str());
+  }
 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
+  using WS  = std::basic_string<wchar_t, std::char_traits<wchar_t>, Alloc<wchar_t>>;
+  using WOS = std::basic_ostringstream<wchar_t, std::char_traits<wchar_t>, Alloc<wchar_t>>;
+  {
+    WOS out;
+    WS s(L"some text");
+    out << s;
+    assert(out.good());
+    assert(s == out.str());
+  }
     {
-        std::wostringstream out;
-        std::wstring s(L"some text");
-        out << s;
-        assert(out.good());
-        assert(s == out.str());
-    }
-    {
-        std::wostringstream out;
-        std::wstring s(L"some text");
-        out.width(12);
-        out << s;
-        assert(out.good());
-        assert(L"   " + s == out.str());
+      WOS out;
+      WS s(L"some text");
+      out.width(12);
+      out << s;
+      assert(out.good());
+      assert(L"   " + s == out.str());
     }
 #endif
+}
+
+int main(int, char**) {
+  test<std::allocator>();
+
 #if TEST_STD_VER >= 11
-    {
-        typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-        std::basic_ostringstream<S::value_type, S::traits_type, S::allocator_type> out;
-        S s("some text");
-        out << s;
-        assert(out.good());
-        assert(s == out.str());
-    }
-    {
-        typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-        std::basic_ostringstream<S::value_type, S::traits_type, S::allocator_type> out;
-        S s("some text");
-        out.width(12);
-        out << s;
-        assert(out.good());
-        assert("   " + s == out.str());
-    }
-#ifndef TEST_HAS_NO_WIDE_CHARACTERS
-    {
-        typedef std::basic_string<wchar_t, std::char_traits<wchar_t>, min_allocator<wchar_t>> S;
-        std::basic_ostringstream<S::value_type, S::traits_type, S::allocator_type> out;
-        S s(L"some text");
-        out << s;
-        assert(out.good());
-        assert(s == out.str());
-    }
-    {
-        typedef std::basic_string<wchar_t, std::char_traits<wchar_t>, min_allocator<wchar_t>> S;
-        std::basic_ostringstream<S::value_type, S::traits_type, S::allocator_type> out;
-        S s(L"some text");
-        out.width(12);
-        out << s;
-        assert(out.good());
-        assert(L"   " + s == out.str());
-    }
-#endif // TEST_HAS_NO_WIDE_CHARACTERS
+  test<min_allocator>();
+  test<fancy_pointer_allocator>();
 #endif // TEST_STD_VER >= 11
 
   return 0;
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string.special/swap.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string.special/swap.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string.special/swap.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string.special/swap.pass.cpp
@@ -19,6 +19,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -33,46 +34,31 @@
     assert(s2 == s1_);
 }
 
+template <class S>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  test(S(""), S(""));
+  test(S(""), S("12345"));
+  test(S(""), S("1234567890"));
+  test(S(""), S("12345678901234567890"));
+  test(S("abcde"), S(""));
+  test(S("abcde"), S("12345"));
+  test(S("abcde"), S("1234567890"));
+  test(S("abcde"), S("12345678901234567890"));
+  test(S("abcdefghij"), S(""));
+  test(S("abcdefghij"), S("12345"));
+  test(S("abcdefghij"), S("1234567890"));
+  test(S("abcdefghij"), S("12345678901234567890"));
+  test(S("abcdefghijklmnopqrst"), S(""));
+  test(S("abcdefghijklmnopqrst"), S("12345"));
+  test(S("abcdefghijklmnopqrst"), S("1234567890"));
+  test(S("abcdefghijklmnopqrst"), S("12345678901234567890"));
+}
+
 TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    test(S(""), S(""));
-    test(S(""), S("12345"));
-    test(S(""), S("1234567890"));
-    test(S(""), S("12345678901234567890"));
-    test(S("abcde"), S(""));
-    test(S("abcde"), S("12345"));
-    test(S("abcde"), S("1234567890"));
-    test(S("abcde"), S("12345678901234567890"));
-    test(S("abcdefghij"), S(""));
-    test(S("abcdefghij"), S("12345"));
-    test(S("abcdefghij"), S("1234567890"));
-    test(S("abcdefghij"), S("12345678901234567890"));
-    test(S("abcdefghijklmnopqrst"), S(""));
-    test(S("abcdefghijklmnopqrst"), S("12345"));
-    test(S("abcdefghijklmnopqrst"), S("1234567890"));
-    test(S("abcdefghijklmnopqrst"), S("12345678901234567890"));
-  }
+  test_string<std::string>();
 #if TEST_STD_VER >= 11
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    test(S(""), S(""));
-    test(S(""), S("12345"));
-    test(S(""), S("1234567890"));
-    test(S(""), S("12345678901234567890"));
-    test(S("abcde"), S(""));
-    test(S("abcde"), S("12345"));
-    test(S("abcde"), S("1234567890"));
-    test(S("abcde"), S("12345678901234567890"));
-    test(S("abcdefghij"), S(""));
-    test(S("abcdefghij"), S("12345"));
-    test(S("abcdefghij"), S("1234567890"));
-    test(S("abcdefghij"), S("12345678901234567890"));
-    test(S("abcdefghijklmnopqrst"), S(""));
-    test(S("abcdefghijklmnopqrst"), S("12345"));
-    test(S("abcdefghijklmnopqrst"), S("1234567890"));
-    test(S("abcdefghijklmnopqrst"), S("12345678901234567890"));
-  }
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string_op!=/pointer_string.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string_op!=/pointer_string.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string_op!=/pointer_string.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string_op!=/pointer_string.pass.cpp
@@ -16,6 +16,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -48,6 +49,7 @@
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string_op!=/string_pointer.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string_op!=/string_pointer.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string_op!=/string_pointer.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string_op!=/string_pointer.pass.cpp
@@ -16,6 +16,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -48,6 +49,7 @@
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string_op!=/string_string.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string_op!=/string_string.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string_op!=/string_string.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string_op!=/string_string.pass.cpp
@@ -17,6 +17,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -49,6 +50,7 @@
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string_op!=/string_string_view.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string_op!=/string_string_view.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string_op!=/string_string_view.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string_op!=/string_string_view.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S, class SV>
 TEST_CONSTEXPR_CXX20 void
@@ -48,6 +49,7 @@
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string_op!=/string_view_string.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string_op!=/string_view_string.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string_op!=/string_view_string.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string_op!=/string_view_string.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S, class SV>
 TEST_CONSTEXPR_CXX20 void
@@ -48,6 +49,7 @@
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string_op+/char_string.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string_op+/char_string.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string_op+/char_string.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string_op+/char_string.pass.cpp
@@ -22,6 +22,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test0(typename S::value_type lhs, const S& rhs, const S& x) {
@@ -35,36 +36,25 @@
 }
 #endif
 
-TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    test0('a', S(""), S("a"));
-    test0('a', S("12345"), S("a12345"));
-    test0('a', S("1234567890"), S("a1234567890"));
-    test0('a', S("12345678901234567890"), S("a12345678901234567890"));
-  }
+template <class S>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  test0('a', S(""), S("a"));
+  test0('a', S("12345"), S("a12345"));
+  test0('a', S("1234567890"), S("a1234567890"));
+  test0('a', S("12345678901234567890"), S("a12345678901234567890"));
 #if TEST_STD_VER >= 11
-  {
-    typedef std::string S;
-    test1('a', S(""), S("a"));
-    test1('a', S("12345"), S("a12345"));
-    test1('a', S("1234567890"), S("a1234567890"));
-    test1('a', S("12345678901234567890"), S("a12345678901234567890"));
-  }
-  {
-    typedef std::basic_string<char, std::char_traits<char>,
-                              min_allocator<char> >
-        S;
-    test0('a', S(""), S("a"));
-    test0('a', S("12345"), S("a12345"));
-    test0('a', S("1234567890"), S("a1234567890"));
-    test0('a', S("12345678901234567890"), S("a12345678901234567890"));
+  test1('a', S(""), S("a"));
+  test1('a', S("12345"), S("a12345"));
+  test1('a', S("1234567890"), S("a1234567890"));
+  test1('a', S("12345678901234567890"), S("a12345678901234567890"));
+#endif
+}
 
-    test1('a', S(""), S("a"));
-    test1('a', S("12345"), S("a12345"));
-    test1('a', S("1234567890"), S("a1234567890"));
-    test1('a', S("12345678901234567890"), S("a12345678901234567890"));
-  }
+TEST_CONSTEXPR_CXX20 bool test() {
+  test_string<std::string>();
+#if TEST_STD_VER >= 11
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string_op+/pointer_string.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string_op+/pointer_string.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string_op+/pointer_string.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string_op+/pointer_string.pass.cpp
@@ -22,6 +22,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test0(const typename S::value_type* lhs, const S& rhs, const S& x) {
@@ -35,97 +36,50 @@
 }
 #endif
 
-TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    test0("", S(""), S(""));
-    test0("", S("12345"), S("12345"));
-    test0("", S("1234567890"), S("1234567890"));
-    test0("", S("12345678901234567890"), S("12345678901234567890"));
-    test0("abcde", S(""), S("abcde"));
-    test0("abcde", S("12345"), S("abcde12345"));
-    test0("abcde", S("1234567890"), S("abcde1234567890"));
-    test0("abcde", S("12345678901234567890"), S("abcde12345678901234567890"));
-    test0("abcdefghij", S(""), S("abcdefghij"));
-    test0("abcdefghij", S("12345"), S("abcdefghij12345"));
-    test0("abcdefghij", S("1234567890"), S("abcdefghij1234567890"));
-    test0("abcdefghij", S("12345678901234567890"),
-          S("abcdefghij12345678901234567890"));
-    test0("abcdefghijklmnopqrst", S(""), S("abcdefghijklmnopqrst"));
-    test0("abcdefghijklmnopqrst", S("12345"), S("abcdefghijklmnopqrst12345"));
-    test0("abcdefghijklmnopqrst", S("1234567890"),
-          S("abcdefghijklmnopqrst1234567890"));
-    test0("abcdefghijklmnopqrst", S("12345678901234567890"),
-          S("abcdefghijklmnopqrst12345678901234567890"));
-  }
+template <class S>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  test0("", S(""), S(""));
+  test0("", S("12345"), S("12345"));
+  test0("", S("1234567890"), S("1234567890"));
+  test0("", S("12345678901234567890"), S("12345678901234567890"));
+  test0("abcde", S(""), S("abcde"));
+  test0("abcde", S("12345"), S("abcde12345"));
+  test0("abcde", S("1234567890"), S("abcde1234567890"));
+  test0("abcde", S("12345678901234567890"), S("abcde12345678901234567890"));
+  test0("abcdefghij", S(""), S("abcdefghij"));
+  test0("abcdefghij", S("12345"), S("abcdefghij12345"));
+  test0("abcdefghij", S("1234567890"), S("abcdefghij1234567890"));
+  test0("abcdefghij", S("12345678901234567890"), S("abcdefghij12345678901234567890"));
+  test0("abcdefghijklmnopqrst", S(""), S("abcdefghijklmnopqrst"));
+  test0("abcdefghijklmnopqrst", S("12345"), S("abcdefghijklmnopqrst12345"));
+  test0("abcdefghijklmnopqrst", S("1234567890"), S("abcdefghijklmnopqrst1234567890"));
+  test0("abcdefghijklmnopqrst", S("12345678901234567890"), S("abcdefghijklmnopqrst12345678901234567890"));
 
 #if TEST_STD_VER >= 11
-  {
-    typedef std::string S;
-    test1("", S(""), S(""));
-    test1("", S("12345"), S("12345"));
-    test1("", S("1234567890"), S("1234567890"));
-    test1("", S("12345678901234567890"), S("12345678901234567890"));
-    test1("abcde", S(""), S("abcde"));
-    test1("abcde", S("12345"), S("abcde12345"));
-    test1("abcde", S("1234567890"), S("abcde1234567890"));
-    test1("abcde", S("12345678901234567890"), S("abcde12345678901234567890"));
-    test1("abcdefghij", S(""), S("abcdefghij"));
-    test1("abcdefghij", S("12345"), S("abcdefghij12345"));
-    test1("abcdefghij", S("1234567890"), S("abcdefghij1234567890"));
-    test1("abcdefghij", S("12345678901234567890"),
-          S("abcdefghij12345678901234567890"));
-    test1("abcdefghijklmnopqrst", S(""), S("abcdefghijklmnopqrst"));
-    test1("abcdefghijklmnopqrst", S("12345"), S("abcdefghijklmnopqrst12345"));
-    test1("abcdefghijklmnopqrst", S("1234567890"),
-          S("abcdefghijklmnopqrst1234567890"));
-    test1("abcdefghijklmnopqrst", S("12345678901234567890"),
-          S("abcdefghijklmnopqrst12345678901234567890"));
-  }
-  {
-    typedef std::basic_string<char, std::char_traits<char>,
-                              min_allocator<char> >
-        S;
-    test0("", S(""), S(""));
-    test0("", S("12345"), S("12345"));
-    test0("", S("1234567890"), S("1234567890"));
-    test0("", S("12345678901234567890"), S("12345678901234567890"));
-    test0("abcde", S(""), S("abcde"));
-    test0("abcde", S("12345"), S("abcde12345"));
-    test0("abcde", S("1234567890"), S("abcde1234567890"));
-    test0("abcde", S("12345678901234567890"), S("abcde12345678901234567890"));
-    test0("abcdefghij", S(""), S("abcdefghij"));
-    test0("abcdefghij", S("12345"), S("abcdefghij12345"));
-    test0("abcdefghij", S("1234567890"), S("abcdefghij1234567890"));
-    test0("abcdefghij", S("12345678901234567890"),
-          S("abcdefghij12345678901234567890"));
-    test0("abcdefghijklmnopqrst", S(""), S("abcdefghijklmnopqrst"));
-    test0("abcdefghijklmnopqrst", S("12345"), S("abcdefghijklmnopqrst12345"));
-    test0("abcdefghijklmnopqrst", S("1234567890"),
-          S("abcdefghijklmnopqrst1234567890"));
-    test0("abcdefghijklmnopqrst", S("12345678901234567890"),
-          S("abcdefghijklmnopqrst12345678901234567890"));
+  test1("", S(""), S(""));
+  test1("", S("12345"), S("12345"));
+  test1("", S("1234567890"), S("1234567890"));
+  test1("", S("12345678901234567890"), S("12345678901234567890"));
+  test1("abcde", S(""), S("abcde"));
+  test1("abcde", S("12345"), S("abcde12345"));
+  test1("abcde", S("1234567890"), S("abcde1234567890"));
+  test1("abcde", S("12345678901234567890"), S("abcde12345678901234567890"));
+  test1("abcdefghij", S(""), S("abcdefghij"));
+  test1("abcdefghij", S("12345"), S("abcdefghij12345"));
+  test1("abcdefghij", S("1234567890"), S("abcdefghij1234567890"));
+  test1("abcdefghij", S("12345678901234567890"), S("abcdefghij12345678901234567890"));
+  test1("abcdefghijklmnopqrst", S(""), S("abcdefghijklmnopqrst"));
+  test1("abcdefghijklmnopqrst", S("12345"), S("abcdefghijklmnopqrst12345"));
+  test1("abcdefghijklmnopqrst", S("1234567890"), S("abcdefghijklmnopqrst1234567890"));
+  test1("abcdefghijklmnopqrst", S("12345678901234567890"), S("abcdefghijklmnopqrst12345678901234567890"));
+#endif
+}
 
-    test1("", S(""), S(""));
-    test1("", S("12345"), S("12345"));
-    test1("", S("1234567890"), S("1234567890"));
-    test1("", S("12345678901234567890"), S("12345678901234567890"));
-    test1("abcde", S(""), S("abcde"));
-    test1("abcde", S("12345"), S("abcde12345"));
-    test1("abcde", S("1234567890"), S("abcde1234567890"));
-    test1("abcde", S("12345678901234567890"), S("abcde12345678901234567890"));
-    test1("abcdefghij", S(""), S("abcdefghij"));
-    test1("abcdefghij", S("12345"), S("abcdefghij12345"));
-    test1("abcdefghij", S("1234567890"), S("abcdefghij1234567890"));
-    test1("abcdefghij", S("12345678901234567890"),
-          S("abcdefghij12345678901234567890"));
-    test1("abcdefghijklmnopqrst", S(""), S("abcdefghijklmnopqrst"));
-    test1("abcdefghijklmnopqrst", S("12345"), S("abcdefghijklmnopqrst12345"));
-    test1("abcdefghijklmnopqrst", S("1234567890"),
-          S("abcdefghijklmnopqrst1234567890"));
-    test1("abcdefghijklmnopqrst", S("12345678901234567890"),
-          S("abcdefghijklmnopqrst12345678901234567890"));
-  }
+TEST_CONSTEXPR_CXX20 bool test() {
+  test_string<std::string>();
+#if TEST_STD_VER >= 11
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string_op+/string_char.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string_op+/string_char.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string_op+/string_char.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string_op+/string_char.pass.cpp
@@ -22,6 +22,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test0(const S& lhs, typename S::value_type rhs, const S& x) {
@@ -35,36 +36,27 @@
 }
 #endif
 
-TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    test0(S(""), '1', S("1"));
-    test0(S("abcde"), '1', S("abcde1"));
-    test0(S("abcdefghij"), '1', S("abcdefghij1"));
-    test0(S("abcdefghijklmnopqrst"), '1', S("abcdefghijklmnopqrst1"));
-  }
+template <class S>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  test0(S(""), '1', S("1"));
+  test0(S(""), '1', S("1"));
+  test0(S("abcde"), '1', S("abcde1"));
+  test0(S("abcdefghij"), '1', S("abcdefghij1"));
+  test0(S("abcdefghijklmnopqrst"), '1', S("abcdefghijklmnopqrst1"));
+
 #if TEST_STD_VER >= 11
-  {
-    typedef std::string S;
-    test1(S(""), '1', S("1"));
-    test1(S("abcde"), '1', S("abcde1"));
-    test1(S("abcdefghij"), '1', S("abcdefghij1"));
-    test1(S("abcdefghijklmnopqrst"), '1', S("abcdefghijklmnopqrst1"));
-  }
-  {
-    typedef std::basic_string<char, std::char_traits<char>,
-                              min_allocator<char> >
-        S;
-    test0(S(""), '1', S("1"));
-    test0(S("abcde"), '1', S("abcde1"));
-    test0(S("abcdefghij"), '1', S("abcdefghij1"));
-    test0(S("abcdefghijklmnopqrst"), '1', S("abcdefghijklmnopqrst1"));
+  test1(S(""), '1', S("1"));
+  test1(S("abcde"), '1', S("abcde1"));
+  test1(S("abcdefghij"), '1', S("abcdefghij1"));
+  test1(S("abcdefghijklmnopqrst"), '1', S("abcdefghijklmnopqrst1"));
+#endif
+}
 
-    test1(S(""), '1', S("1"));
-    test1(S("abcde"), '1', S("abcde1"));
-    test1(S("abcdefghij"), '1', S("abcdefghij1"));
-    test1(S("abcdefghijklmnopqrst"), '1', S("abcdefghijklmnopqrst1"));
-  }
+TEST_CONSTEXPR_CXX20 bool test() {
+  test_string<std::string>();
+#if TEST_STD_VER >= 11
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string_op+/string_pointer.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string_op+/string_pointer.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string_op+/string_pointer.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string_op+/string_pointer.pass.cpp
@@ -22,6 +22,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test0(const S& lhs, const typename S::value_type* rhs, const S& x) {
@@ -35,96 +36,49 @@
 }
 #endif
 
-TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    test0(S(""), "", S(""));
-    test0(S(""), "12345", S("12345"));
-    test0(S(""), "1234567890", S("1234567890"));
-    test0(S(""), "12345678901234567890", S("12345678901234567890"));
-    test0(S("abcde"), "", S("abcde"));
-    test0(S("abcde"), "12345", S("abcde12345"));
-    test0(S("abcde"), "1234567890", S("abcde1234567890"));
-    test0(S("abcde"), "12345678901234567890", S("abcde12345678901234567890"));
-    test0(S("abcdefghij"), "", S("abcdefghij"));
-    test0(S("abcdefghij"), "12345", S("abcdefghij12345"));
-    test0(S("abcdefghij"), "1234567890", S("abcdefghij1234567890"));
-    test0(S("abcdefghij"), "12345678901234567890",
-          S("abcdefghij12345678901234567890"));
-    test0(S("abcdefghijklmnopqrst"), "", S("abcdefghijklmnopqrst"));
-    test0(S("abcdefghijklmnopqrst"), "12345", S("abcdefghijklmnopqrst12345"));
-    test0(S("abcdefghijklmnopqrst"), "1234567890",
-          S("abcdefghijklmnopqrst1234567890"));
-    test0(S("abcdefghijklmnopqrst"), "12345678901234567890",
-          S("abcdefghijklmnopqrst12345678901234567890"));
-  }
+template <class S>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  test0(S(""), "", S(""));
+  test0(S(""), "12345", S("12345"));
+  test0(S(""), "1234567890", S("1234567890"));
+  test0(S(""), "12345678901234567890", S("12345678901234567890"));
+  test0(S("abcde"), "", S("abcde"));
+  test0(S("abcde"), "12345", S("abcde12345"));
+  test0(S("abcde"), "1234567890", S("abcde1234567890"));
+  test0(S("abcde"), "12345678901234567890", S("abcde12345678901234567890"));
+  test0(S("abcdefghij"), "", S("abcdefghij"));
+  test0(S("abcdefghij"), "12345", S("abcdefghij12345"));
+  test0(S("abcdefghij"), "1234567890", S("abcdefghij1234567890"));
+  test0(S("abcdefghij"), "12345678901234567890", S("abcdefghij12345678901234567890"));
+  test0(S("abcdefghijklmnopqrst"), "", S("abcdefghijklmnopqrst"));
+  test0(S("abcdefghijklmnopqrst"), "12345", S("abcdefghijklmnopqrst12345"));
+  test0(S("abcdefghijklmnopqrst"), "1234567890", S("abcdefghijklmnopqrst1234567890"));
+  test0(S("abcdefghijklmnopqrst"), "12345678901234567890", S("abcdefghijklmnopqrst12345678901234567890"));
 #if TEST_STD_VER >= 11
-  {
-    typedef std::string S;
-    test1(S(""), "", S(""));
-    test1(S(""), "12345", S("12345"));
-    test1(S(""), "1234567890", S("1234567890"));
-    test1(S(""), "12345678901234567890", S("12345678901234567890"));
-    test1(S("abcde"), "", S("abcde"));
-    test1(S("abcde"), "12345", S("abcde12345"));
-    test1(S("abcde"), "1234567890", S("abcde1234567890"));
-    test1(S("abcde"), "12345678901234567890", S("abcde12345678901234567890"));
-    test1(S("abcdefghij"), "", S("abcdefghij"));
-    test1(S("abcdefghij"), "12345", S("abcdefghij12345"));
-    test1(S("abcdefghij"), "1234567890", S("abcdefghij1234567890"));
-    test1(S("abcdefghij"), "12345678901234567890",
-          S("abcdefghij12345678901234567890"));
-    test1(S("abcdefghijklmnopqrst"), "", S("abcdefghijklmnopqrst"));
-    test1(S("abcdefghijklmnopqrst"), "12345", S("abcdefghijklmnopqrst12345"));
-    test1(S("abcdefghijklmnopqrst"), "1234567890",
-          S("abcdefghijklmnopqrst1234567890"));
-    test1(S("abcdefghijklmnopqrst"), "12345678901234567890",
-          S("abcdefghijklmnopqrst12345678901234567890"));
-  }
-  {
-    typedef std::basic_string<char, std::char_traits<char>,
-                              min_allocator<char> >
-        S;
-    test0(S(""), "", S(""));
-    test0(S(""), "12345", S("12345"));
-    test0(S(""), "1234567890", S("1234567890"));
-    test0(S(""), "12345678901234567890", S("12345678901234567890"));
-    test0(S("abcde"), "", S("abcde"));
-    test0(S("abcde"), "12345", S("abcde12345"));
-    test0(S("abcde"), "1234567890", S("abcde1234567890"));
-    test0(S("abcde"), "12345678901234567890", S("abcde12345678901234567890"));
-    test0(S("abcdefghij"), "", S("abcdefghij"));
-    test0(S("abcdefghij"), "12345", S("abcdefghij12345"));
-    test0(S("abcdefghij"), "1234567890", S("abcdefghij1234567890"));
-    test0(S("abcdefghij"), "12345678901234567890",
-          S("abcdefghij12345678901234567890"));
-    test0(S("abcdefghijklmnopqrst"), "", S("abcdefghijklmnopqrst"));
-    test0(S("abcdefghijklmnopqrst"), "12345", S("abcdefghijklmnopqrst12345"));
-    test0(S("abcdefghijklmnopqrst"), "1234567890",
-          S("abcdefghijklmnopqrst1234567890"));
-    test0(S("abcdefghijklmnopqrst"), "12345678901234567890",
-          S("abcdefghijklmnopqrst12345678901234567890"));
+  test1(S(""), "", S(""));
+  test1(S(""), "12345", S("12345"));
+  test1(S(""), "1234567890", S("1234567890"));
+  test1(S(""), "12345678901234567890", S("12345678901234567890"));
+  test1(S("abcde"), "", S("abcde"));
+  test1(S("abcde"), "12345", S("abcde12345"));
+  test1(S("abcde"), "1234567890", S("abcde1234567890"));
+  test1(S("abcde"), "12345678901234567890", S("abcde12345678901234567890"));
+  test1(S("abcdefghij"), "", S("abcdefghij"));
+  test1(S("abcdefghij"), "12345", S("abcdefghij12345"));
+  test1(S("abcdefghij"), "1234567890", S("abcdefghij1234567890"));
+  test1(S("abcdefghij"), "12345678901234567890", S("abcdefghij12345678901234567890"));
+  test1(S("abcdefghijklmnopqrst"), "", S("abcdefghijklmnopqrst"));
+  test1(S("abcdefghijklmnopqrst"), "12345", S("abcdefghijklmnopqrst12345"));
+  test1(S("abcdefghijklmnopqrst"), "1234567890", S("abcdefghijklmnopqrst1234567890"));
+  test1(S("abcdefghijklmnopqrst"), "12345678901234567890", S("abcdefghijklmnopqrst12345678901234567890"));
+#endif
+}
 
-    test1(S(""), "", S(""));
-    test1(S(""), "12345", S("12345"));
-    test1(S(""), "1234567890", S("1234567890"));
-    test1(S(""), "12345678901234567890", S("12345678901234567890"));
-    test1(S("abcde"), "", S("abcde"));
-    test1(S("abcde"), "12345", S("abcde12345"));
-    test1(S("abcde"), "1234567890", S("abcde1234567890"));
-    test1(S("abcde"), "12345678901234567890", S("abcde12345678901234567890"));
-    test1(S("abcdefghij"), "", S("abcdefghij"));
-    test1(S("abcdefghij"), "12345", S("abcdefghij12345"));
-    test1(S("abcdefghij"), "1234567890", S("abcdefghij1234567890"));
-    test1(S("abcdefghij"), "12345678901234567890",
-          S("abcdefghij12345678901234567890"));
-    test1(S("abcdefghijklmnopqrst"), "", S("abcdefghijklmnopqrst"));
-    test1(S("abcdefghijklmnopqrst"), "12345", S("abcdefghijklmnopqrst12345"));
-    test1(S("abcdefghijklmnopqrst"), "1234567890",
-          S("abcdefghijklmnopqrst1234567890"));
-    test1(S("abcdefghijklmnopqrst"), "12345678901234567890",
-          S("abcdefghijklmnopqrst12345678901234567890"));
-  }
+TEST_CONSTEXPR_CXX20 bool test() {
+  test_string<std::string>();
+#if TEST_STD_VER >= 11
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string_op+/string_string.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string_op+/string_string.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string_op+/string_string.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string_op+/string_string.pass.cpp
@@ -34,6 +34,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test0(const S& lhs, const S& rhs, const S& x) {
@@ -57,193 +58,84 @@
 }
 #endif
 
-TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    test0(S(""), S(""), S(""));
-    test0(S(""), S("12345"), S("12345"));
-    test0(S(""), S("1234567890"), S("1234567890"));
-    test0(S(""), S("12345678901234567890"), S("12345678901234567890"));
-    test0(S("abcde"), S(""), S("abcde"));
-    test0(S("abcde"), S("12345"), S("abcde12345"));
-    test0(S("abcde"), S("1234567890"), S("abcde1234567890"));
-    test0(S("abcde"), S("12345678901234567890"),
-          S("abcde12345678901234567890"));
-    test0(S("abcdefghij"), S(""), S("abcdefghij"));
-    test0(S("abcdefghij"), S("12345"), S("abcdefghij12345"));
-    test0(S("abcdefghij"), S("1234567890"), S("abcdefghij1234567890"));
-    test0(S("abcdefghij"), S("12345678901234567890"),
-          S("abcdefghij12345678901234567890"));
-    test0(S("abcdefghijklmnopqrst"), S(""), S("abcdefghijklmnopqrst"));
-    test0(S("abcdefghijklmnopqrst"), S("12345"),
-          S("abcdefghijklmnopqrst12345"));
-    test0(S("abcdefghijklmnopqrst"), S("1234567890"),
-          S("abcdefghijklmnopqrst1234567890"));
-    test0(S("abcdefghijklmnopqrst"), S("12345678901234567890"),
-          S("abcdefghijklmnopqrst12345678901234567890"));
-  }
+template <class S>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  test0(S(""), S(""), S(""));
+  test0(S(""), S("12345"), S("12345"));
+  test0(S(""), S("1234567890"), S("1234567890"));
+  test0(S(""), S("12345678901234567890"), S("12345678901234567890"));
+  test0(S("abcde"), S(""), S("abcde"));
+  test0(S("abcde"), S("12345"), S("abcde12345"));
+  test0(S("abcde"), S("1234567890"), S("abcde1234567890"));
+  test0(S("abcde"), S("12345678901234567890"), S("abcde12345678901234567890"));
+  test0(S("abcdefghij"), S(""), S("abcdefghij"));
+  test0(S("abcdefghij"), S("12345"), S("abcdefghij12345"));
+  test0(S("abcdefghij"), S("1234567890"), S("abcdefghij1234567890"));
+  test0(S("abcdefghij"), S("12345678901234567890"), S("abcdefghij12345678901234567890"));
+  test0(S("abcdefghijklmnopqrst"), S(""), S("abcdefghijklmnopqrst"));
+  test0(S("abcdefghijklmnopqrst"), S("12345"), S("abcdefghijklmnopqrst12345"));
+  test0(S("abcdefghijklmnopqrst"), S("1234567890"), S("abcdefghijklmnopqrst1234567890"));
+  test0(S("abcdefghijklmnopqrst"), S("12345678901234567890"), S("abcdefghijklmnopqrst12345678901234567890"));
 #if TEST_STD_VER >= 11
-  {
-    typedef std::string S;
-    test1(S(""), S(""), S(""));
-    test1(S(""), S("12345"), S("12345"));
-    test1(S(""), S("1234567890"), S("1234567890"));
-    test1(S(""), S("12345678901234567890"), S("12345678901234567890"));
-    test1(S("abcde"), S(""), S("abcde"));
-    test1(S("abcde"), S("12345"), S("abcde12345"));
-    test1(S("abcde"), S("1234567890"), S("abcde1234567890"));
-    test1(S("abcde"), S("12345678901234567890"),
-          S("abcde12345678901234567890"));
-    test1(S("abcdefghij"), S(""), S("abcdefghij"));
-    test1(S("abcdefghij"), S("12345"), S("abcdefghij12345"));
-    test1(S("abcdefghij"), S("1234567890"), S("abcdefghij1234567890"));
-    test1(S("abcdefghij"), S("12345678901234567890"),
-          S("abcdefghij12345678901234567890"));
-    test1(S("abcdefghijklmnopqrst"), S(""), S("abcdefghijklmnopqrst"));
-    test1(S("abcdefghijklmnopqrst"), S("12345"),
-          S("abcdefghijklmnopqrst12345"));
-    test1(S("abcdefghijklmnopqrst"), S("1234567890"),
-          S("abcdefghijklmnopqrst1234567890"));
-    test1(S("abcdefghijklmnopqrst"), S("12345678901234567890"),
-          S("abcdefghijklmnopqrst12345678901234567890"));
-
-    test2(S(""), S(""), S(""));
-    test2(S(""), S("12345"), S("12345"));
-    test2(S(""), S("1234567890"), S("1234567890"));
-    test2(S(""), S("12345678901234567890"), S("12345678901234567890"));
-    test2(S("abcde"), S(""), S("abcde"));
-    test2(S("abcde"), S("12345"), S("abcde12345"));
-    test2(S("abcde"), S("1234567890"), S("abcde1234567890"));
-    test2(S("abcde"), S("12345678901234567890"),
-          S("abcde12345678901234567890"));
-    test2(S("abcdefghij"), S(""), S("abcdefghij"));
-    test2(S("abcdefghij"), S("12345"), S("abcdefghij12345"));
-    test2(S("abcdefghij"), S("1234567890"), S("abcdefghij1234567890"));
-    test2(S("abcdefghij"), S("12345678901234567890"),
-          S("abcdefghij12345678901234567890"));
-    test2(S("abcdefghijklmnopqrst"), S(""), S("abcdefghijklmnopqrst"));
-    test2(S("abcdefghijklmnopqrst"), S("12345"),
-          S("abcdefghijklmnopqrst12345"));
-    test2(S("abcdefghijklmnopqrst"), S("1234567890"),
-          S("abcdefghijklmnopqrst1234567890"));
-    test2(S("abcdefghijklmnopqrst"), S("12345678901234567890"),
-          S("abcdefghijklmnopqrst12345678901234567890"));
-
-    test3(S(""), S(""), S(""));
-    test3(S(""), S("12345"), S("12345"));
-    test3(S(""), S("1234567890"), S("1234567890"));
-    test3(S(""), S("12345678901234567890"), S("12345678901234567890"));
-    test3(S("abcde"), S(""), S("abcde"));
-    test3(S("abcde"), S("12345"), S("abcde12345"));
-    test3(S("abcde"), S("1234567890"), S("abcde1234567890"));
-    test3(S("abcde"), S("12345678901234567890"),
-          S("abcde12345678901234567890"));
-    test3(S("abcdefghij"), S(""), S("abcdefghij"));
-    test3(S("abcdefghij"), S("12345"), S("abcdefghij12345"));
-    test3(S("abcdefghij"), S("1234567890"), S("abcdefghij1234567890"));
-    test3(S("abcdefghij"), S("12345678901234567890"),
-          S("abcdefghij12345678901234567890"));
-    test3(S("abcdefghijklmnopqrst"), S(""), S("abcdefghijklmnopqrst"));
-    test3(S("abcdefghijklmnopqrst"), S("12345"),
-          S("abcdefghijklmnopqrst12345"));
-    test3(S("abcdefghijklmnopqrst"), S("1234567890"),
-          S("abcdefghijklmnopqrst1234567890"));
-    test3(S("abcdefghijklmnopqrst"), S("12345678901234567890"),
-          S("abcdefghijklmnopqrst12345678901234567890"));
-  }
-  {
-    typedef std::basic_string<char, std::char_traits<char>,
-                              min_allocator<char> >
-        S;
-    test0(S(""), S(""), S(""));
-    test0(S(""), S("12345"), S("12345"));
-    test0(S(""), S("1234567890"), S("1234567890"));
-    test0(S(""), S("12345678901234567890"), S("12345678901234567890"));
-    test0(S("abcde"), S(""), S("abcde"));
-    test0(S("abcde"), S("12345"), S("abcde12345"));
-    test0(S("abcde"), S("1234567890"), S("abcde1234567890"));
-    test0(S("abcde"), S("12345678901234567890"),
-          S("abcde12345678901234567890"));
-    test0(S("abcdefghij"), S(""), S("abcdefghij"));
-    test0(S("abcdefghij"), S("12345"), S("abcdefghij12345"));
-    test0(S("abcdefghij"), S("1234567890"), S("abcdefghij1234567890"));
-    test0(S("abcdefghij"), S("12345678901234567890"),
-          S("abcdefghij12345678901234567890"));
-    test0(S("abcdefghijklmnopqrst"), S(""), S("abcdefghijklmnopqrst"));
-    test0(S("abcdefghijklmnopqrst"), S("12345"),
-          S("abcdefghijklmnopqrst12345"));
-    test0(S("abcdefghijklmnopqrst"), S("1234567890"),
-          S("abcdefghijklmnopqrst1234567890"));
-    test0(S("abcdefghijklmnopqrst"), S("12345678901234567890"),
-          S("abcdefghijklmnopqrst12345678901234567890"));
-
-    test1(S(""), S(""), S(""));
-    test1(S(""), S("12345"), S("12345"));
-    test1(S(""), S("1234567890"), S("1234567890"));
-    test1(S(""), S("12345678901234567890"), S("12345678901234567890"));
-    test1(S("abcde"), S(""), S("abcde"));
-    test1(S("abcde"), S("12345"), S("abcde12345"));
-    test1(S("abcde"), S("1234567890"), S("abcde1234567890"));
-    test1(S("abcde"), S("12345678901234567890"),
-          S("abcde12345678901234567890"));
-    test1(S("abcdefghij"), S(""), S("abcdefghij"));
-    test1(S("abcdefghij"), S("12345"), S("abcdefghij12345"));
-    test1(S("abcdefghij"), S("1234567890"), S("abcdefghij1234567890"));
-    test1(S("abcdefghij"), S("12345678901234567890"),
-          S("abcdefghij12345678901234567890"));
-    test1(S("abcdefghijklmnopqrst"), S(""), S("abcdefghijklmnopqrst"));
-    test1(S("abcdefghijklmnopqrst"), S("12345"),
-          S("abcdefghijklmnopqrst12345"));
-    test1(S("abcdefghijklmnopqrst"), S("1234567890"),
-          S("abcdefghijklmnopqrst1234567890"));
-    test1(S("abcdefghijklmnopqrst"), S("12345678901234567890"),
-          S("abcdefghijklmnopqrst12345678901234567890"));
-
-    test2(S(""), S(""), S(""));
-    test2(S(""), S("12345"), S("12345"));
-    test2(S(""), S("1234567890"), S("1234567890"));
-    test2(S(""), S("12345678901234567890"), S("12345678901234567890"));
-    test2(S("abcde"), S(""), S("abcde"));
-    test2(S("abcde"), S("12345"), S("abcde12345"));
-    test2(S("abcde"), S("1234567890"), S("abcde1234567890"));
-    test2(S("abcde"), S("12345678901234567890"),
-          S("abcde12345678901234567890"));
-    test2(S("abcdefghij"), S(""), S("abcdefghij"));
-    test2(S("abcdefghij"), S("12345"), S("abcdefghij12345"));
-    test2(S("abcdefghij"), S("1234567890"), S("abcdefghij1234567890"));
-    test2(S("abcdefghij"), S("12345678901234567890"),
-          S("abcdefghij12345678901234567890"));
-    test2(S("abcdefghijklmnopqrst"), S(""), S("abcdefghijklmnopqrst"));
-    test2(S("abcdefghijklmnopqrst"), S("12345"),
-          S("abcdefghijklmnopqrst12345"));
-    test2(S("abcdefghijklmnopqrst"), S("1234567890"),
-          S("abcdefghijklmnopqrst1234567890"));
-    test2(S("abcdefghijklmnopqrst"), S("12345678901234567890"),
-          S("abcdefghijklmnopqrst12345678901234567890"));
+  test1(S(""), S(""), S(""));
+  test1(S(""), S("12345"), S("12345"));
+  test1(S(""), S("1234567890"), S("1234567890"));
+  test1(S(""), S("12345678901234567890"), S("12345678901234567890"));
+  test1(S("abcde"), S(""), S("abcde"));
+  test1(S("abcde"), S("12345"), S("abcde12345"));
+  test1(S("abcde"), S("1234567890"), S("abcde1234567890"));
+  test1(S("abcde"), S("12345678901234567890"), S("abcde12345678901234567890"));
+  test1(S("abcdefghij"), S(""), S("abcdefghij"));
+  test1(S("abcdefghij"), S("12345"), S("abcdefghij12345"));
+  test1(S("abcdefghij"), S("1234567890"), S("abcdefghij1234567890"));
+  test1(S("abcdefghij"), S("12345678901234567890"), S("abcdefghij12345678901234567890"));
+  test1(S("abcdefghijklmnopqrst"), S(""), S("abcdefghijklmnopqrst"));
+  test1(S("abcdefghijklmnopqrst"), S("12345"), S("abcdefghijklmnopqrst12345"));
+  test1(S("abcdefghijklmnopqrst"), S("1234567890"), S("abcdefghijklmnopqrst1234567890"));
+  test1(S("abcdefghijklmnopqrst"), S("12345678901234567890"), S("abcdefghijklmnopqrst12345678901234567890"));
+
+  test2(S(""), S(""), S(""));
+  test2(S(""), S("12345"), S("12345"));
+  test2(S(""), S("1234567890"), S("1234567890"));
+  test2(S(""), S("12345678901234567890"), S("12345678901234567890"));
+  test2(S("abcde"), S(""), S("abcde"));
+  test2(S("abcde"), S("12345"), S("abcde12345"));
+  test2(S("abcde"), S("1234567890"), S("abcde1234567890"));
+  test2(S("abcde"), S("12345678901234567890"), S("abcde12345678901234567890"));
+  test2(S("abcdefghij"), S(""), S("abcdefghij"));
+  test2(S("abcdefghij"), S("12345"), S("abcdefghij12345"));
+  test2(S("abcdefghij"), S("1234567890"), S("abcdefghij1234567890"));
+  test2(S("abcdefghij"), S("12345678901234567890"), S("abcdefghij12345678901234567890"));
+  test2(S("abcdefghijklmnopqrst"), S(""), S("abcdefghijklmnopqrst"));
+  test2(S("abcdefghijklmnopqrst"), S("12345"), S("abcdefghijklmnopqrst12345"));
+  test2(S("abcdefghijklmnopqrst"), S("1234567890"), S("abcdefghijklmnopqrst1234567890"));
+  test2(S("abcdefghijklmnopqrst"), S("12345678901234567890"), S("abcdefghijklmnopqrst12345678901234567890"));
+
+  test3(S(""), S(""), S(""));
+  test3(S(""), S("12345"), S("12345"));
+  test3(S(""), S("1234567890"), S("1234567890"));
+  test3(S(""), S("12345678901234567890"), S("12345678901234567890"));
+  test3(S("abcde"), S(""), S("abcde"));
+  test3(S("abcde"), S("12345"), S("abcde12345"));
+  test3(S("abcde"), S("1234567890"), S("abcde1234567890"));
+  test3(S("abcde"), S("12345678901234567890"), S("abcde12345678901234567890"));
+  test3(S("abcdefghij"), S(""), S("abcdefghij"));
+  test3(S("abcdefghij"), S("12345"), S("abcdefghij12345"));
+  test3(S("abcdefghij"), S("1234567890"), S("abcdefghij1234567890"));
+  test3(S("abcdefghij"), S("12345678901234567890"), S("abcdefghij12345678901234567890"));
+  test3(S("abcdefghijklmnopqrst"), S(""), S("abcdefghijklmnopqrst"));
+  test3(S("abcdefghijklmnopqrst"), S("12345"), S("abcdefghijklmnopqrst12345"));
+  test3(S("abcdefghijklmnopqrst"), S("1234567890"), S("abcdefghijklmnopqrst1234567890"));
+  test3(S("abcdefghijklmnopqrst"), S("12345678901234567890"), S("abcdefghijklmnopqrst12345678901234567890"));
+#endif
+}
 
-    test3(S(""), S(""), S(""));
-    test3(S(""), S("12345"), S("12345"));
-    test3(S(""), S("1234567890"), S("1234567890"));
-    test3(S(""), S("12345678901234567890"), S("12345678901234567890"));
-    test3(S("abcde"), S(""), S("abcde"));
-    test3(S("abcde"), S("12345"), S("abcde12345"));
-    test3(S("abcde"), S("1234567890"), S("abcde1234567890"));
-    test3(S("abcde"), S("12345678901234567890"),
-          S("abcde12345678901234567890"));
-    test3(S("abcdefghij"), S(""), S("abcdefghij"));
-    test3(S("abcdefghij"), S("12345"), S("abcdefghij12345"));
-    test3(S("abcdefghij"), S("1234567890"), S("abcdefghij1234567890"));
-    test3(S("abcdefghij"), S("12345678901234567890"),
-          S("abcdefghij12345678901234567890"));
-    test3(S("abcdefghijklmnopqrst"), S(""), S("abcdefghijklmnopqrst"));
-    test3(S("abcdefghijklmnopqrst"), S("12345"),
-          S("abcdefghijklmnopqrst12345"));
-    test3(S("abcdefghijklmnopqrst"), S("1234567890"),
-          S("abcdefghijklmnopqrst1234567890"));
-    test3(S("abcdefghijklmnopqrst"), S("12345678901234567890"),
-          S("abcdefghijklmnopqrst12345678901234567890"));
-  }
-#endif // TEST_STD_VER >= 11
+TEST_CONSTEXPR_CXX20 bool test() {
+  test_string<std::string>();
+#if TEST_STD_VER >= 11
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
+#endif
 
   return true;
 }
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string_operator==/pointer_string.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string_operator==/pointer_string.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string_operator==/pointer_string.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string_operator==/pointer_string.pass.cpp
@@ -16,6 +16,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -24,46 +25,31 @@
     assert((lhs == rhs) == x);
 }
 
+template <class S>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  test("", S(""), true);
+  test("", S("abcde"), false);
+  test("", S("abcdefghij"), false);
+  test("", S("abcdefghijklmnopqrst"), false);
+  test("abcde", S(""), false);
+  test("abcde", S("abcde"), true);
+  test("abcde", S("abcdefghij"), false);
+  test("abcde", S("abcdefghijklmnopqrst"), false);
+  test("abcdefghij", S(""), false);
+  test("abcdefghij", S("abcde"), false);
+  test("abcdefghij", S("abcdefghij"), true);
+  test("abcdefghij", S("abcdefghijklmnopqrst"), false);
+  test("abcdefghijklmnopqrst", S(""), false);
+  test("abcdefghijklmnopqrst", S("abcde"), false);
+  test("abcdefghijklmnopqrst", S("abcdefghij"), false);
+  test("abcdefghijklmnopqrst", S("abcdefghijklmnopqrst"), true);
+}
+
 TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    test("", S(""), true);
-    test("", S("abcde"), false);
-    test("", S("abcdefghij"), false);
-    test("", S("abcdefghijklmnopqrst"), false);
-    test("abcde", S(""), false);
-    test("abcde", S("abcde"), true);
-    test("abcde", S("abcdefghij"), false);
-    test("abcde", S("abcdefghijklmnopqrst"), false);
-    test("abcdefghij", S(""), false);
-    test("abcdefghij", S("abcde"), false);
-    test("abcdefghij", S("abcdefghij"), true);
-    test("abcdefghij", S("abcdefghijklmnopqrst"), false);
-    test("abcdefghijklmnopqrst", S(""), false);
-    test("abcdefghijklmnopqrst", S("abcde"), false);
-    test("abcdefghijklmnopqrst", S("abcdefghij"), false);
-    test("abcdefghijklmnopqrst", S("abcdefghijklmnopqrst"), true);
-  }
+  test_string<std::string>();
 #if TEST_STD_VER >= 11
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    test("", S(""), true);
-    test("", S("abcde"), false);
-    test("", S("abcdefghij"), false);
-    test("", S("abcdefghijklmnopqrst"), false);
-    test("abcde", S(""), false);
-    test("abcde", S("abcde"), true);
-    test("abcde", S("abcdefghij"), false);
-    test("abcde", S("abcdefghijklmnopqrst"), false);
-    test("abcdefghij", S(""), false);
-    test("abcdefghij", S("abcde"), false);
-    test("abcdefghij", S("abcdefghij"), true);
-    test("abcdefghij", S("abcdefghijklmnopqrst"), false);
-    test("abcdefghijklmnopqrst", S(""), false);
-    test("abcdefghijklmnopqrst", S("abcde"), false);
-    test("abcdefghijklmnopqrst", S("abcdefghij"), false);
-    test("abcdefghijklmnopqrst", S("abcdefghijklmnopqrst"), true);
-  }
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string_operator==/string_pointer.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string_operator==/string_pointer.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string_operator==/string_pointer.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string_operator==/string_pointer.pass.cpp
@@ -16,6 +16,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -24,46 +25,31 @@
     assert((lhs == rhs) == x);
 }
 
+template <class S>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  test(S(""), "", true);
+  test(S(""), "abcde", false);
+  test(S(""), "abcdefghij", false);
+  test(S(""), "abcdefghijklmnopqrst", false);
+  test(S("abcde"), "", false);
+  test(S("abcde"), "abcde", true);
+  test(S("abcde"), "abcdefghij", false);
+  test(S("abcde"), "abcdefghijklmnopqrst", false);
+  test(S("abcdefghij"), "", false);
+  test(S("abcdefghij"), "abcde", false);
+  test(S("abcdefghij"), "abcdefghij", true);
+  test(S("abcdefghij"), "abcdefghijklmnopqrst", false);
+  test(S("abcdefghijklmnopqrst"), "", false);
+  test(S("abcdefghijklmnopqrst"), "abcde", false);
+  test(S("abcdefghijklmnopqrst"), "abcdefghij", false);
+  test(S("abcdefghijklmnopqrst"), "abcdefghijklmnopqrst", true);
+}
+
 TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    test(S(""), "", true);
-    test(S(""), "abcde", false);
-    test(S(""), "abcdefghij", false);
-    test(S(""), "abcdefghijklmnopqrst", false);
-    test(S("abcde"), "", false);
-    test(S("abcde"), "abcde", true);
-    test(S("abcde"), "abcdefghij", false);
-    test(S("abcde"), "abcdefghijklmnopqrst", false);
-    test(S("abcdefghij"), "", false);
-    test(S("abcdefghij"), "abcde", false);
-    test(S("abcdefghij"), "abcdefghij", true);
-    test(S("abcdefghij"), "abcdefghijklmnopqrst", false);
-    test(S("abcdefghijklmnopqrst"), "", false);
-    test(S("abcdefghijklmnopqrst"), "abcde", false);
-    test(S("abcdefghijklmnopqrst"), "abcdefghij", false);
-    test(S("abcdefghijklmnopqrst"), "abcdefghijklmnopqrst", true);
-  }
+  test_string<std::string>();
 #if TEST_STD_VER >= 11
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    test(S(""), "", true);
-    test(S(""), "abcde", false);
-    test(S(""), "abcdefghij", false);
-    test(S(""), "abcdefghijklmnopqrst", false);
-    test(S("abcde"), "", false);
-    test(S("abcde"), "abcde", true);
-    test(S("abcde"), "abcdefghij", false);
-    test(S("abcde"), "abcdefghijklmnopqrst", false);
-    test(S("abcdefghij"), "", false);
-    test(S("abcdefghij"), "abcde", false);
-    test(S("abcdefghij"), "abcdefghij", true);
-    test(S("abcdefghij"), "abcdefghijklmnopqrst", false);
-    test(S("abcdefghijklmnopqrst"), "", false);
-    test(S("abcdefghijklmnopqrst"), "abcde", false);
-    test(S("abcdefghijklmnopqrst"), "abcdefghij", false);
-    test(S("abcdefghijklmnopqrst"), "abcdefghijklmnopqrst", true);
-  }
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string_operator==/string_string.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string_operator==/string_string.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string_operator==/string_string.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string_operator==/string_string.pass.cpp
@@ -17,6 +17,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -25,46 +26,31 @@
     assert((lhs == rhs) == x);
 }
 
+template <class S>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  test(S(""), S(""), true);
+  test(S(""), S("abcde"), false);
+  test(S(""), S("abcdefghij"), false);
+  test(S(""), S("abcdefghijklmnopqrst"), false);
+  test(S("abcde"), S(""), false);
+  test(S("abcde"), S("abcde"), true);
+  test(S("abcde"), S("abcdefghij"), false);
+  test(S("abcde"), S("abcdefghijklmnopqrst"), false);
+  test(S("abcdefghij"), S(""), false);
+  test(S("abcdefghij"), S("abcde"), false);
+  test(S("abcdefghij"), S("abcdefghij"), true);
+  test(S("abcdefghij"), S("abcdefghijklmnopqrst"), false);
+  test(S("abcdefghijklmnopqrst"), S(""), false);
+  test(S("abcdefghijklmnopqrst"), S("abcde"), false);
+  test(S("abcdefghijklmnopqrst"), S("abcdefghij"), false);
+  test(S("abcdefghijklmnopqrst"), S("abcdefghijklmnopqrst"), true);
+}
+
 TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    test(S(""), S(""), true);
-    test(S(""), S("abcde"), false);
-    test(S(""), S("abcdefghij"), false);
-    test(S(""), S("abcdefghijklmnopqrst"), false);
-    test(S("abcde"), S(""), false);
-    test(S("abcde"), S("abcde"), true);
-    test(S("abcde"), S("abcdefghij"), false);
-    test(S("abcde"), S("abcdefghijklmnopqrst"), false);
-    test(S("abcdefghij"), S(""), false);
-    test(S("abcdefghij"), S("abcde"), false);
-    test(S("abcdefghij"), S("abcdefghij"), true);
-    test(S("abcdefghij"), S("abcdefghijklmnopqrst"), false);
-    test(S("abcdefghijklmnopqrst"), S(""), false);
-    test(S("abcdefghijklmnopqrst"), S("abcde"), false);
-    test(S("abcdefghijklmnopqrst"), S("abcdefghij"), false);
-    test(S("abcdefghijklmnopqrst"), S("abcdefghijklmnopqrst"), true);
-  }
+  test_string<std::string>();
 #if TEST_STD_VER >= 11
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    test(S(""), S(""), true);
-    test(S(""), S("abcde"), false);
-    test(S(""), S("abcdefghij"), false);
-    test(S(""), S("abcdefghijklmnopqrst"), false);
-    test(S("abcde"), S(""), false);
-    test(S("abcde"), S("abcde"), true);
-    test(S("abcde"), S("abcdefghij"), false);
-    test(S("abcde"), S("abcdefghijklmnopqrst"), false);
-    test(S("abcdefghij"), S(""), false);
-    test(S("abcdefghij"), S("abcde"), false);
-    test(S("abcdefghij"), S("abcdefghij"), true);
-    test(S("abcdefghij"), S("abcdefghijklmnopqrst"), false);
-    test(S("abcdefghijklmnopqrst"), S(""), false);
-    test(S("abcdefghijklmnopqrst"), S("abcde"), false);
-    test(S("abcdefghijklmnopqrst"), S("abcdefghij"), false);
-    test(S("abcdefghijklmnopqrst"), S("abcdefghijklmnopqrst"), true);
-  }
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string_operator==/string_string_view.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string_operator==/string_string_view.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string_operator==/string_string_view.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string_operator==/string_string_view.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S, class SV>
 TEST_CONSTEXPR_CXX20 void
@@ -23,48 +24,33 @@
     assert((lhs == rhs) == x);
 }
 
+template <class CharT, template <class> class Alloc>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  using S  = std::basic_string<CharT, std::char_traits<CharT>, Alloc<CharT>>;
+  using SV = std::basic_string_view<CharT, std::char_traits<CharT>>;
+  test(S(""), SV(""), true);
+  test(S(""), SV("abcde"), false);
+  test(S(""), SV("abcdefghij"), false);
+  test(S(""), SV("abcdefghijklmnopqrst"), false);
+  test(S("abcde"), SV(""), false);
+  test(S("abcde"), SV("abcde"), true);
+  test(S("abcde"), SV("abcdefghij"), false);
+  test(S("abcde"), SV("abcdefghijklmnopqrst"), false);
+  test(S("abcdefghij"), SV(""), false);
+  test(S("abcdefghij"), SV("abcde"), false);
+  test(S("abcdefghij"), SV("abcdefghij"), true);
+  test(S("abcdefghij"), SV("abcdefghijklmnopqrst"), false);
+  test(S("abcdefghijklmnopqrst"), SV(""), false);
+  test(S("abcdefghijklmnopqrst"), SV("abcde"), false);
+  test(S("abcdefghijklmnopqrst"), SV("abcdefghij"), false);
+  test(S("abcdefghijklmnopqrst"), SV("abcdefghijklmnopqrst"), true);
+}
+
 TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    typedef std::string_view SV;
-    test(S(""), SV(""), true);
-    test(S(""), SV("abcde"), false);
-    test(S(""), SV("abcdefghij"), false);
-    test(S(""), SV("abcdefghijklmnopqrst"), false);
-    test(S("abcde"), SV(""), false);
-    test(S("abcde"), SV("abcde"), true);
-    test(S("abcde"), SV("abcdefghij"), false);
-    test(S("abcde"), SV("abcdefghijklmnopqrst"), false);
-    test(S("abcdefghij"), SV(""), false);
-    test(S("abcdefghij"), SV("abcde"), false);
-    test(S("abcdefghij"), SV("abcdefghij"), true);
-    test(S("abcdefghij"), SV("abcdefghijklmnopqrst"), false);
-    test(S("abcdefghijklmnopqrst"), SV(""), false);
-    test(S("abcdefghijklmnopqrst"), SV("abcde"), false);
-    test(S("abcdefghijklmnopqrst"), SV("abcdefghij"), false);
-    test(S("abcdefghijklmnopqrst"), SV("abcdefghijklmnopqrst"), true);
-  }
+  test_string<char, std::allocator>();
 #if TEST_STD_VER >= 11
-  {
-    typedef std::basic_string     <char, std::char_traits<char>, min_allocator<char>> S;
-    typedef std::basic_string_view<char, std::char_traits<char>> SV;
-    test(S(""), SV(""), true);
-    test(S(""), SV("abcde"), false);
-    test(S(""), SV("abcdefghij"), false);
-    test(S(""), SV("abcdefghijklmnopqrst"), false);
-    test(S("abcde"), SV(""), false);
-    test(S("abcde"), SV("abcde"), true);
-    test(S("abcde"), SV("abcdefghij"), false);
-    test(S("abcde"), SV("abcdefghijklmnopqrst"), false);
-    test(S("abcdefghij"), SV(""), false);
-    test(S("abcdefghij"), SV("abcde"), false);
-    test(S("abcdefghij"), SV("abcdefghij"), true);
-    test(S("abcdefghij"), SV("abcdefghijklmnopqrst"), false);
-    test(S("abcdefghijklmnopqrst"), SV(""), false);
-    test(S("abcdefghijklmnopqrst"), SV("abcde"), false);
-    test(S("abcdefghijklmnopqrst"), SV("abcdefghij"), false);
-    test(S("abcdefghijklmnopqrst"), SV("abcdefghijklmnopqrst"), true);
-  }
+  test_string<char, min_allocator>();
+  test_string<char, fancy_pointer_allocator>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string_operator==/string_view_string.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string_operator==/string_view_string.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string_operator==/string_view_string.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string_operator==/string_view_string.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S, class SV>
 TEST_CONSTEXPR_CXX20 void
@@ -23,50 +24,35 @@
     assert((lhs == rhs) == x);
 }
 
+template <class CharT, template <class> class Alloc>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  using S  = std::basic_string<CharT, std::char_traits<CharT>, Alloc<CharT>>;
+  using SV = std::basic_string_view<CharT, std::char_traits<CharT>>;
+
+  test(SV(""), S(""), true);
+  test(SV(""), S("abcde"), false);
+  test(SV(""), S("abcdefghij"), false);
+  test(SV(""), S("abcdefghijklmnopqrst"), false);
+  test(SV("abcde"), S(""), false);
+  test(SV("abcde"), S("abcde"), true);
+  test(SV("abcde"), S("abcdefghij"), false);
+  test(SV("abcde"), S("abcdefghijklmnopqrst"), false);
+  test(SV("abcdefghij"), S(""), false);
+  test(SV("abcdefghij"), S("abcde"), false);
+  test(SV("abcdefghij"), S("abcdefghij"), true);
+  test(SV("abcdefghij"), S("abcdefghijklmnopqrst"), false);
+  test(SV("abcdefghijklmnopqrst"), S(""), false);
+  test(SV("abcdefghijklmnopqrst"), S("abcde"), false);
+  test(SV("abcdefghijklmnopqrst"), S("abcdefghij"), false);
+  test(SV("abcdefghijklmnopqrst"), S("abcdefghijklmnopqrst"), true);
+}
+
 TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    typedef std::string_view SV;
-    test(SV(""), S(""), true);
-    test(SV(""), S("abcde"), false);
-    test(SV(""), S("abcdefghij"), false);
-    test(SV(""), S("abcdefghijklmnopqrst"), false);
-    test(SV("abcde"), S(""), false);
-    test(SV("abcde"), S("abcde"), true);
-    test(SV("abcde"), S("abcdefghij"), false);
-    test(SV("abcde"), S("abcdefghijklmnopqrst"), false);
-    test(SV("abcdefghij"), S(""), false);
-    test(SV("abcdefghij"), S("abcde"), false);
-    test(SV("abcdefghij"), S("abcdefghij"), true);
-    test(SV("abcdefghij"), S("abcdefghijklmnopqrst"), false);
-    test(SV("abcdefghijklmnopqrst"), S(""), false);
-    test(SV("abcdefghijklmnopqrst"), S("abcde"), false);
-    test(SV("abcdefghijklmnopqrst"), S("abcdefghij"), false);
-    test(SV("abcdefghijklmnopqrst"), S("abcdefghijklmnopqrst"), true);
-  }
+  test_string<char, std::allocator>();
 #if TEST_STD_VER >= 11
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    typedef std::basic_string_view<char, std::char_traits<char>> SV;
-    test(SV(""), S(""), true);
-    test(SV(""), S("abcde"), false);
-    test(SV(""), S("abcdefghij"), false);
-    test(SV(""), S("abcdefghijklmnopqrst"), false);
-    test(SV("abcde"), S(""), false);
-    test(SV("abcde"), S("abcde"), true);
-    test(SV("abcde"), S("abcdefghij"), false);
-    test(SV("abcde"), S("abcdefghijklmnopqrst"), false);
-    test(SV("abcdefghij"), S(""), false);
-    test(SV("abcdefghij"), S("abcde"), false);
-    test(SV("abcdefghij"), S("abcdefghij"), true);
-    test(SV("abcdefghij"), S("abcdefghijklmnopqrst"), false);
-    test(SV("abcdefghijklmnopqrst"), S(""), false);
-    test(SV("abcdefghijklmnopqrst"), S("abcde"), false);
-    test(SV("abcdefghijklmnopqrst"), S("abcdefghij"), false);
-    test(SV("abcdefghijklmnopqrst"), S("abcdefghijklmnopqrst"), true);
-  }
+  test_string<char, min_allocator>();
+  test_string<char, fancy_pointer_allocator>();
 #endif
-
   return true;
 }
 
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string_opgt/pointer_string.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string_opgt/pointer_string.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string_opgt/pointer_string.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string_opgt/pointer_string.pass.cpp
@@ -16,6 +16,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -24,46 +25,31 @@
     assert((lhs > rhs) == x);
 }
 
+template <class S>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  test("", S(""), false);
+  test("", S("abcde"), false);
+  test("", S("abcdefghij"), false);
+  test("", S("abcdefghijklmnopqrst"), false);
+  test("abcde", S(""), true);
+  test("abcde", S("abcde"), false);
+  test("abcde", S("abcdefghij"), false);
+  test("abcde", S("abcdefghijklmnopqrst"), false);
+  test("abcdefghij", S(""), true);
+  test("abcdefghij", S("abcde"), true);
+  test("abcdefghij", S("abcdefghij"), false);
+  test("abcdefghij", S("abcdefghijklmnopqrst"), false);
+  test("abcdefghijklmnopqrst", S(""), true);
+  test("abcdefghijklmnopqrst", S("abcde"), true);
+  test("abcdefghijklmnopqrst", S("abcdefghij"), true);
+  test("abcdefghijklmnopqrst", S("abcdefghijklmnopqrst"), false);
+}
+
 TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    test("", S(""), false);
-    test("", S("abcde"), false);
-    test("", S("abcdefghij"), false);
-    test("", S("abcdefghijklmnopqrst"), false);
-    test("abcde", S(""), true);
-    test("abcde", S("abcde"), false);
-    test("abcde", S("abcdefghij"), false);
-    test("abcde", S("abcdefghijklmnopqrst"), false);
-    test("abcdefghij", S(""), true);
-    test("abcdefghij", S("abcde"), true);
-    test("abcdefghij", S("abcdefghij"), false);
-    test("abcdefghij", S("abcdefghijklmnopqrst"), false);
-    test("abcdefghijklmnopqrst", S(""), true);
-    test("abcdefghijklmnopqrst", S("abcde"), true);
-    test("abcdefghijklmnopqrst", S("abcdefghij"), true);
-    test("abcdefghijklmnopqrst", S("abcdefghijklmnopqrst"), false);
-  }
+  test_string<std::string>();
 #if TEST_STD_VER >= 11
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    test("", S(""), false);
-    test("", S("abcde"), false);
-    test("", S("abcdefghij"), false);
-    test("", S("abcdefghijklmnopqrst"), false);
-    test("abcde", S(""), true);
-    test("abcde", S("abcde"), false);
-    test("abcde", S("abcdefghij"), false);
-    test("abcde", S("abcdefghijklmnopqrst"), false);
-    test("abcdefghij", S(""), true);
-    test("abcdefghij", S("abcde"), true);
-    test("abcdefghij", S("abcdefghij"), false);
-    test("abcdefghij", S("abcdefghijklmnopqrst"), false);
-    test("abcdefghijklmnopqrst", S(""), true);
-    test("abcdefghijklmnopqrst", S("abcde"), true);
-    test("abcdefghijklmnopqrst", S("abcdefghij"), true);
-    test("abcdefghijklmnopqrst", S("abcdefghijklmnopqrst"), false);
-  }
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string_opgt/string_pointer.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string_opgt/string_pointer.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string_opgt/string_pointer.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string_opgt/string_pointer.pass.cpp
@@ -16,6 +16,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -24,46 +25,31 @@
     assert((lhs > rhs) == x);
 }
 
+template <class S>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  test(S(""), "", false);
+  test(S(""), "abcde", false);
+  test(S(""), "abcdefghij", false);
+  test(S(""), "abcdefghijklmnopqrst", false);
+  test(S("abcde"), "", true);
+  test(S("abcde"), "abcde", false);
+  test(S("abcde"), "abcdefghij", false);
+  test(S("abcde"), "abcdefghijklmnopqrst", false);
+  test(S("abcdefghij"), "", true);
+  test(S("abcdefghij"), "abcde", true);
+  test(S("abcdefghij"), "abcdefghij", false);
+  test(S("abcdefghij"), "abcdefghijklmnopqrst", false);
+  test(S("abcdefghijklmnopqrst"), "", true);
+  test(S("abcdefghijklmnopqrst"), "abcde", true);
+  test(S("abcdefghijklmnopqrst"), "abcdefghij", true);
+  test(S("abcdefghijklmnopqrst"), "abcdefghijklmnopqrst", false);
+}
+
 TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    test(S(""), "", false);
-    test(S(""), "abcde", false);
-    test(S(""), "abcdefghij", false);
-    test(S(""), "abcdefghijklmnopqrst", false);
-    test(S("abcde"), "", true);
-    test(S("abcde"), "abcde", false);
-    test(S("abcde"), "abcdefghij", false);
-    test(S("abcde"), "abcdefghijklmnopqrst", false);
-    test(S("abcdefghij"), "", true);
-    test(S("abcdefghij"), "abcde", true);
-    test(S("abcdefghij"), "abcdefghij", false);
-    test(S("abcdefghij"), "abcdefghijklmnopqrst", false);
-    test(S("abcdefghijklmnopqrst"), "", true);
-    test(S("abcdefghijklmnopqrst"), "abcde", true);
-    test(S("abcdefghijklmnopqrst"), "abcdefghij", true);
-    test(S("abcdefghijklmnopqrst"), "abcdefghijklmnopqrst", false);
-  }
+  test_string<std::string>();
 #if TEST_STD_VER >= 11
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    test(S(""), "", false);
-    test(S(""), "abcde", false);
-    test(S(""), "abcdefghij", false);
-    test(S(""), "abcdefghijklmnopqrst", false);
-    test(S("abcde"), "", true);
-    test(S("abcde"), "abcde", false);
-    test(S("abcde"), "abcdefghij", false);
-    test(S("abcde"), "abcdefghijklmnopqrst", false);
-    test(S("abcdefghij"), "", true);
-    test(S("abcdefghij"), "abcde", true);
-    test(S("abcdefghij"), "abcdefghij", false);
-    test(S("abcdefghij"), "abcdefghijklmnopqrst", false);
-    test(S("abcdefghijklmnopqrst"), "", true);
-    test(S("abcdefghijklmnopqrst"), "abcde", true);
-    test(S("abcdefghijklmnopqrst"), "abcdefghij", true);
-    test(S("abcdefghijklmnopqrst"), "abcdefghijklmnopqrst", false);
-  }
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string_opgt/string_string.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string_opgt/string_string.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string_opgt/string_string.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string_opgt/string_string.pass.cpp
@@ -17,6 +17,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -25,46 +26,31 @@
     assert((lhs > rhs) == x);
 }
 
+template <class S>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  test(S(""), S(""), false);
+  test(S(""), S("abcde"), false);
+  test(S(""), S("abcdefghij"), false);
+  test(S(""), S("abcdefghijklmnopqrst"), false);
+  test(S("abcde"), S(""), true);
+  test(S("abcde"), S("abcde"), false);
+  test(S("abcde"), S("abcdefghij"), false);
+  test(S("abcde"), S("abcdefghijklmnopqrst"), false);
+  test(S("abcdefghij"), S(""), true);
+  test(S("abcdefghij"), S("abcde"), true);
+  test(S("abcdefghij"), S("abcdefghij"), false);
+  test(S("abcdefghij"), S("abcdefghijklmnopqrst"), false);
+  test(S("abcdefghijklmnopqrst"), S(""), true);
+  test(S("abcdefghijklmnopqrst"), S("abcde"), true);
+  test(S("abcdefghijklmnopqrst"), S("abcdefghij"), true);
+  test(S("abcdefghijklmnopqrst"), S("abcdefghijklmnopqrst"), false);
+}
+
 TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    test(S(""), S(""), false);
-    test(S(""), S("abcde"), false);
-    test(S(""), S("abcdefghij"), false);
-    test(S(""), S("abcdefghijklmnopqrst"), false);
-    test(S("abcde"), S(""), true);
-    test(S("abcde"), S("abcde"), false);
-    test(S("abcde"), S("abcdefghij"), false);
-    test(S("abcde"), S("abcdefghijklmnopqrst"), false);
-    test(S("abcdefghij"), S(""), true);
-    test(S("abcdefghij"), S("abcde"), true);
-    test(S("abcdefghij"), S("abcdefghij"), false);
-    test(S("abcdefghij"), S("abcdefghijklmnopqrst"), false);
-    test(S("abcdefghijklmnopqrst"), S(""), true);
-    test(S("abcdefghijklmnopqrst"), S("abcde"), true);
-    test(S("abcdefghijklmnopqrst"), S("abcdefghij"), true);
-    test(S("abcdefghijklmnopqrst"), S("abcdefghijklmnopqrst"), false);
-  }
+  test_string<std::string>();
 #if TEST_STD_VER >= 11
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    test(S(""), S(""), false);
-    test(S(""), S("abcde"), false);
-    test(S(""), S("abcdefghij"), false);
-    test(S(""), S("abcdefghijklmnopqrst"), false);
-    test(S("abcde"), S(""), true);
-    test(S("abcde"), S("abcde"), false);
-    test(S("abcde"), S("abcdefghij"), false);
-    test(S("abcde"), S("abcdefghijklmnopqrst"), false);
-    test(S("abcdefghij"), S(""), true);
-    test(S("abcdefghij"), S("abcde"), true);
-    test(S("abcdefghij"), S("abcdefghij"), false);
-    test(S("abcdefghij"), S("abcdefghijklmnopqrst"), false);
-    test(S("abcdefghijklmnopqrst"), S(""), true);
-    test(S("abcdefghijklmnopqrst"), S("abcde"), true);
-    test(S("abcdefghijklmnopqrst"), S("abcdefghij"), true);
-    test(S("abcdefghijklmnopqrst"), S("abcdefghijklmnopqrst"), false);
-  }
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string_opgt/string_string_view.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string_opgt/string_string_view.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string_opgt/string_string_view.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string_opgt/string_string_view.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S, class SV>
 TEST_CONSTEXPR_CXX20 void
@@ -23,48 +24,33 @@
     assert((lhs > rhs) == x);
 }
 
+template <class CharT, template <class> class Alloc>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  using S  = std::basic_string<CharT, std::char_traits<CharT>, Alloc<CharT>>;
+  using SV = std::basic_string_view<CharT, std::char_traits<CharT>>;
+  test(S(""), SV(""), false);
+  test(S(""), SV("abcde"), false);
+  test(S(""), SV("abcdefghij"), false);
+  test(S(""), SV("abcdefghijklmnopqrst"), false);
+  test(S("abcde"), SV(""), true);
+  test(S("abcde"), SV("abcde"), false);
+  test(S("abcde"), SV("abcdefghij"), false);
+  test(S("abcde"), SV("abcdefghijklmnopqrst"), false);
+  test(S("abcdefghij"), SV(""), true);
+  test(S("abcdefghij"), SV("abcde"), true);
+  test(S("abcdefghij"), SV("abcdefghij"), false);
+  test(S("abcdefghij"), SV("abcdefghijklmnopqrst"), false);
+  test(S("abcdefghijklmnopqrst"), SV(""), true);
+  test(S("abcdefghijklmnopqrst"), SV("abcde"), true);
+  test(S("abcdefghijklmnopqrst"), SV("abcdefghij"), true);
+  test(S("abcdefghijklmnopqrst"), SV("abcdefghijklmnopqrst"), false);
+}
+
 TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    typedef std::string_view SV;
-    test(S(""), SV(""), false);
-    test(S(""), SV("abcde"), false);
-    test(S(""), SV("abcdefghij"), false);
-    test(S(""), SV("abcdefghijklmnopqrst"), false);
-    test(S("abcde"), SV(""), true);
-    test(S("abcde"), SV("abcde"), false);
-    test(S("abcde"), SV("abcdefghij"), false);
-    test(S("abcde"), SV("abcdefghijklmnopqrst"), false);
-    test(S("abcdefghij"), SV(""), true);
-    test(S("abcdefghij"), SV("abcde"), true);
-    test(S("abcdefghij"), SV("abcdefghij"), false);
-    test(S("abcdefghij"), SV("abcdefghijklmnopqrst"), false);
-    test(S("abcdefghijklmnopqrst"), SV(""), true);
-    test(S("abcdefghijklmnopqrst"), SV("abcde"), true);
-    test(S("abcdefghijklmnopqrst"), SV("abcdefghij"), true);
-    test(S("abcdefghijklmnopqrst"), SV("abcdefghijklmnopqrst"), false);
-  }
+  test_string<char, std::allocator>();
 #if TEST_STD_VER >= 11
-  {
-    typedef std::basic_string     <char, std::char_traits<char>, min_allocator<char>> S;
-    typedef std::basic_string_view<char, std::char_traits<char>> SV;
-    test(S(""), SV(""), false);
-    test(S(""), SV("abcde"), false);
-    test(S(""), SV("abcdefghij"), false);
-    test(S(""), SV("abcdefghijklmnopqrst"), false);
-    test(S("abcde"), SV(""), true);
-    test(S("abcde"), SV("abcde"), false);
-    test(S("abcde"), SV("abcdefghij"), false);
-    test(S("abcde"), SV("abcdefghijklmnopqrst"), false);
-    test(S("abcdefghij"), SV(""), true);
-    test(S("abcdefghij"), SV("abcde"), true);
-    test(S("abcdefghij"), SV("abcdefghij"), false);
-    test(S("abcdefghij"), SV("abcdefghijklmnopqrst"), false);
-    test(S("abcdefghijklmnopqrst"), SV(""), true);
-    test(S("abcdefghijklmnopqrst"), SV("abcde"), true);
-    test(S("abcdefghijklmnopqrst"), SV("abcdefghij"), true);
-    test(S("abcdefghijklmnopqrst"), SV("abcdefghijklmnopqrst"), false);
-  }
+  test_string<char, min_allocator>();
+  test_string<char, fancy_pointer_allocator>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string_opgt/string_view_string.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string_opgt/string_view_string.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string_opgt/string_view_string.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string_opgt/string_view_string.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S, class SV>
 TEST_CONSTEXPR_CXX20 void
@@ -23,48 +24,33 @@
     assert((lhs > rhs) == x);
 }
 
+template <class CharT, template <class> class Alloc>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  using S  = std::basic_string<CharT, std::char_traits<CharT>, Alloc<CharT>>;
+  using SV = std::basic_string_view<CharT, std::char_traits<CharT>>;
+  test(SV(""), S(""), false);
+  test(SV(""), S("abcde"), false);
+  test(SV(""), S("abcdefghij"), false);
+  test(SV(""), S("abcdefghijklmnopqrst"), false);
+  test(SV("abcde"), S(""), true);
+  test(SV("abcde"), S("abcde"), false);
+  test(SV("abcde"), S("abcdefghij"), false);
+  test(SV("abcde"), S("abcdefghijklmnopqrst"), false);
+  test(SV("abcdefghij"), S(""), true);
+  test(SV("abcdefghij"), S("abcde"), true);
+  test(SV("abcdefghij"), S("abcdefghij"), false);
+  test(SV("abcdefghij"), S("abcdefghijklmnopqrst"), false);
+  test(SV("abcdefghijklmnopqrst"), S(""), true);
+  test(SV("abcdefghijklmnopqrst"), S("abcde"), true);
+  test(SV("abcdefghijklmnopqrst"), S("abcdefghij"), true);
+  test(SV("abcdefghijklmnopqrst"), S("abcdefghijklmnopqrst"), false);
+}
+
 TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    typedef std::string_view SV;
-    test(SV(""), S(""), false);
-    test(SV(""), S("abcde"), false);
-    test(SV(""), S("abcdefghij"), false);
-    test(SV(""), S("abcdefghijklmnopqrst"), false);
-    test(SV("abcde"), S(""), true);
-    test(SV("abcde"), S("abcde"), false);
-    test(SV("abcde"), S("abcdefghij"), false);
-    test(SV("abcde"), S("abcdefghijklmnopqrst"), false);
-    test(SV("abcdefghij"), S(""), true);
-    test(SV("abcdefghij"), S("abcde"), true);
-    test(SV("abcdefghij"), S("abcdefghij"), false);
-    test(SV("abcdefghij"), S("abcdefghijklmnopqrst"), false);
-    test(SV("abcdefghijklmnopqrst"), S(""), true);
-    test(SV("abcdefghijklmnopqrst"), S("abcde"), true);
-    test(SV("abcdefghijklmnopqrst"), S("abcdefghij"), true);
-    test(SV("abcdefghijklmnopqrst"), S("abcdefghijklmnopqrst"), false);
-  }
+  test_string<char, std::allocator>();
 #if TEST_STD_VER >= 11
-  {
-    typedef std::basic_string     <char, std::char_traits<char>, min_allocator<char>> S;
-    typedef std::basic_string_view<char, std::char_traits<char>> SV;
-    test(SV(""), S(""), false);
-    test(SV(""), S("abcde"), false);
-    test(SV(""), S("abcdefghij"), false);
-    test(SV(""), S("abcdefghijklmnopqrst"), false);
-    test(SV("abcde"), S(""), true);
-    test(SV("abcde"), S("abcde"), false);
-    test(SV("abcde"), S("abcdefghij"), false);
-    test(SV("abcde"), S("abcdefghijklmnopqrst"), false);
-    test(SV("abcdefghij"), S(""), true);
-    test(SV("abcdefghij"), S("abcde"), true);
-    test(SV("abcdefghij"), S("abcdefghij"), false);
-    test(SV("abcdefghij"), S("abcdefghijklmnopqrst"), false);
-    test(SV("abcdefghijklmnopqrst"), S(""), true);
-    test(SV("abcdefghijklmnopqrst"), S("abcde"), true);
-    test(SV("abcdefghijklmnopqrst"), S("abcdefghij"), true);
-    test(SV("abcdefghijklmnopqrst"), S("abcdefghijklmnopqrst"), false);
-  }
+  test_string<char, min_allocator>();
+  test_string<char, fancy_pointer_allocator>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string_opgt=/pointer_string.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string_opgt=/pointer_string.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string_opgt=/pointer_string.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string_opgt=/pointer_string.pass.cpp
@@ -16,6 +16,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -24,46 +25,31 @@
     assert((lhs >= rhs) == x);
 }
 
+template <class S>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  test("", S(""), true);
+  test("", S("abcde"), false);
+  test("", S("abcdefghij"), false);
+  test("", S("abcdefghijklmnopqrst"), false);
+  test("abcde", S(""), true);
+  test("abcde", S("abcde"), true);
+  test("abcde", S("abcdefghij"), false);
+  test("abcde", S("abcdefghijklmnopqrst"), false);
+  test("abcdefghij", S(""), true);
+  test("abcdefghij", S("abcde"), true);
+  test("abcdefghij", S("abcdefghij"), true);
+  test("abcdefghij", S("abcdefghijklmnopqrst"), false);
+  test("abcdefghijklmnopqrst", S(""), true);
+  test("abcdefghijklmnopqrst", S("abcde"), true);
+  test("abcdefghijklmnopqrst", S("abcdefghij"), true);
+  test("abcdefghijklmnopqrst", S("abcdefghijklmnopqrst"), true);
+}
+
 TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    test("", S(""), true);
-    test("", S("abcde"), false);
-    test("", S("abcdefghij"), false);
-    test("", S("abcdefghijklmnopqrst"), false);
-    test("abcde", S(""), true);
-    test("abcde", S("abcde"), true);
-    test("abcde", S("abcdefghij"), false);
-    test("abcde", S("abcdefghijklmnopqrst"), false);
-    test("abcdefghij", S(""), true);
-    test("abcdefghij", S("abcde"), true);
-    test("abcdefghij", S("abcdefghij"), true);
-    test("abcdefghij", S("abcdefghijklmnopqrst"), false);
-    test("abcdefghijklmnopqrst", S(""), true);
-    test("abcdefghijklmnopqrst", S("abcde"), true);
-    test("abcdefghijklmnopqrst", S("abcdefghij"), true);
-    test("abcdefghijklmnopqrst", S("abcdefghijklmnopqrst"), true);
-  }
+  test_string<std::string>();
 #if TEST_STD_VER >= 11
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    test("", S(""), true);
-    test("", S("abcde"), false);
-    test("", S("abcdefghij"), false);
-    test("", S("abcdefghijklmnopqrst"), false);
-    test("abcde", S(""), true);
-    test("abcde", S("abcde"), true);
-    test("abcde", S("abcdefghij"), false);
-    test("abcde", S("abcdefghijklmnopqrst"), false);
-    test("abcdefghij", S(""), true);
-    test("abcdefghij", S("abcde"), true);
-    test("abcdefghij", S("abcdefghij"), true);
-    test("abcdefghij", S("abcdefghijklmnopqrst"), false);
-    test("abcdefghijklmnopqrst", S(""), true);
-    test("abcdefghijklmnopqrst", S("abcde"), true);
-    test("abcdefghijklmnopqrst", S("abcdefghij"), true);
-    test("abcdefghijklmnopqrst", S("abcdefghijklmnopqrst"), true);
-  }
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string_opgt=/string_pointer.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string_opgt=/string_pointer.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string_opgt=/string_pointer.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string_opgt=/string_pointer.pass.cpp
@@ -16,6 +16,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -24,46 +25,31 @@
     assert((lhs >= rhs) == x);
 }
 
+template <class S>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  test(S(""), "", true);
+  test(S(""), "abcde", false);
+  test(S(""), "abcdefghij", false);
+  test(S(""), "abcdefghijklmnopqrst", false);
+  test(S("abcde"), "", true);
+  test(S("abcde"), "abcde", true);
+  test(S("abcde"), "abcdefghij", false);
+  test(S("abcde"), "abcdefghijklmnopqrst", false);
+  test(S("abcdefghij"), "", true);
+  test(S("abcdefghij"), "abcde", true);
+  test(S("abcdefghij"), "abcdefghij", true);
+  test(S("abcdefghij"), "abcdefghijklmnopqrst", false);
+  test(S("abcdefghijklmnopqrst"), "", true);
+  test(S("abcdefghijklmnopqrst"), "abcde", true);
+  test(S("abcdefghijklmnopqrst"), "abcdefghij", true);
+  test(S("abcdefghijklmnopqrst"), "abcdefghijklmnopqrst", true);
+}
+
 TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    test(S(""), "", true);
-    test(S(""), "abcde", false);
-    test(S(""), "abcdefghij", false);
-    test(S(""), "abcdefghijklmnopqrst", false);
-    test(S("abcde"), "", true);
-    test(S("abcde"), "abcde", true);
-    test(S("abcde"), "abcdefghij", false);
-    test(S("abcde"), "abcdefghijklmnopqrst", false);
-    test(S("abcdefghij"), "", true);
-    test(S("abcdefghij"), "abcde", true);
-    test(S("abcdefghij"), "abcdefghij", true);
-    test(S("abcdefghij"), "abcdefghijklmnopqrst", false);
-    test(S("abcdefghijklmnopqrst"), "", true);
-    test(S("abcdefghijklmnopqrst"), "abcde", true);
-    test(S("abcdefghijklmnopqrst"), "abcdefghij", true);
-    test(S("abcdefghijklmnopqrst"), "abcdefghijklmnopqrst", true);
-  }
+  test_string<std::string>();
 #if TEST_STD_VER >= 11
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    test(S(""), "", true);
-    test(S(""), "abcde", false);
-    test(S(""), "abcdefghij", false);
-    test(S(""), "abcdefghijklmnopqrst", false);
-    test(S("abcde"), "", true);
-    test(S("abcde"), "abcde", true);
-    test(S("abcde"), "abcdefghij", false);
-    test(S("abcde"), "abcdefghijklmnopqrst", false);
-    test(S("abcdefghij"), "", true);
-    test(S("abcdefghij"), "abcde", true);
-    test(S("abcdefghij"), "abcdefghij", true);
-    test(S("abcdefghij"), "abcdefghijklmnopqrst", false);
-    test(S("abcdefghijklmnopqrst"), "", true);
-    test(S("abcdefghijklmnopqrst"), "abcde", true);
-    test(S("abcdefghijklmnopqrst"), "abcdefghij", true);
-    test(S("abcdefghijklmnopqrst"), "abcdefghijklmnopqrst", true);
-  }
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string_opgt=/string_string.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string_opgt=/string_string.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string_opgt=/string_string.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string_opgt=/string_string.pass.cpp
@@ -17,6 +17,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -25,46 +26,31 @@
     assert((lhs >= rhs) == x);
 }
 
+template <class S>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  test(S(""), S(""), true);
+  test(S(""), S("abcde"), false);
+  test(S(""), S("abcdefghij"), false);
+  test(S(""), S("abcdefghijklmnopqrst"), false);
+  test(S("abcde"), S(""), true);
+  test(S("abcde"), S("abcde"), true);
+  test(S("abcde"), S("abcdefghij"), false);
+  test(S("abcde"), S("abcdefghijklmnopqrst"), false);
+  test(S("abcdefghij"), S(""), true);
+  test(S("abcdefghij"), S("abcde"), true);
+  test(S("abcdefghij"), S("abcdefghij"), true);
+  test(S("abcdefghij"), S("abcdefghijklmnopqrst"), false);
+  test(S("abcdefghijklmnopqrst"), S(""), true);
+  test(S("abcdefghijklmnopqrst"), S("abcde"), true);
+  test(S("abcdefghijklmnopqrst"), S("abcdefghij"), true);
+  test(S("abcdefghijklmnopqrst"), S("abcdefghijklmnopqrst"), true);
+}
+
 TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    test(S(""), S(""), true);
-    test(S(""), S("abcde"), false);
-    test(S(""), S("abcdefghij"), false);
-    test(S(""), S("abcdefghijklmnopqrst"), false);
-    test(S("abcde"), S(""), true);
-    test(S("abcde"), S("abcde"), true);
-    test(S("abcde"), S("abcdefghij"), false);
-    test(S("abcde"), S("abcdefghijklmnopqrst"), false);
-    test(S("abcdefghij"), S(""), true);
-    test(S("abcdefghij"), S("abcde"), true);
-    test(S("abcdefghij"), S("abcdefghij"), true);
-    test(S("abcdefghij"), S("abcdefghijklmnopqrst"), false);
-    test(S("abcdefghijklmnopqrst"), S(""), true);
-    test(S("abcdefghijklmnopqrst"), S("abcde"), true);
-    test(S("abcdefghijklmnopqrst"), S("abcdefghij"), true);
-    test(S("abcdefghijklmnopqrst"), S("abcdefghijklmnopqrst"), true);
-  }
+  test_string<std::string>();
 #if TEST_STD_VER >= 11
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    test(S(""), S(""), true);
-    test(S(""), S("abcde"), false);
-    test(S(""), S("abcdefghij"), false);
-    test(S(""), S("abcdefghijklmnopqrst"), false);
-    test(S("abcde"), S(""), true);
-    test(S("abcde"), S("abcde"), true);
-    test(S("abcde"), S("abcdefghij"), false);
-    test(S("abcde"), S("abcdefghijklmnopqrst"), false);
-    test(S("abcdefghij"), S(""), true);
-    test(S("abcdefghij"), S("abcde"), true);
-    test(S("abcdefghij"), S("abcdefghij"), true);
-    test(S("abcdefghij"), S("abcdefghijklmnopqrst"), false);
-    test(S("abcdefghijklmnopqrst"), S(""), true);
-    test(S("abcdefghijklmnopqrst"), S("abcde"), true);
-    test(S("abcdefghijklmnopqrst"), S("abcdefghij"), true);
-    test(S("abcdefghijklmnopqrst"), S("abcdefghijklmnopqrst"), true);
-  }
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string_opgt=/string_string_view.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string_opgt=/string_string_view.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string_opgt=/string_string_view.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string_opgt=/string_string_view.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S, class SV>
 TEST_CONSTEXPR_CXX20 void
@@ -23,48 +24,33 @@
     assert((lhs >= rhs) == x);
 }
 
+template <class CharT, template <class> class Alloc>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  using S  = std::basic_string<CharT, std::char_traits<CharT>, Alloc<CharT>>;
+  using SV = std::basic_string_view<CharT, std::char_traits<CharT>>;
+  test(S(""), SV(""), true);
+  test(S(""), SV("abcde"), false);
+  test(S(""), SV("abcdefghij"), false);
+  test(S(""), SV("abcdefghijklmnopqrst"), false);
+  test(S("abcde"), SV(""), true);
+  test(S("abcde"), SV("abcde"), true);
+  test(S("abcde"), SV("abcdefghij"), false);
+  test(S("abcde"), SV("abcdefghijklmnopqrst"), false);
+  test(S("abcdefghij"), SV(""), true);
+  test(S("abcdefghij"), SV("abcde"), true);
+  test(S("abcdefghij"), SV("abcdefghij"), true);
+  test(S("abcdefghij"), SV("abcdefghijklmnopqrst"), false);
+  test(S("abcdefghijklmnopqrst"), SV(""), true);
+  test(S("abcdefghijklmnopqrst"), SV("abcde"), true);
+  test(S("abcdefghijklmnopqrst"), SV("abcdefghij"), true);
+  test(S("abcdefghijklmnopqrst"), SV("abcdefghijklmnopqrst"), true);
+}
+
 TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    typedef std::string_view SV;
-    test(S(""), SV(""), true);
-    test(S(""), SV("abcde"), false);
-    test(S(""), SV("abcdefghij"), false);
-    test(S(""), SV("abcdefghijklmnopqrst"), false);
-    test(S("abcde"), SV(""), true);
-    test(S("abcde"), SV("abcde"), true);
-    test(S("abcde"), SV("abcdefghij"), false);
-    test(S("abcde"), SV("abcdefghijklmnopqrst"), false);
-    test(S("abcdefghij"), SV(""), true);
-    test(S("abcdefghij"), SV("abcde"), true);
-    test(S("abcdefghij"), SV("abcdefghij"), true);
-    test(S("abcdefghij"), SV("abcdefghijklmnopqrst"), false);
-    test(S("abcdefghijklmnopqrst"), SV(""), true);
-    test(S("abcdefghijklmnopqrst"), SV("abcde"), true);
-    test(S("abcdefghijklmnopqrst"), SV("abcdefghij"), true);
-    test(S("abcdefghijklmnopqrst"), SV("abcdefghijklmnopqrst"), true);
-  }
+  test_string<char, std::allocator>();
 #if TEST_STD_VER >= 11
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    typedef std::basic_string_view<char, std::char_traits<char>> SV;
-    test(S(""), SV(""), true);
-    test(S(""), SV("abcde"), false);
-    test(S(""), SV("abcdefghij"), false);
-    test(S(""), SV("abcdefghijklmnopqrst"), false);
-    test(S("abcde"), SV(""), true);
-    test(S("abcde"), SV("abcde"), true);
-    test(S("abcde"), SV("abcdefghij"), false);
-    test(S("abcde"), SV("abcdefghijklmnopqrst"), false);
-    test(S("abcdefghij"), SV(""), true);
-    test(S("abcdefghij"), SV("abcde"), true);
-    test(S("abcdefghij"), SV("abcdefghij"), true);
-    test(S("abcdefghij"), SV("abcdefghijklmnopqrst"), false);
-    test(S("abcdefghijklmnopqrst"), SV(""), true);
-    test(S("abcdefghijklmnopqrst"), SV("abcde"), true);
-    test(S("abcdefghijklmnopqrst"), SV("abcdefghij"), true);
-    test(S("abcdefghijklmnopqrst"), SV("abcdefghijklmnopqrst"), true);
-  }
+  test_string<char, min_allocator>();
+  test_string<char, fancy_pointer_allocator>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string_opgt=/string_view_string.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string_opgt=/string_view_string.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string_opgt=/string_view_string.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string_opgt=/string_view_string.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S, class SV>
 TEST_CONSTEXPR_CXX20 void
@@ -23,48 +24,33 @@
     assert((lhs >= rhs) == x);
 }
 
+template <class CharT, template <class> class Alloc>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  using S  = std::basic_string<CharT, std::char_traits<CharT>, Alloc<CharT>>;
+  using SV = std::basic_string_view<CharT, std::char_traits<CharT>>;
+  test(SV(""), S(""), true);
+  test(SV(""), S("abcde"), false);
+  test(SV(""), S("abcdefghij"), false);
+  test(SV(""), S("abcdefghijklmnopqrst"), false);
+  test(SV("abcde"), S(""), true);
+  test(SV("abcde"), S("abcde"), true);
+  test(SV("abcde"), S("abcdefghij"), false);
+  test(SV("abcde"), S("abcdefghijklmnopqrst"), false);
+  test(SV("abcdefghij"), S(""), true);
+  test(SV("abcdefghij"), S("abcde"), true);
+  test(SV("abcdefghij"), S("abcdefghij"), true);
+  test(SV("abcdefghij"), S("abcdefghijklmnopqrst"), false);
+  test(SV("abcdefghijklmnopqrst"), S(""), true);
+  test(SV("abcdefghijklmnopqrst"), S("abcde"), true);
+  test(SV("abcdefghijklmnopqrst"), S("abcdefghij"), true);
+  test(SV("abcdefghijklmnopqrst"), S("abcdefghijklmnopqrst"), true);
+}
+
 TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    typedef std::string_view SV;
-    test(SV(""), S(""), true);
-    test(SV(""), S("abcde"), false);
-    test(SV(""), S("abcdefghij"), false);
-    test(SV(""), S("abcdefghijklmnopqrst"), false);
-    test(SV("abcde"), S(""), true);
-    test(SV("abcde"), S("abcde"), true);
-    test(SV("abcde"), S("abcdefghij"), false);
-    test(SV("abcde"), S("abcdefghijklmnopqrst"), false);
-    test(SV("abcdefghij"), S(""), true);
-    test(SV("abcdefghij"), S("abcde"), true);
-    test(SV("abcdefghij"), S("abcdefghij"), true);
-    test(SV("abcdefghij"), S("abcdefghijklmnopqrst"), false);
-    test(SV("abcdefghijklmnopqrst"), S(""), true);
-    test(SV("abcdefghijklmnopqrst"), S("abcde"), true);
-    test(SV("abcdefghijklmnopqrst"), S("abcdefghij"), true);
-    test(SV("abcdefghijklmnopqrst"), S("abcdefghijklmnopqrst"), true);
-  }
+  test_string<char, std::allocator>();
 #if TEST_STD_VER >= 11
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    typedef std::basic_string_view<char, std::char_traits<char>> SV;
-    test(SV(""), S(""), true);
-    test(SV(""), S("abcde"), false);
-    test(SV(""), S("abcdefghij"), false);
-    test(SV(""), S("abcdefghijklmnopqrst"), false);
-    test(SV("abcde"), S(""), true);
-    test(SV("abcde"), S("abcde"), true);
-    test(SV("abcde"), S("abcdefghij"), false);
-    test(SV("abcde"), S("abcdefghijklmnopqrst"), false);
-    test(SV("abcdefghij"), S(""), true);
-    test(SV("abcdefghij"), S("abcde"), true);
-    test(SV("abcdefghij"), S("abcdefghij"), true);
-    test(SV("abcdefghij"), S("abcdefghijklmnopqrst"), false);
-    test(SV("abcdefghijklmnopqrst"), S(""), true);
-    test(SV("abcdefghijklmnopqrst"), S("abcde"), true);
-    test(SV("abcdefghijklmnopqrst"), S("abcdefghij"), true);
-    test(SV("abcdefghijklmnopqrst"), S("abcdefghijklmnopqrst"), true);
-  }
+  test_string<char, min_allocator>();
+  test_string<char, fancy_pointer_allocator>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string_oplt/pointer_string.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string_oplt/pointer_string.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string_oplt/pointer_string.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string_oplt/pointer_string.pass.cpp
@@ -16,6 +16,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -24,46 +25,31 @@
     assert((lhs < rhs) == x);
 }
 
+template <class S>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  test("", S(""), false);
+  test("", S("abcde"), true);
+  test("", S("abcdefghij"), true);
+  test("", S("abcdefghijklmnopqrst"), true);
+  test("abcde", S(""), false);
+  test("abcde", S("abcde"), false);
+  test("abcde", S("abcdefghij"), true);
+  test("abcde", S("abcdefghijklmnopqrst"), true);
+  test("abcdefghij", S(""), false);
+  test("abcdefghij", S("abcde"), false);
+  test("abcdefghij", S("abcdefghij"), false);
+  test("abcdefghij", S("abcdefghijklmnopqrst"), true);
+  test("abcdefghijklmnopqrst", S(""), false);
+  test("abcdefghijklmnopqrst", S("abcde"), false);
+  test("abcdefghijklmnopqrst", S("abcdefghij"), false);
+  test("abcdefghijklmnopqrst", S("abcdefghijklmnopqrst"), false);
+}
+
 TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    test("", S(""), false);
-    test("", S("abcde"), true);
-    test("", S("abcdefghij"), true);
-    test("", S("abcdefghijklmnopqrst"), true);
-    test("abcde", S(""), false);
-    test("abcde", S("abcde"), false);
-    test("abcde", S("abcdefghij"), true);
-    test("abcde", S("abcdefghijklmnopqrst"), true);
-    test("abcdefghij", S(""), false);
-    test("abcdefghij", S("abcde"), false);
-    test("abcdefghij", S("abcdefghij"), false);
-    test("abcdefghij", S("abcdefghijklmnopqrst"), true);
-    test("abcdefghijklmnopqrst", S(""), false);
-    test("abcdefghijklmnopqrst", S("abcde"), false);
-    test("abcdefghijklmnopqrst", S("abcdefghij"), false);
-    test("abcdefghijklmnopqrst", S("abcdefghijklmnopqrst"), false);
-  }
+  test_string<std::string>();
 #if TEST_STD_VER >= 11
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    test("", S(""), false);
-    test("", S("abcde"), true);
-    test("", S("abcdefghij"), true);
-    test("", S("abcdefghijklmnopqrst"), true);
-    test("abcde", S(""), false);
-    test("abcde", S("abcde"), false);
-    test("abcde", S("abcdefghij"), true);
-    test("abcde", S("abcdefghijklmnopqrst"), true);
-    test("abcdefghij", S(""), false);
-    test("abcdefghij", S("abcde"), false);
-    test("abcdefghij", S("abcdefghij"), false);
-    test("abcdefghij", S("abcdefghijklmnopqrst"), true);
-    test("abcdefghijklmnopqrst", S(""), false);
-    test("abcdefghijklmnopqrst", S("abcde"), false);
-    test("abcdefghijklmnopqrst", S("abcdefghij"), false);
-    test("abcdefghijklmnopqrst", S("abcdefghijklmnopqrst"), false);
-  }
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string_oplt/string_pointer.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string_oplt/string_pointer.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string_oplt/string_pointer.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string_oplt/string_pointer.pass.cpp
@@ -16,6 +16,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -24,46 +25,31 @@
     assert((lhs < rhs) == x);
 }
 
+template <class S>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  test(S(""), "", false);
+  test(S(""), "abcde", true);
+  test(S(""), "abcdefghij", true);
+  test(S(""), "abcdefghijklmnopqrst", true);
+  test(S("abcde"), "", false);
+  test(S("abcde"), "abcde", false);
+  test(S("abcde"), "abcdefghij", true);
+  test(S("abcde"), "abcdefghijklmnopqrst", true);
+  test(S("abcdefghij"), "", false);
+  test(S("abcdefghij"), "abcde", false);
+  test(S("abcdefghij"), "abcdefghij", false);
+  test(S("abcdefghij"), "abcdefghijklmnopqrst", true);
+  test(S("abcdefghijklmnopqrst"), "", false);
+  test(S("abcdefghijklmnopqrst"), "abcde", false);
+  test(S("abcdefghijklmnopqrst"), "abcdefghij", false);
+  test(S("abcdefghijklmnopqrst"), "abcdefghijklmnopqrst", false);
+}
+
 TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    test(S(""), "", false);
-    test(S(""), "abcde", true);
-    test(S(""), "abcdefghij", true);
-    test(S(""), "abcdefghijklmnopqrst", true);
-    test(S("abcde"), "", false);
-    test(S("abcde"), "abcde", false);
-    test(S("abcde"), "abcdefghij", true);
-    test(S("abcde"), "abcdefghijklmnopqrst", true);
-    test(S("abcdefghij"), "", false);
-    test(S("abcdefghij"), "abcde", false);
-    test(S("abcdefghij"), "abcdefghij", false);
-    test(S("abcdefghij"), "abcdefghijklmnopqrst", true);
-    test(S("abcdefghijklmnopqrst"), "", false);
-    test(S("abcdefghijklmnopqrst"), "abcde", false);
-    test(S("abcdefghijklmnopqrst"), "abcdefghij", false);
-    test(S("abcdefghijklmnopqrst"), "abcdefghijklmnopqrst", false);
-  }
+  test_string<std::string>();
 #if TEST_STD_VER >= 11
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    test(S(""), "", false);
-    test(S(""), "abcde", true);
-    test(S(""), "abcdefghij", true);
-    test(S(""), "abcdefghijklmnopqrst", true);
-    test(S("abcde"), "", false);
-    test(S("abcde"), "abcde", false);
-    test(S("abcde"), "abcdefghij", true);
-    test(S("abcde"), "abcdefghijklmnopqrst", true);
-    test(S("abcdefghij"), "", false);
-    test(S("abcdefghij"), "abcde", false);
-    test(S("abcdefghij"), "abcdefghij", false);
-    test(S("abcdefghij"), "abcdefghijklmnopqrst", true);
-    test(S("abcdefghijklmnopqrst"), "", false);
-    test(S("abcdefghijklmnopqrst"), "abcde", false);
-    test(S("abcdefghijklmnopqrst"), "abcdefghij", false);
-    test(S("abcdefghijklmnopqrst"), "abcdefghijklmnopqrst", false);
-  }
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string_oplt/string_string.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string_oplt/string_string.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string_oplt/string_string.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string_oplt/string_string.pass.cpp
@@ -17,6 +17,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -25,46 +26,31 @@
     assert((lhs < rhs) == x);
 }
 
+template <class S>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  test(S(""), S(""), false);
+  test(S(""), S("abcde"), true);
+  test(S(""), S("abcdefghij"), true);
+  test(S(""), S("abcdefghijklmnopqrst"), true);
+  test(S("abcde"), S(""), false);
+  test(S("abcde"), S("abcde"), false);
+  test(S("abcde"), S("abcdefghij"), true);
+  test(S("abcde"), S("abcdefghijklmnopqrst"), true);
+  test(S("abcdefghij"), S(""), false);
+  test(S("abcdefghij"), S("abcde"), false);
+  test(S("abcdefghij"), S("abcdefghij"), false);
+  test(S("abcdefghij"), S("abcdefghijklmnopqrst"), true);
+  test(S("abcdefghijklmnopqrst"), S(""), false);
+  test(S("abcdefghijklmnopqrst"), S("abcde"), false);
+  test(S("abcdefghijklmnopqrst"), S("abcdefghij"), false);
+  test(S("abcdefghijklmnopqrst"), S("abcdefghijklmnopqrst"), false);
+}
+
 TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    test(S(""), S(""), false);
-    test(S(""), S("abcde"), true);
-    test(S(""), S("abcdefghij"), true);
-    test(S(""), S("abcdefghijklmnopqrst"), true);
-    test(S("abcde"), S(""), false);
-    test(S("abcde"), S("abcde"), false);
-    test(S("abcde"), S("abcdefghij"), true);
-    test(S("abcde"), S("abcdefghijklmnopqrst"), true);
-    test(S("abcdefghij"), S(""), false);
-    test(S("abcdefghij"), S("abcde"), false);
-    test(S("abcdefghij"), S("abcdefghij"), false);
-    test(S("abcdefghij"), S("abcdefghijklmnopqrst"), true);
-    test(S("abcdefghijklmnopqrst"), S(""), false);
-    test(S("abcdefghijklmnopqrst"), S("abcde"), false);
-    test(S("abcdefghijklmnopqrst"), S("abcdefghij"), false);
-    test(S("abcdefghijklmnopqrst"), S("abcdefghijklmnopqrst"), false);
-  }
+  test_string<std::string>();
 #if TEST_STD_VER >= 11
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    test(S(""), S(""), false);
-    test(S(""), S("abcde"), true);
-    test(S(""), S("abcdefghij"), true);
-    test(S(""), S("abcdefghijklmnopqrst"), true);
-    test(S("abcde"), S(""), false);
-    test(S("abcde"), S("abcde"), false);
-    test(S("abcde"), S("abcdefghij"), true);
-    test(S("abcde"), S("abcdefghijklmnopqrst"), true);
-    test(S("abcdefghij"), S(""), false);
-    test(S("abcdefghij"), S("abcde"), false);
-    test(S("abcdefghij"), S("abcdefghij"), false);
-    test(S("abcdefghij"), S("abcdefghijklmnopqrst"), true);
-    test(S("abcdefghijklmnopqrst"), S(""), false);
-    test(S("abcdefghijklmnopqrst"), S("abcde"), false);
-    test(S("abcdefghijklmnopqrst"), S("abcdefghij"), false);
-    test(S("abcdefghijklmnopqrst"), S("abcdefghijklmnopqrst"), false);
-  }
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string_oplt/string_string_view.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string_oplt/string_string_view.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string_oplt/string_string_view.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string_oplt/string_string_view.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S, class SV>
 TEST_CONSTEXPR_CXX20 void
@@ -23,48 +24,33 @@
     assert((lhs < rhs) == x);
 }
 
+template <class CharT, template <class> class Alloc>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  using S  = std::basic_string<CharT, std::char_traits<CharT>, Alloc<CharT>>;
+  using SV = std::basic_string_view<CharT, std::char_traits<CharT>>;
+  test(S(""), SV(""), false);
+  test(S(""), SV("abcde"), true);
+  test(S(""), SV("abcdefghij"), true);
+  test(S(""), SV("abcdefghijklmnopqrst"), true);
+  test(S("abcde"), SV(""), false);
+  test(S("abcde"), SV("abcde"), false);
+  test(S("abcde"), SV("abcdefghij"), true);
+  test(S("abcde"), SV("abcdefghijklmnopqrst"), true);
+  test(S("abcdefghij"), SV(""), false);
+  test(S("abcdefghij"), SV("abcde"), false);
+  test(S("abcdefghij"), SV("abcdefghij"), false);
+  test(S("abcdefghij"), SV("abcdefghijklmnopqrst"), true);
+  test(S("abcdefghijklmnopqrst"), SV(""), false);
+  test(S("abcdefghijklmnopqrst"), SV("abcde"), false);
+  test(S("abcdefghijklmnopqrst"), SV("abcdefghij"), false);
+  test(S("abcdefghijklmnopqrst"), SV("abcdefghijklmnopqrst"), false);
+}
+
 TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    typedef std::string_view SV;
-    test(S(""), SV(""), false);
-    test(S(""), SV("abcde"), true);
-    test(S(""), SV("abcdefghij"), true);
-    test(S(""), SV("abcdefghijklmnopqrst"), true);
-    test(S("abcde"), SV(""), false);
-    test(S("abcde"), SV("abcde"), false);
-    test(S("abcde"), SV("abcdefghij"), true);
-    test(S("abcde"), SV("abcdefghijklmnopqrst"), true);
-    test(S("abcdefghij"), SV(""), false);
-    test(S("abcdefghij"), SV("abcde"), false);
-    test(S("abcdefghij"), SV("abcdefghij"), false);
-    test(S("abcdefghij"), SV("abcdefghijklmnopqrst"), true);
-    test(S("abcdefghijklmnopqrst"), SV(""), false);
-    test(S("abcdefghijklmnopqrst"), SV("abcde"), false);
-    test(S("abcdefghijklmnopqrst"), SV("abcdefghij"), false);
-    test(S("abcdefghijklmnopqrst"), SV("abcdefghijklmnopqrst"), false);
-  }
+  test_string<char, std::allocator>();
 #if TEST_STD_VER >= 11
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    typedef std::basic_string_view<char, std::char_traits<char>> SV;
-    test(S(""), SV(""), false);
-    test(S(""), SV("abcde"), true);
-    test(S(""), SV("abcdefghij"), true);
-    test(S(""), SV("abcdefghijklmnopqrst"), true);
-    test(S("abcde"), SV(""), false);
-    test(S("abcde"), SV("abcde"), false);
-    test(S("abcde"), SV("abcdefghij"), true);
-    test(S("abcde"), SV("abcdefghijklmnopqrst"), true);
-    test(S("abcdefghij"), SV(""), false);
-    test(S("abcdefghij"), SV("abcde"), false);
-    test(S("abcdefghij"), SV("abcdefghij"), false);
-    test(S("abcdefghij"), SV("abcdefghijklmnopqrst"), true);
-    test(S("abcdefghijklmnopqrst"), SV(""), false);
-    test(S("abcdefghijklmnopqrst"), SV("abcde"), false);
-    test(S("abcdefghijklmnopqrst"), SV("abcdefghij"), false);
-    test(S("abcdefghijklmnopqrst"), SV("abcdefghijklmnopqrst"), false);
-  }
+  test_string<char, min_allocator>();
+  test_string<char, fancy_pointer_allocator>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string_oplt/string_view_string.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string_oplt/string_view_string.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string_oplt/string_view_string.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string_oplt/string_view_string.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S, class SV>
 TEST_CONSTEXPR_CXX20 void
@@ -23,48 +24,33 @@
     assert((lhs < rhs) == x);
 }
 
+template <class CharT, template <class> class Alloc>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  using S  = std::basic_string<CharT, std::char_traits<CharT>, Alloc<CharT>>;
+  using SV = std::basic_string_view<CharT, std::char_traits<CharT>>;
+  test(SV(""), S(""), false);
+  test(SV(""), S("abcde"), true);
+  test(SV(""), S("abcdefghij"), true);
+  test(SV(""), S("abcdefghijklmnopqrst"), true);
+  test(SV("abcde"), S(""), false);
+  test(SV("abcde"), S("abcde"), false);
+  test(SV("abcde"), S("abcdefghij"), true);
+  test(SV("abcde"), S("abcdefghijklmnopqrst"), true);
+  test(SV("abcdefghij"), S(""), false);
+  test(SV("abcdefghij"), S("abcde"), false);
+  test(SV("abcdefghij"), S("abcdefghij"), false);
+  test(SV("abcdefghij"), S("abcdefghijklmnopqrst"), true);
+  test(SV("abcdefghijklmnopqrst"), S(""), false);
+  test(SV("abcdefghijklmnopqrst"), S("abcde"), false);
+  test(SV("abcdefghijklmnopqrst"), S("abcdefghij"), false);
+  test(SV("abcdefghijklmnopqrst"), S("abcdefghijklmnopqrst"), false);
+}
+
 TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    typedef std::string_view SV;
-    test(SV(""), S(""), false);
-    test(SV(""), S("abcde"), true);
-    test(SV(""), S("abcdefghij"), true);
-    test(SV(""), S("abcdefghijklmnopqrst"), true);
-    test(SV("abcde"), S(""), false);
-    test(SV("abcde"), S("abcde"), false);
-    test(SV("abcde"), S("abcdefghij"), true);
-    test(SV("abcde"), S("abcdefghijklmnopqrst"), true);
-    test(SV("abcdefghij"), S(""), false);
-    test(SV("abcdefghij"), S("abcde"), false);
-    test(SV("abcdefghij"), S("abcdefghij"), false);
-    test(SV("abcdefghij"), S("abcdefghijklmnopqrst"), true);
-    test(SV("abcdefghijklmnopqrst"), S(""), false);
-    test(SV("abcdefghijklmnopqrst"), S("abcde"), false);
-    test(SV("abcdefghijklmnopqrst"), S("abcdefghij"), false);
-    test(SV("abcdefghijklmnopqrst"), S("abcdefghijklmnopqrst"), false);
-  }
+  test_string<char, std::allocator>();
 #if TEST_STD_VER >= 11
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    typedef std::basic_string_view<char, std::char_traits<char>> SV;
-    test(SV(""), S(""), false);
-    test(SV(""), S("abcde"), true);
-    test(SV(""), S("abcdefghij"), true);
-    test(SV(""), S("abcdefghijklmnopqrst"), true);
-    test(SV("abcde"), S(""), false);
-    test(SV("abcde"), S("abcde"), false);
-    test(SV("abcde"), S("abcdefghij"), true);
-    test(SV("abcde"), S("abcdefghijklmnopqrst"), true);
-    test(SV("abcdefghij"), S(""), false);
-    test(SV("abcdefghij"), S("abcde"), false);
-    test(SV("abcdefghij"), S("abcdefghij"), false);
-    test(SV("abcdefghij"), S("abcdefghijklmnopqrst"), true);
-    test(SV("abcdefghijklmnopqrst"), S(""), false);
-    test(SV("abcdefghijklmnopqrst"), S("abcde"), false);
-    test(SV("abcdefghijklmnopqrst"), S("abcdefghij"), false);
-    test(SV("abcdefghijklmnopqrst"), S("abcdefghijklmnopqrst"), false);
-  }
+  test_string<char, min_allocator>();
+  test_string<char, fancy_pointer_allocator>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string_oplt=/pointer_string.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string_oplt=/pointer_string.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string_oplt=/pointer_string.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string_oplt=/pointer_string.pass.cpp
@@ -16,6 +16,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -24,46 +25,31 @@
     assert((lhs <= rhs) == x);
 }
 
+template <class S>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  test("", S(""), true);
+  test("", S("abcde"), true);
+  test("", S("abcdefghij"), true);
+  test("", S("abcdefghijklmnopqrst"), true);
+  test("abcde", S(""), false);
+  test("abcde", S("abcde"), true);
+  test("abcde", S("abcdefghij"), true);
+  test("abcde", S("abcdefghijklmnopqrst"), true);
+  test("abcdefghij", S(""), false);
+  test("abcdefghij", S("abcde"), false);
+  test("abcdefghij", S("abcdefghij"), true);
+  test("abcdefghij", S("abcdefghijklmnopqrst"), true);
+  test("abcdefghijklmnopqrst", S(""), false);
+  test("abcdefghijklmnopqrst", S("abcde"), false);
+  test("abcdefghijklmnopqrst", S("abcdefghij"), false);
+  test("abcdefghijklmnopqrst", S("abcdefghijklmnopqrst"), true);
+}
+
 TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    test("", S(""), true);
-    test("", S("abcde"), true);
-    test("", S("abcdefghij"), true);
-    test("", S("abcdefghijklmnopqrst"), true);
-    test("abcde", S(""), false);
-    test("abcde", S("abcde"), true);
-    test("abcde", S("abcdefghij"), true);
-    test("abcde", S("abcdefghijklmnopqrst"), true);
-    test("abcdefghij", S(""), false);
-    test("abcdefghij", S("abcde"), false);
-    test("abcdefghij", S("abcdefghij"), true);
-    test("abcdefghij", S("abcdefghijklmnopqrst"), true);
-    test("abcdefghijklmnopqrst", S(""), false);
-    test("abcdefghijklmnopqrst", S("abcde"), false);
-    test("abcdefghijklmnopqrst", S("abcdefghij"), false);
-    test("abcdefghijklmnopqrst", S("abcdefghijklmnopqrst"), true);
-  }
+  test_string<std::string>();
 #if TEST_STD_VER >= 11
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    test("", S(""), true);
-    test("", S("abcde"), true);
-    test("", S("abcdefghij"), true);
-    test("", S("abcdefghijklmnopqrst"), true);
-    test("abcde", S(""), false);
-    test("abcde", S("abcde"), true);
-    test("abcde", S("abcdefghij"), true);
-    test("abcde", S("abcdefghijklmnopqrst"), true);
-    test("abcdefghij", S(""), false);
-    test("abcdefghij", S("abcde"), false);
-    test("abcdefghij", S("abcdefghij"), true);
-    test("abcdefghij", S("abcdefghijklmnopqrst"), true);
-    test("abcdefghijklmnopqrst", S(""), false);
-    test("abcdefghijklmnopqrst", S("abcde"), false);
-    test("abcdefghijklmnopqrst", S("abcdefghij"), false);
-    test("abcdefghijklmnopqrst", S("abcdefghijklmnopqrst"), true);
-  }
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string_oplt=/string_pointer.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string_oplt=/string_pointer.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string_oplt=/string_pointer.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string_oplt=/string_pointer.pass.cpp
@@ -16,6 +16,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -24,46 +25,31 @@
     assert((lhs <= rhs) == x);
 }
 
+template <class S>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  test(S(""), "", true);
+  test(S(""), "abcde", true);
+  test(S(""), "abcdefghij", true);
+  test(S(""), "abcdefghijklmnopqrst", true);
+  test(S("abcde"), "", false);
+  test(S("abcde"), "abcde", true);
+  test(S("abcde"), "abcdefghij", true);
+  test(S("abcde"), "abcdefghijklmnopqrst", true);
+  test(S("abcdefghij"), "", false);
+  test(S("abcdefghij"), "abcde", false);
+  test(S("abcdefghij"), "abcdefghij", true);
+  test(S("abcdefghij"), "abcdefghijklmnopqrst", true);
+  test(S("abcdefghijklmnopqrst"), "", false);
+  test(S("abcdefghijklmnopqrst"), "abcde", false);
+  test(S("abcdefghijklmnopqrst"), "abcdefghij", false);
+  test(S("abcdefghijklmnopqrst"), "abcdefghijklmnopqrst", true);
+}
+
 TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    test(S(""), "", true);
-    test(S(""), "abcde", true);
-    test(S(""), "abcdefghij", true);
-    test(S(""), "abcdefghijklmnopqrst", true);
-    test(S("abcde"), "", false);
-    test(S("abcde"), "abcde", true);
-    test(S("abcde"), "abcdefghij", true);
-    test(S("abcde"), "abcdefghijklmnopqrst", true);
-    test(S("abcdefghij"), "", false);
-    test(S("abcdefghij"), "abcde", false);
-    test(S("abcdefghij"), "abcdefghij", true);
-    test(S("abcdefghij"), "abcdefghijklmnopqrst", true);
-    test(S("abcdefghijklmnopqrst"), "", false);
-    test(S("abcdefghijklmnopqrst"), "abcde", false);
-    test(S("abcdefghijklmnopqrst"), "abcdefghij", false);
-    test(S("abcdefghijklmnopqrst"), "abcdefghijklmnopqrst", true);
-  }
+  test_string<std::string>();
 #if TEST_STD_VER >= 11
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    test(S(""), "", true);
-    test(S(""), "abcde", true);
-    test(S(""), "abcdefghij", true);
-    test(S(""), "abcdefghijklmnopqrst", true);
-    test(S("abcde"), "", false);
-    test(S("abcde"), "abcde", true);
-    test(S("abcde"), "abcdefghij", true);
-    test(S("abcde"), "abcdefghijklmnopqrst", true);
-    test(S("abcdefghij"), "", false);
-    test(S("abcdefghij"), "abcde", false);
-    test(S("abcdefghij"), "abcdefghij", true);
-    test(S("abcdefghij"), "abcdefghijklmnopqrst", true);
-    test(S("abcdefghijklmnopqrst"), "", false);
-    test(S("abcdefghijklmnopqrst"), "abcde", false);
-    test(S("abcdefghijklmnopqrst"), "abcdefghij", false);
-    test(S("abcdefghijklmnopqrst"), "abcdefghijklmnopqrst", true);
-  }
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string_oplt=/string_string.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string_oplt=/string_string.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string_oplt=/string_string.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string_oplt=/string_string.pass.cpp
@@ -17,6 +17,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -25,46 +26,31 @@
     assert((lhs <= rhs) == x);
 }
 
+template <class S>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  test(S(""), S(""), true);
+  test(S(""), S("abcde"), true);
+  test(S(""), S("abcdefghij"), true);
+  test(S(""), S("abcdefghijklmnopqrst"), true);
+  test(S("abcde"), S(""), false);
+  test(S("abcde"), S("abcde"), true);
+  test(S("abcde"), S("abcdefghij"), true);
+  test(S("abcde"), S("abcdefghijklmnopqrst"), true);
+  test(S("abcdefghij"), S(""), false);
+  test(S("abcdefghij"), S("abcde"), false);
+  test(S("abcdefghij"), S("abcdefghij"), true);
+  test(S("abcdefghij"), S("abcdefghijklmnopqrst"), true);
+  test(S("abcdefghijklmnopqrst"), S(""), false);
+  test(S("abcdefghijklmnopqrst"), S("abcde"), false);
+  test(S("abcdefghijklmnopqrst"), S("abcdefghij"), false);
+  test(S("abcdefghijklmnopqrst"), S("abcdefghijklmnopqrst"), true);
+}
+
 TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    test(S(""), S(""), true);
-    test(S(""), S("abcde"), true);
-    test(S(""), S("abcdefghij"), true);
-    test(S(""), S("abcdefghijklmnopqrst"), true);
-    test(S("abcde"), S(""), false);
-    test(S("abcde"), S("abcde"), true);
-    test(S("abcde"), S("abcdefghij"), true);
-    test(S("abcde"), S("abcdefghijklmnopqrst"), true);
-    test(S("abcdefghij"), S(""), false);
-    test(S("abcdefghij"), S("abcde"), false);
-    test(S("abcdefghij"), S("abcdefghij"), true);
-    test(S("abcdefghij"), S("abcdefghijklmnopqrst"), true);
-    test(S("abcdefghijklmnopqrst"), S(""), false);
-    test(S("abcdefghijklmnopqrst"), S("abcde"), false);
-    test(S("abcdefghijklmnopqrst"), S("abcdefghij"), false);
-    test(S("abcdefghijklmnopqrst"), S("abcdefghijklmnopqrst"), true);
-  }
+  test_string<std::string>();
 #if TEST_STD_VER >= 11
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    test(S(""), S(""), true);
-    test(S(""), S("abcde"), true);
-    test(S(""), S("abcdefghij"), true);
-    test(S(""), S("abcdefghijklmnopqrst"), true);
-    test(S("abcde"), S(""), false);
-    test(S("abcde"), S("abcde"), true);
-    test(S("abcde"), S("abcdefghij"), true);
-    test(S("abcde"), S("abcdefghijklmnopqrst"), true);
-    test(S("abcdefghij"), S(""), false);
-    test(S("abcdefghij"), S("abcde"), false);
-    test(S("abcdefghij"), S("abcdefghij"), true);
-    test(S("abcdefghij"), S("abcdefghijklmnopqrst"), true);
-    test(S("abcdefghijklmnopqrst"), S(""), false);
-    test(S("abcdefghijklmnopqrst"), S("abcde"), false);
-    test(S("abcdefghijklmnopqrst"), S("abcdefghij"), false);
-    test(S("abcdefghijklmnopqrst"), S("abcdefghijklmnopqrst"), true);
-  }
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string_oplt=/string_string_view.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string_oplt=/string_string_view.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string_oplt=/string_string_view.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string_oplt=/string_string_view.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S, class SV>
 TEST_CONSTEXPR_CXX20 void
@@ -23,48 +24,33 @@
     assert((lhs <= rhs) == x);
 }
 
+template <class CharT, template <class> class Alloc>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  using S  = std::basic_string<CharT, std::char_traits<CharT>, Alloc<CharT>>;
+  using SV = std::basic_string_view<CharT, std::char_traits<CharT>>;
+  test(S(""), SV(""), true);
+  test(S(""), SV("abcde"), true);
+  test(S(""), SV("abcdefghij"), true);
+  test(S(""), SV("abcdefghijklmnopqrst"), true);
+  test(S("abcde"), SV(""), false);
+  test(S("abcde"), SV("abcde"), true);
+  test(S("abcde"), SV("abcdefghij"), true);
+  test(S("abcde"), SV("abcdefghijklmnopqrst"), true);
+  test(S("abcdefghij"), SV(""), false);
+  test(S("abcdefghij"), SV("abcde"), false);
+  test(S("abcdefghij"), SV("abcdefghij"), true);
+  test(S("abcdefghij"), SV("abcdefghijklmnopqrst"), true);
+  test(S("abcdefghijklmnopqrst"), SV(""), false);
+  test(S("abcdefghijklmnopqrst"), SV("abcde"), false);
+  test(S("abcdefghijklmnopqrst"), SV("abcdefghij"), false);
+  test(S("abcdefghijklmnopqrst"), SV("abcdefghijklmnopqrst"), true);
+}
+
 TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    typedef std::string_view SV;
-    test(S(""), SV(""), true);
-    test(S(""), SV("abcde"), true);
-    test(S(""), SV("abcdefghij"), true);
-    test(S(""), SV("abcdefghijklmnopqrst"), true);
-    test(S("abcde"), SV(""), false);
-    test(S("abcde"), SV("abcde"), true);
-    test(S("abcde"), SV("abcdefghij"), true);
-    test(S("abcde"), SV("abcdefghijklmnopqrst"), true);
-    test(S("abcdefghij"), SV(""), false);
-    test(S("abcdefghij"), SV("abcde"), false);
-    test(S("abcdefghij"), SV("abcdefghij"), true);
-    test(S("abcdefghij"), SV("abcdefghijklmnopqrst"), true);
-    test(S("abcdefghijklmnopqrst"), SV(""), false);
-    test(S("abcdefghijklmnopqrst"), SV("abcde"), false);
-    test(S("abcdefghijklmnopqrst"), SV("abcdefghij"), false);
-    test(S("abcdefghijklmnopqrst"), SV("abcdefghijklmnopqrst"), true);
-  }
+  test_string<char, std::allocator>();
 #if TEST_STD_VER >= 11
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    typedef std::basic_string_view<char, std::char_traits<char>> SV;
-    test(S(""), SV(""), true);
-    test(S(""), SV("abcde"), true);
-    test(S(""), SV("abcdefghij"), true);
-    test(S(""), SV("abcdefghijklmnopqrst"), true);
-    test(S("abcde"), SV(""), false);
-    test(S("abcde"), SV("abcde"), true);
-    test(S("abcde"), SV("abcdefghij"), true);
-    test(S("abcde"), SV("abcdefghijklmnopqrst"), true);
-    test(S("abcdefghij"), SV(""), false);
-    test(S("abcdefghij"), SV("abcde"), false);
-    test(S("abcdefghij"), SV("abcdefghij"), true);
-    test(S("abcdefghij"), SV("abcdefghijklmnopqrst"), true);
-    test(S("abcdefghijklmnopqrst"), SV(""), false);
-    test(S("abcdefghijklmnopqrst"), SV("abcde"), false);
-    test(S("abcdefghijklmnopqrst"), SV("abcdefghij"), false);
-    test(S("abcdefghijklmnopqrst"), SV("abcdefghijklmnopqrst"), true);
-  }
+  test_string<char, min_allocator>();
+  test_string<char, fancy_pointer_allocator>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string_oplt=/string_view_string.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string_oplt=/string_view_string.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string_oplt=/string_view_string.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string_oplt=/string_view_string.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S, class SV>
 TEST_CONSTEXPR_CXX20 void
@@ -23,48 +24,33 @@
     assert((lhs <= rhs) == x);
 }
 
+template <class CharT, template <class> class Alloc>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  using S  = std::basic_string<CharT, std::char_traits<CharT>, Alloc<CharT>>;
+  using SV = std::basic_string_view<CharT, std::char_traits<CharT>>;
+  test(SV(""), S(""), true);
+  test(SV(""), S("abcde"), true);
+  test(SV(""), S("abcdefghij"), true);
+  test(SV(""), S("abcdefghijklmnopqrst"), true);
+  test(SV("abcde"), S(""), false);
+  test(SV("abcde"), S("abcde"), true);
+  test(SV("abcde"), S("abcdefghij"), true);
+  test(SV("abcde"), S("abcdefghijklmnopqrst"), true);
+  test(SV("abcdefghij"), S(""), false);
+  test(SV("abcdefghij"), S("abcde"), false);
+  test(SV("abcdefghij"), S("abcdefghij"), true);
+  test(SV("abcdefghij"), S("abcdefghijklmnopqrst"), true);
+  test(SV("abcdefghijklmnopqrst"), S(""), false);
+  test(SV("abcdefghijklmnopqrst"), S("abcde"), false);
+  test(SV("abcdefghijklmnopqrst"), S("abcdefghij"), false);
+  test(SV("abcdefghijklmnopqrst"), S("abcdefghijklmnopqrst"), true);
+}
+
 TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    typedef std::string_view SV;
-    test(SV(""), S(""), true);
-    test(SV(""), S("abcde"), true);
-    test(SV(""), S("abcdefghij"), true);
-    test(SV(""), S("abcdefghijklmnopqrst"), true);
-    test(SV("abcde"), S(""), false);
-    test(SV("abcde"), S("abcde"), true);
-    test(SV("abcde"), S("abcdefghij"), true);
-    test(SV("abcde"), S("abcdefghijklmnopqrst"), true);
-    test(SV("abcdefghij"), S(""), false);
-    test(SV("abcdefghij"), S("abcde"), false);
-    test(SV("abcdefghij"), S("abcdefghij"), true);
-    test(SV("abcdefghij"), S("abcdefghijklmnopqrst"), true);
-    test(SV("abcdefghijklmnopqrst"), S(""), false);
-    test(SV("abcdefghijklmnopqrst"), S("abcde"), false);
-    test(SV("abcdefghijklmnopqrst"), S("abcdefghij"), false);
-    test(SV("abcdefghijklmnopqrst"), S("abcdefghijklmnopqrst"), true);
-  }
+  test_string<char, std::allocator>();
 #if TEST_STD_VER >= 11
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    typedef std::basic_string_view<char, std::char_traits<char>> SV;
-    test(SV(""), S(""), true);
-    test(SV(""), S("abcde"), true);
-    test(SV(""), S("abcdefghij"), true);
-    test(SV(""), S("abcdefghijklmnopqrst"), true);
-    test(SV("abcde"), S(""), false);
-    test(SV("abcde"), S("abcde"), true);
-    test(SV("abcde"), S("abcdefghij"), true);
-    test(SV("abcde"), S("abcdefghijklmnopqrst"), true);
-    test(SV("abcdefghij"), S(""), false);
-    test(SV("abcdefghij"), S("abcde"), false);
-    test(SV("abcdefghij"), S("abcdefghij"), true);
-    test(SV("abcdefghij"), S("abcdefghijklmnopqrst"), true);
-    test(SV("abcdefghijklmnopqrst"), S(""), false);
-    test(SV("abcdefghijklmnopqrst"), S("abcde"), false);
-    test(SV("abcdefghijklmnopqrst"), S("abcdefghij"), false);
-    test(SV("abcdefghijklmnopqrst"), S("abcdefghijklmnopqrst"), true);
-  }
+  test_string<char, min_allocator>();
+  test_string<char, fancy_pointer_allocator>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string.accessors/c_str.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string.accessors/c_str.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.ops/string.accessors/c_str.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string.accessors/c_str.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -31,22 +32,19 @@
         assert(T::eq(str[0], typename S::value_type()));
 }
 
+template <class S>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  test(S(""));
+  test(S("abcde"));
+  test(S("abcdefghij"));
+  test(S("abcdefghijklmnopqrst"));
+}
+
 TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    test(S(""));
-    test(S("abcde"));
-    test(S("abcdefghij"));
-    test(S("abcdefghijklmnopqrst"));
-  }
+  test_string<std::string>();
 #if TEST_STD_VER >= 11
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    test(S(""));
-    test(S("abcde"));
-    test(S("abcdefghij"));
-    test(S("abcdefghijklmnopqrst"));
-  }
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string.accessors/data.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string.accessors/data.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.ops/string.accessors/data.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string.accessors/data.pass.cpp
@@ -16,6 +16,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -47,32 +48,32 @@
         assert(T::eq(str[0], typename S::value_type()));
 }
 
-TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    test_const(S(""));
-    test_const(S("abcde"));
-    test_const(S("abcdefghij"));
-    test_const(S("abcdefghijklmnopqrst"));
-  }
-#if TEST_STD_VER >= 11
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    test_const(S(""));
-    test_const(S("abcde"));
-    test_const(S("abcdefghij"));
-    test_const(S("abcdefghijklmnopqrst"));
-  }
-#endif
+template <class S>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  test_const(S(""));
+  test_const(S("abcde"));
+  test_const(S("abcdefghij"));
+  test_const(S("abcdefghijklmnopqrst"));
 #if TEST_STD_VER > 14
   {
-    typedef std::string S;
-    S s1("");                     test_nonconst(s1);
-    S s2("abcde");                test_nonconst(s2);
-    S s3("abcdefghij");           test_nonconst(s3);
-    S s4("abcdefghijklmnopqrst"); test_nonconst(s4);
+    S s1("");
+    test_nonconst(s1);
+    S s2("abcde");
+    test_nonconst(s2);
+    S s3("abcdefghij");
+    test_nonconst(s3);
+    S s4("abcdefghijklmnopqrst");
+    test_nonconst(s4);
   }
 #endif
+}
+
+TEST_CONSTEXPR_CXX20 bool test() {
+  test_string<std::string>();
+#if TEST_STD_VER >= 11
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
+#endif
 
   return true;
 }
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string.accessors/get_allocator.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string.accessors/get_allocator.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.ops/string.accessors/get_allocator.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string.accessors/get_allocator.pass.cpp
@@ -24,24 +24,32 @@
     assert(s.get_allocator() == a);
 }
 
+template <class CharT, template <class> class Alloc>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  using A = test_allocator<char>;
+  using S = std::basic_string<char, std::char_traits<char>, A>;
+  test(S(""), A());
+  test(S("abcde", A()), A());
+  test(S("abcdefghij", A()), A());
+  test(S("abcdefghijklmnopqrst", A()), A());
+}
+
+template <>
+TEST_CONSTEXPR_CXX20 void test_string<char, test_allocator>() {
+  using A = test_allocator<char>;
+  using S = std::basic_string<char, std::char_traits<char>, A>;
+  test(S(""), A());
+  test(S("abcde", A(1)), A(1));
+  test(S("abcdefghij", A(2)), A(2));
+  test(S("abcdefghijklmnopqrst", A(3)), A(3));
+}
+
 TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef test_allocator<char> A;
-    typedef std::basic_string<char, std::char_traits<char>, A> S;
-    test(S(""), A());
-    test(S("abcde", A(1)), A(1));
-    test(S("abcdefghij", A(2)), A(2));
-    test(S("abcdefghijklmnopqrst", A(3)), A(3));
-  }
+  test_string<char, std::allocator>();
+  test_string<char, test_allocator>();
 #if TEST_STD_VER >= 11
-  {
-    typedef min_allocator<char> A;
-    typedef std::basic_string<char, std::char_traits<char>, A> S;
-    test(S(""), A());
-    test(S("abcde", A()), A());
-    test(S("abcdefghij", A()), A());
-    test(S("abcdefghijklmnopqrst", A()), A());
-  }
+  test_string<char, min_allocator>();
+  test_string<char, fancy_pointer_allocator>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_compare/pointer.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_compare/pointer.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.ops/string_compare/pointer.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_compare/pointer.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 TEST_CONSTEXPR_CXX20 int sign(int x)
 {
@@ -33,46 +34,31 @@
     assert(sign(s.compare(str)) == sign(x));
 }
 
+template <class S>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  test(S(""), "", 0);
+  test(S(""), "abcde", -5);
+  test(S(""), "abcdefghij", -10);
+  test(S(""), "abcdefghijklmnopqrst", -20);
+  test(S("abcde"), "", 5);
+  test(S("abcde"), "abcde", 0);
+  test(S("abcde"), "abcdefghij", -5);
+  test(S("abcde"), "abcdefghijklmnopqrst", -15);
+  test(S("abcdefghij"), "", 10);
+  test(S("abcdefghij"), "abcde", 5);
+  test(S("abcdefghij"), "abcdefghij", 0);
+  test(S("abcdefghij"), "abcdefghijklmnopqrst", -10);
+  test(S("abcdefghijklmnopqrst"), "", 20);
+  test(S("abcdefghijklmnopqrst"), "abcde", 15);
+  test(S("abcdefghijklmnopqrst"), "abcdefghij", 10);
+  test(S("abcdefghijklmnopqrst"), "abcdefghijklmnopqrst", 0);
+}
+
 TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    test(S(""), "", 0);
-    test(S(""), "abcde", -5);
-    test(S(""), "abcdefghij", -10);
-    test(S(""), "abcdefghijklmnopqrst", -20);
-    test(S("abcde"), "", 5);
-    test(S("abcde"), "abcde", 0);
-    test(S("abcde"), "abcdefghij", -5);
-    test(S("abcde"), "abcdefghijklmnopqrst", -15);
-    test(S("abcdefghij"), "", 10);
-    test(S("abcdefghij"), "abcde", 5);
-    test(S("abcdefghij"), "abcdefghij", 0);
-    test(S("abcdefghij"), "abcdefghijklmnopqrst", -10);
-    test(S("abcdefghijklmnopqrst"), "", 20);
-    test(S("abcdefghijklmnopqrst"), "abcde", 15);
-    test(S("abcdefghijklmnopqrst"), "abcdefghij", 10);
-    test(S("abcdefghijklmnopqrst"), "abcdefghijklmnopqrst", 0);
-  }
+  test_string<std::string>();
 #if TEST_STD_VER >= 11
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    test(S(""), "", 0);
-    test(S(""), "abcde", -5);
-    test(S(""), "abcdefghij", -10);
-    test(S(""), "abcdefghijklmnopqrst", -20);
-    test(S("abcde"), "", 5);
-    test(S("abcde"), "abcde", 0);
-    test(S("abcde"), "abcdefghij", -5);
-    test(S("abcde"), "abcdefghijklmnopqrst", -15);
-    test(S("abcdefghij"), "", 10);
-    test(S("abcdefghij"), "abcde", 5);
-    test(S("abcdefghij"), "abcdefghij", 0);
-    test(S("abcdefghij"), "abcdefghijklmnopqrst", -10);
-    test(S("abcdefghijklmnopqrst"), "", 20);
-    test(S("abcdefghijklmnopqrst"), "abcde", 15);
-    test(S("abcdefghijklmnopqrst"), "abcdefghij", 10);
-    test(S("abcdefghijklmnopqrst"), "abcdefghijklmnopqrst", 0);
-  }
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_compare/size_size_T_size_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_compare/size_size_T_size_size.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.ops/string_compare/size_size_T_size_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_compare/size_size_T_size_size.pass.cpp
@@ -19,6 +19,7 @@
 #include <cassert>
 
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 #include "test_macros.h"
 
@@ -5979,8 +5980,11 @@
   return true;
 }
 
-template <class S, class SV>
+template <class CharT, template <class> class Alloc>
 void test() {
+  using S  = std::basic_string<CharT, std::char_traits<CharT>, Alloc<CharT>>;
+  using SV = std::basic_string_view<CharT, std::char_traits<CharT>>;
+
   test0<S, SV>();
   test1<S, SV>();
   test2<S, SV>();
@@ -6102,10 +6106,10 @@
 
 int main(int, char**)
 {
-  test<std::string, std::string_view>();
+  test<char, std::allocator>();
 #if TEST_STD_VER >= 11
-  test<std::basic_string<char, std::char_traits<char>, min_allocator<char>>,
-       std::basic_string_view<char, std::char_traits<char>>>();
+  test<char, min_allocator>();
+  test<char, fancy_pointer_allocator>();
 #endif
 
   return 0;
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_compare/size_size_pointer.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_compare/size_size_pointer.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.ops/string_compare/size_size_pointer.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_compare/size_size_pointer.pass.cpp
@@ -15,6 +15,7 @@
 #include <cassert>
 
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 #include "test_macros.h"
 
@@ -361,20 +362,18 @@
     test(S("abcdefghijklmnopqrst"), 21, 0, "abcdefghijklmnopqrst", 0);
 }
 
+template <class S>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  test0<S>();
+  test1<S>();
+  test2<S>();
+}
+
 TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    test0<S>();
-    test1<S>();
-    test2<S>();
-  }
+  test_string<std::string>();
 #if TEST_STD_VER >= 11
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    test0<S>();
-    test1<S>();
-    test2<S>();
-  }
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_compare/size_size_pointer_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_compare/size_size_pointer_size.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.ops/string_compare/size_size_pointer_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_compare/size_size_pointer_size.pass.cpp
@@ -15,6 +15,7 @@
 #include <cassert>
 
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 #include "test_macros.h"
 
@@ -1354,6 +1355,7 @@
   test<std::string>();
 #if TEST_STD_VER >= 11
   test<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return 0;
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_compare/size_size_string.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_compare/size_size_string.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.ops/string_compare/size_size_string.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_compare/size_size_string.pass.cpp
@@ -16,6 +16,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 TEST_CONSTEXPR_CXX20 int sign(int x)
 {
@@ -360,29 +361,23 @@
     test(S("abcdefghijklmnopqrst"), 21, 0, S("abcdefghijklmnopqrst"), 0);
 }
 
-TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    test0<S>();
-    test1<S>();
-    test2<S>();
-  }
-#if TEST_STD_VER >= 11
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    test0<S>();
-    test1<S>();
-    test2<S>();
-  }
-#endif
+template <class S>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  test0<S>();
+  test1<S>();
+  test2<S>();
+}
 
+TEST_CONSTEXPR_CXX20 bool test() {
+  test_string<std::string>();
 #if TEST_STD_VER >= 11
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
   { // LWG 2946
     std::string s = " !";
     assert(s.compare(0, 1, {"abc", 1}) < 0);
   }
 #endif
-
   return true;
 }
 
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_compare/size_size_string_size_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_compare/size_size_string_size_size.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.ops/string_compare/size_size_string_size_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_compare/size_size_string_size_size.pass.cpp
@@ -17,6 +17,7 @@
 #include <cassert>
 
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 #include "test_macros.h"
 
@@ -6072,6 +6073,7 @@
   test<std::string>();
 #if TEST_STD_VER >= 11
   test<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return 0;
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_compare/size_size_string_view.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_compare/size_size_string_view.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.ops/string_compare/size_size_string_view.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_compare/size_size_string_view.pass.cpp
@@ -15,6 +15,7 @@
 #include <cassert>
 
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 #include "test_macros.h"
 
@@ -361,22 +362,21 @@
     test(S("abcdefghijklmnopqrst"), 21, 0, SV("abcdefghijklmnopqrst"), 0);
 }
 
+template <class CharT, template <class> class Alloc>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  using S  = std::basic_string<CharT, std::char_traits<CharT>, Alloc<CharT>>;
+  using SV = std::basic_string_view<CharT, std::char_traits<CharT>>;
+
+  test0<S, SV>();
+  test1<S, SV>();
+  test2<S, SV>();
+}
+
 TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    typedef std::string_view SV;
-    test0<S, SV>();
-    test1<S, SV>();
-    test2<S, SV>();
-  }
+  test_string<char, std::allocator>();
 #if TEST_STD_VER >= 11
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    typedef std::string_view SV;
-    test0<S, SV>();
-    test1<S, SV>();
-    test2<S, SV>();
-  }
+  test_string<char, min_allocator>();
+  test_string<char, fancy_pointer_allocator>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_compare/string.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_compare/string.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.ops/string_compare/string.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_compare/string.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 TEST_CONSTEXPR_CXX20 int sign(int x)
 {
@@ -33,49 +34,31 @@
     assert(sign(s.compare(str)) == sign(x));
 }
 
-TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    test(S(""), S(""), 0);
-    test(S(""), S("abcde"), -5);
-    test(S(""), S("abcdefghij"), -10);
-    test(S(""), S("abcdefghijklmnopqrst"), -20);
-    test(S("abcde"), S(""), 5);
-    test(S("abcde"), S("abcde"), 0);
-    test(S("abcde"), S("abcdefghij"), -5);
-    test(S("abcde"), S("abcdefghijklmnopqrst"), -15);
-    test(S("abcdefghij"), S(""), 10);
-    test(S("abcdefghij"), S("abcde"), 5);
-    test(S("abcdefghij"), S("abcdefghij"), 0);
-    test(S("abcdefghij"), S("abcdefghijklmnopqrst"), -10);
-    test(S("abcdefghijklmnopqrst"), S(""), 20);
-    test(S("abcdefghijklmnopqrst"), S("abcde"), 15);
-    test(S("abcdefghijklmnopqrst"), S("abcdefghij"), 10);
-    test(S("abcdefghijklmnopqrst"), S("abcdefghijklmnopqrst"), 0);
-  }
-#if TEST_STD_VER >= 11
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    test(S(""), S(""), 0);
-    test(S(""), S("abcde"), -5);
-    test(S(""), S("abcdefghij"), -10);
-    test(S(""), S("abcdefghijklmnopqrst"), -20);
-    test(S("abcde"), S(""), 5);
-    test(S("abcde"), S("abcde"), 0);
-    test(S("abcde"), S("abcdefghij"), -5);
-    test(S("abcde"), S("abcdefghijklmnopqrst"), -15);
-    test(S("abcdefghij"), S(""), 10);
-    test(S("abcdefghij"), S("abcde"), 5);
-    test(S("abcdefghij"), S("abcdefghij"), 0);
-    test(S("abcdefghij"), S("abcdefghijklmnopqrst"), -10);
-    test(S("abcdefghijklmnopqrst"), S(""), 20);
-    test(S("abcdefghijklmnopqrst"), S("abcde"), 15);
-    test(S("abcdefghijklmnopqrst"), S("abcdefghij"), 10);
-    test(S("abcdefghijklmnopqrst"), S("abcdefghijklmnopqrst"), 0);
-  }
-#endif
+template <class S>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  test(S(""), S(""), 0);
+  test(S(""), S("abcde"), -5);
+  test(S(""), S("abcdefghij"), -10);
+  test(S(""), S("abcdefghijklmnopqrst"), -20);
+  test(S("abcde"), S(""), 5);
+  test(S("abcde"), S("abcde"), 0);
+  test(S("abcde"), S("abcdefghij"), -5);
+  test(S("abcde"), S("abcdefghijklmnopqrst"), -15);
+  test(S("abcdefghij"), S(""), 10);
+  test(S("abcdefghij"), S("abcde"), 5);
+  test(S("abcdefghij"), S("abcdefghij"), 0);
+  test(S("abcdefghij"), S("abcdefghijklmnopqrst"), -10);
+  test(S("abcdefghijklmnopqrst"), S(""), 20);
+  test(S("abcdefghijklmnopqrst"), S("abcde"), 15);
+  test(S("abcdefghijklmnopqrst"), S("abcdefghij"), 10);
+  test(S("abcdefghijklmnopqrst"), S("abcdefghijklmnopqrst"), 0);
+}
 
+TEST_CONSTEXPR_CXX20 bool test() {
+  test_string<std::string>();
 #if TEST_STD_VER >= 11
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
   { // LWG 2946
     std::string s = " !";
     assert(s.compare({"abc", 1}) < 0);
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_compare/string_view.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_compare/string_view.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.ops/string_compare/string_view.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_compare/string_view.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 TEST_CONSTEXPR_CXX20 int sign(int x)
 {
@@ -33,48 +34,34 @@
     assert(sign(s.compare(sv)) == sign(x));
 }
 
+template <class CharT, template <class> class Alloc>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  using S  = std::basic_string<CharT, std::char_traits<CharT>, Alloc<CharT>>;
+  using SV = std::basic_string_view<CharT, std::char_traits<CharT>>;
+
+  test(S(""), SV(""), 0);
+  test(S(""), SV("abcde"), -5);
+  test(S(""), SV("abcdefghij"), -10);
+  test(S(""), SV("abcdefghijklmnopqrst"), -20);
+  test(S("abcde"), SV(""), 5);
+  test(S("abcde"), SV("abcde"), 0);
+  test(S("abcde"), SV("abcdefghij"), -5);
+  test(S("abcde"), SV("abcdefghijklmnopqrst"), -15);
+  test(S("abcdefghij"), SV(""), 10);
+  test(S("abcdefghij"), SV("abcde"), 5);
+  test(S("abcdefghij"), SV("abcdefghij"), 0);
+  test(S("abcdefghij"), SV("abcdefghijklmnopqrst"), -10);
+  test(S("abcdefghijklmnopqrst"), SV(""), 20);
+  test(S("abcdefghijklmnopqrst"), SV("abcde"), 15);
+  test(S("abcdefghijklmnopqrst"), SV("abcdefghij"), 10);
+  test(S("abcdefghijklmnopqrst"), SV("abcdefghijklmnopqrst"), 0);
+}
+
 TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    typedef std::string_view SV;
-    test(S(""), SV(""), 0);
-    test(S(""), SV("abcde"), -5);
-    test(S(""), SV("abcdefghij"), -10);
-    test(S(""), SV("abcdefghijklmnopqrst"), -20);
-    test(S("abcde"), SV(""), 5);
-    test(S("abcde"), SV("abcde"), 0);
-    test(S("abcde"), SV("abcdefghij"), -5);
-    test(S("abcde"), SV("abcdefghijklmnopqrst"), -15);
-    test(S("abcdefghij"), SV(""), 10);
-    test(S("abcdefghij"), SV("abcde"), 5);
-    test(S("abcdefghij"), SV("abcdefghij"), 0);
-    test(S("abcdefghij"), SV("abcdefghijklmnopqrst"), -10);
-    test(S("abcdefghijklmnopqrst"), SV(""), 20);
-    test(S("abcdefghijklmnopqrst"), SV("abcde"), 15);
-    test(S("abcdefghijklmnopqrst"), SV("abcdefghij"), 10);
-    test(S("abcdefghijklmnopqrst"), SV("abcdefghijklmnopqrst"), 0);
-  }
+  test_string<char, std::allocator>();
 #if TEST_STD_VER >= 11
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    typedef std::string_view SV;
-    test(S(""), SV(""), 0);
-    test(S(""), SV("abcde"), -5);
-    test(S(""), SV("abcdefghij"), -10);
-    test(S(""), SV("abcdefghijklmnopqrst"), -20);
-    test(S("abcde"), SV(""), 5);
-    test(S("abcde"), SV("abcde"), 0);
-    test(S("abcde"), SV("abcdefghij"), -5);
-    test(S("abcde"), SV("abcdefghijklmnopqrst"), -15);
-    test(S("abcdefghij"), SV(""), 10);
-    test(S("abcdefghij"), SV("abcde"), 5);
-    test(S("abcdefghij"), SV("abcdefghij"), 0);
-    test(S("abcdefghij"), SV("abcdefghijklmnopqrst"), -10);
-    test(S("abcdefghijklmnopqrst"), SV(""), 20);
-    test(S("abcdefghijklmnopqrst"), SV("abcde"), 15);
-    test(S("abcdefghijklmnopqrst"), SV("abcdefghij"), 10);
-    test(S("abcdefghijklmnopqrst"), SV("abcdefghijklmnopqrst"), 0);
-  }
+  test_string<char, min_allocator>();
+  test_string<char, fancy_pointer_allocator>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_find.first.not.of/char_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_find.first.not.of/char_size.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.ops/string_find.first.not.of/char_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_find.first.not.of/char_size.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -37,68 +38,42 @@
         assert(x < s.size());
 }
 
-TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    test(S(""), 'q', 0, S::npos);
-    test(S(""), 'q', 1, S::npos);
-    test(S("kitcj"), 'q', 0, 0);
-    test(S("qkamf"), 'q', 1, 1);
-    test(S("nhmko"), 'q', 2, 2);
-    test(S("tpsaf"), 'q', 4, 4);
-    test(S("lahfb"), 'q', 5, S::npos);
-    test(S("irkhs"), 'q', 6, S::npos);
-    test(S("gmfhdaipsr"), 'q', 0, 0);
-    test(S("kantesmpgj"), 'q', 1, 1);
-    test(S("odaftiegpm"), 'q', 5, 5);
-    test(S("oknlrstdpi"), 'q', 9, 9);
-    test(S("eolhfgpjqk"), 'q', 10, S::npos);
-    test(S("pcdrofikas"), 'q', 11, S::npos);
-    test(S("nbatdlmekrgcfqsophij"), 'q', 0, 0);
-    test(S("bnrpehidofmqtcksjgla"), 'q', 1, 1);
-    test(S("jdmciepkaqgotsrfnhlb"), 'q', 10, 10);
-    test(S("jtdaefblsokrmhpgcnqi"), 'q', 19, 19);
-    test(S("hkbgspofltajcnedqmri"), 'q', 20, S::npos);
-    test(S("oselktgbcapndfjihrmq"), 'q', 21, S::npos);
+template <class S>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  test(S(""), 'q', 0, S::npos);
+  test(S(""), 'q', 1, S::npos);
+  test(S("kitcj"), 'q', 0, 0);
+  test(S("qkamf"), 'q', 1, 1);
+  test(S("nhmko"), 'q', 2, 2);
+  test(S("tpsaf"), 'q', 4, 4);
+  test(S("lahfb"), 'q', 5, S::npos);
+  test(S("irkhs"), 'q', 6, S::npos);
+  test(S("gmfhdaipsr"), 'q', 0, 0);
+  test(S("kantesmpgj"), 'q', 1, 1);
+  test(S("odaftiegpm"), 'q', 5, 5);
+  test(S("oknlrstdpi"), 'q', 9, 9);
+  test(S("eolhfgpjqk"), 'q', 10, S::npos);
+  test(S("pcdrofikas"), 'q', 11, S::npos);
+  test(S("nbatdlmekrgcfqsophij"), 'q', 0, 0);
+  test(S("bnrpehidofmqtcksjgla"), 'q', 1, 1);
+  test(S("jdmciepkaqgotsrfnhlb"), 'q', 10, 10);
+  test(S("jtdaefblsokrmhpgcnqi"), 'q', 19, 19);
+  test(S("hkbgspofltajcnedqmri"), 'q', 20, S::npos);
+  test(S("oselktgbcapndfjihrmq"), 'q', 21, S::npos);
 
-    test(S(""), 'q', S::npos);
-    test(S("q"), 'q', S::npos);
-    test(S("qqq"), 'q', S::npos);
-    test(S("csope"), 'q', 0);
-    test(S("gfsmthlkon"), 'q', 0);
-    test(S("laenfsbridchgotmkqpj"), 'q', 0);
-  }
-#if TEST_STD_VER >= 11
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    test(S(""), 'q', 0, S::npos);
-    test(S(""), 'q', 1, S::npos);
-    test(S("kitcj"), 'q', 0, 0);
-    test(S("qkamf"), 'q', 1, 1);
-    test(S("nhmko"), 'q', 2, 2);
-    test(S("tpsaf"), 'q', 4, 4);
-    test(S("lahfb"), 'q', 5, S::npos);
-    test(S("irkhs"), 'q', 6, S::npos);
-    test(S("gmfhdaipsr"), 'q', 0, 0);
-    test(S("kantesmpgj"), 'q', 1, 1);
-    test(S("odaftiegpm"), 'q', 5, 5);
-    test(S("oknlrstdpi"), 'q', 9, 9);
-    test(S("eolhfgpjqk"), 'q', 10, S::npos);
-    test(S("pcdrofikas"), 'q', 11, S::npos);
-    test(S("nbatdlmekrgcfqsophij"), 'q', 0, 0);
-    test(S("bnrpehidofmqtcksjgla"), 'q', 1, 1);
-    test(S("jdmciepkaqgotsrfnhlb"), 'q', 10, 10);
-    test(S("jtdaefblsokrmhpgcnqi"), 'q', 19, 19);
-    test(S("hkbgspofltajcnedqmri"), 'q', 20, S::npos);
-    test(S("oselktgbcapndfjihrmq"), 'q', 21, S::npos);
+  test(S(""), 'q', S::npos);
+  test(S("q"), 'q', S::npos);
+  test(S("qqq"), 'q', S::npos);
+  test(S("csope"), 'q', 0);
+  test(S("gfsmthlkon"), 'q', 0);
+  test(S("laenfsbridchgotmkqpj"), 'q', 0);
+}
 
-    test(S(""), 'q', S::npos);
-    test(S("q"), 'q', S::npos);
-    test(S("qqq"), 'q', S::npos);
-    test(S("csope"), 'q', 0);
-    test(S("gfsmthlkon"), 'q', 0);
-    test(S("laenfsbridchgotmkqpj"), 'q', 0);
-  }
+TEST_CONSTEXPR_CXX20 bool test() {
+  test_string<std::string>();
+#if TEST_STD_VER >= 11
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_find.first.not.of/pointer_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_find.first.not.of/pointer_size.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.ops/string_find.first.not.of/pointer_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_find.first.not.of/pointer_size.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -142,18 +143,17 @@
     test(S("pniotcfrhqsmgdkjbael"), "htaobedqikfplcgjsmrn", S::npos);
 }
 
+template <class S>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  test0<S>();
+  test1<S>();
+}
+
 TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    test0<S>();
-    test1<S>();
-  }
+  test_string<std::string>();
 #if TEST_STD_VER >= 11
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    test0<S>();
-    test1<S>();
-  }
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_find.first.not.of/pointer_size_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_find.first.not.of/pointer_size_size.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.ops/string_find.first.not.of/pointer_size_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_find.first.not.of/pointer_size_size.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -367,22 +368,19 @@
     test(S("hnbrcplsjfgiktoedmaq"), "qprlsfojamgndekthibc", 21, 20, S::npos);
 }
 
+template <class S>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  test0<S>();
+  test1<S>();
+  test2<S>();
+  test3<S>();
+}
+
 TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    test0<S>();
-    test1<S>();
-    test2<S>();
-    test3<S>();
-  }
+  test_string<std::string>();
 #if TEST_STD_VER >= 11
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    test0<S>();
-    test1<S>();
-    test2<S>();
-    test3<S>();
-  }
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_find.first.not.of/string_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_find.first.not.of/string_size.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.ops/string_find.first.not.of/string_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_find.first.not.of/string_size.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -142,21 +143,17 @@
     test(S("pniotcfrhqsmgdkjbael"), S("htaobedqikfplcgjsmrn"), S::npos);
 }
 
-TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    test0<S>();
-    test1<S>();
-  }
-#if TEST_STD_VER >= 11
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    test0<S>();
-    test1<S>();
-  }
-#endif
+template <class S>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  test0<S>();
+  test1<S>();
+}
 
+TEST_CONSTEXPR_CXX20 bool test() {
+  test_string<std::string>();
 #if TEST_STD_VER >= 11
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
   { // LWG 2946
     std::string s = " !";
     assert(s.find_first_not_of({"abc", 1}) == 0);
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_find.first.not.of/string_view_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_find.first.not.of/string_view_size.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.ops/string_find.first.not.of/string_view_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_find.first.not.of/string_view_size.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S, class SV>
 TEST_CONSTEXPR_CXX20 void
@@ -142,20 +143,20 @@
     test(S("pniotcfrhqsmgdkjbael"), SV("htaobedqikfplcgjsmrn"), S::npos);
 }
 
+template <class CharT, template <class> class Alloc>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  using S  = std::basic_string<CharT, std::char_traits<CharT>, Alloc<CharT>>;
+  using SV = std::basic_string_view<CharT, std::char_traits<CharT>>;
+
+  test0<S, SV>();
+  test1<S, SV>();
+}
+
 TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    typedef std::string_view SV;
-    test0<S, SV>();
-    test1<S, SV>();
-  }
+  test_string<char, std::allocator>();
 #if TEST_STD_VER >= 11
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    typedef std::string_view SV;
-    test0<S, SV>();
-    test1<S, SV>();
-  }
+  test_string<char, min_allocator>();
+  test_string<char, fancy_pointer_allocator>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_find.first.of/char_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_find.first.of/char_size.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.ops/string_find.first.of/char_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_find.first.of/char_size.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -37,64 +38,40 @@
         assert(x < s.size());
 }
 
-TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    test(S(""), 'e', 0, S::npos);
-    test(S(""), 'e', 1, S::npos);
-    test(S("kitcj"), 'e', 0, S::npos);
-    test(S("qkamf"), 'e', 1, S::npos);
-    test(S("nhmko"), 'e', 2, S::npos);
-    test(S("tpsaf"), 'e', 4, S::npos);
-    test(S("lahfb"), 'e', 5, S::npos);
-    test(S("irkhs"), 'e', 6, S::npos);
-    test(S("gmfhdaipsr"), 'e', 0, S::npos);
-    test(S("kantesmpgj"), 'e', 1, 4);
-    test(S("odaftiegpm"), 'e', 5, 6);
-    test(S("oknlrstdpi"), 'e', 9, S::npos);
-    test(S("eolhfgpjqk"), 'e', 10, S::npos);
-    test(S("pcdrofikas"), 'e', 11, S::npos);
-    test(S("nbatdlmekrgcfqsophij"), 'e', 0, 7);
-    test(S("bnrpehidofmqtcksjgla"), 'e', 1, 4);
-    test(S("jdmciepkaqgotsrfnhlb"), 'e', 10, S::npos);
-    test(S("jtdaefblsokrmhpgcnqi"), 'e', 19, S::npos);
-    test(S("hkbgspofltajcnedqmri"), 'e', 20, S::npos);
-    test(S("oselktgbcapndfjihrmq"), 'e', 21, S::npos);
+template <class S>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  test(S(""), 'e', 0, S::npos);
+  test(S(""), 'e', 1, S::npos);
+  test(S("kitcj"), 'e', 0, S::npos);
+  test(S("qkamf"), 'e', 1, S::npos);
+  test(S("nhmko"), 'e', 2, S::npos);
+  test(S("tpsaf"), 'e', 4, S::npos);
+  test(S("lahfb"), 'e', 5, S::npos);
+  test(S("irkhs"), 'e', 6, S::npos);
+  test(S("gmfhdaipsr"), 'e', 0, S::npos);
+  test(S("kantesmpgj"), 'e', 1, 4);
+  test(S("odaftiegpm"), 'e', 5, 6);
+  test(S("oknlrstdpi"), 'e', 9, S::npos);
+  test(S("eolhfgpjqk"), 'e', 10, S::npos);
+  test(S("pcdrofikas"), 'e', 11, S::npos);
+  test(S("nbatdlmekrgcfqsophij"), 'e', 0, 7);
+  test(S("bnrpehidofmqtcksjgla"), 'e', 1, 4);
+  test(S("jdmciepkaqgotsrfnhlb"), 'e', 10, S::npos);
+  test(S("jtdaefblsokrmhpgcnqi"), 'e', 19, S::npos);
+  test(S("hkbgspofltajcnedqmri"), 'e', 20, S::npos);
+  test(S("oselktgbcapndfjihrmq"), 'e', 21, S::npos);
 
-    test(S(""), 'e', S::npos);
-    test(S("csope"), 'e', 4);
-    test(S("gfsmthlkon"), 'e', S::npos);
-    test(S("laenfsbridchgotmkqpj"), 'e', 2);
-  }
-#if TEST_STD_VER >= 11
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    test(S(""), 'e', 0, S::npos);
-    test(S(""), 'e', 1, S::npos);
-    test(S("kitcj"), 'e', 0, S::npos);
-    test(S("qkamf"), 'e', 1, S::npos);
-    test(S("nhmko"), 'e', 2, S::npos);
-    test(S("tpsaf"), 'e', 4, S::npos);
-    test(S("lahfb"), 'e', 5, S::npos);
-    test(S("irkhs"), 'e', 6, S::npos);
-    test(S("gmfhdaipsr"), 'e', 0, S::npos);
-    test(S("kantesmpgj"), 'e', 1, 4);
-    test(S("odaftiegpm"), 'e', 5, 6);
-    test(S("oknlrstdpi"), 'e', 9, S::npos);
-    test(S("eolhfgpjqk"), 'e', 10, S::npos);
-    test(S("pcdrofikas"), 'e', 11, S::npos);
-    test(S("nbatdlmekrgcfqsophij"), 'e', 0, 7);
-    test(S("bnrpehidofmqtcksjgla"), 'e', 1, 4);
-    test(S("jdmciepkaqgotsrfnhlb"), 'e', 10, S::npos);
-    test(S("jtdaefblsokrmhpgcnqi"), 'e', 19, S::npos);
-    test(S("hkbgspofltajcnedqmri"), 'e', 20, S::npos);
-    test(S("oselktgbcapndfjihrmq"), 'e', 21, S::npos);
+  test(S(""), 'e', S::npos);
+  test(S("csope"), 'e', 4);
+  test(S("gfsmthlkon"), 'e', S::npos);
+  test(S("laenfsbridchgotmkqpj"), 'e', 2);
+}
 
-    test(S(""), 'e', S::npos);
-    test(S("csope"), 'e', 4);
-    test(S("gfsmthlkon"), 'e', S::npos);
-    test(S("laenfsbridchgotmkqpj"), 'e', 2);
-  }
+TEST_CONSTEXPR_CXX20 bool test() {
+  test_string<std::string>();
+#if TEST_STD_VER >= 11
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_find.first.of/pointer_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_find.first.of/pointer_size.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.ops/string_find.first.of/pointer_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_find.first.of/pointer_size.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -143,18 +144,17 @@
     test(S("pniotcfrhqsmgdkjbael"), "htaobedqikfplcgjsmrn", 0);
 }
 
+template <class S>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  test0<S>();
+  test1<S>();
+}
+
 TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    test0<S>();
-    test1<S>();
-  }
+  test_string<std::string>();
 #if TEST_STD_VER >= 11
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    test0<S>();
-    test1<S>();
-  }
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_find.first.of/pointer_size_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_find.first.of/pointer_size_size.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.ops/string_find.first.of/pointer_size_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_find.first.of/pointer_size_size.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -367,22 +368,19 @@
     test(S("hnbrcplsjfgiktoedmaq"), "qprlsfojamgndekthibc", 21, 20, S::npos);
 }
 
+template <class S>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  test0<S>();
+  test1<S>();
+  test2<S>();
+  test3<S>();
+}
+
 TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    test0<S>();
-    test1<S>();
-    test2<S>();
-    test3<S>();
-  }
+  test_string<std::string>();
 #if TEST_STD_VER >= 11
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    test0<S>();
-    test1<S>();
-    test2<S>();
-    test3<S>();
-  }
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_find.first.of/string_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_find.first.of/string_size.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.ops/string_find.first.of/string_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_find.first.of/string_size.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -142,21 +143,17 @@
     test(S("pniotcfrhqsmgdkjbael"), S("htaobedqikfplcgjsmrn"), 0);
 }
 
-TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    test0<S>();
-    test1<S>();
-  }
-#if TEST_STD_VER >= 11
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    test0<S>();
-    test1<S>();
-  }
-#endif
+template <class S>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  test0<S>();
+  test1<S>();
+}
 
+TEST_CONSTEXPR_CXX20 bool test() {
+  test_string<std::string>();
 #if TEST_STD_VER >= 11
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
   { // LWG 2946
     std::string s = " !";
     assert(s.find_first_of({"abc", 1}) == std::string::npos);
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_find.first.of/string_view_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_find.first.of/string_view_size.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.ops/string_find.first.of/string_view_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_find.first.of/string_view_size.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S, class SV>
 TEST_CONSTEXPR_CXX20 void
@@ -142,20 +143,20 @@
     test(S("pniotcfrhqsmgdkjbael"), SV("htaobedqikfplcgjsmrn"), 0);
 }
 
+template <class CharT, template <class> class Alloc>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  using S  = std::basic_string<CharT, std::char_traits<CharT>, Alloc<CharT>>;
+  using SV = std::basic_string_view<CharT, std::char_traits<CharT>>;
+
+  test0<S, SV>();
+  test1<S, SV>();
+}
+
 TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    typedef std::string_view SV;
-    test0<S, SV>();
-    test1<S, SV>();
-  }
+  test_string<char, std::allocator>();
 #if TEST_STD_VER >= 11
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    typedef std::string_view SV;
-    test0<S, SV>();
-    test1<S, SV>();
-  }
+  test_string<char, min_allocator>();
+  test_string<char, fancy_pointer_allocator>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_find.last.not.of/char_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_find.last.not.of/char_size.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.ops/string_find.last.not.of/char_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_find.last.not.of/char_size.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -37,64 +38,40 @@
         assert(x < s.size());
 }
 
-TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    test(S(""), 'i', 0, S::npos);
-    test(S(""), 'i', 1, S::npos);
-    test(S("kitcj"), 'i', 0, 0);
-    test(S("qkamf"), 'i', 1, 1);
-    test(S("nhmko"), 'i', 2, 2);
-    test(S("tpsaf"), 'i', 4, 4);
-    test(S("lahfb"), 'i', 5, 4);
-    test(S("irkhs"), 'i', 6, 4);
-    test(S("gmfhdaipsr"), 'i', 0, 0);
-    test(S("kantesmpgj"), 'i', 1, 1);
-    test(S("odaftiegpm"), 'i', 5, 4);
-    test(S("oknlrstdpi"), 'i', 9, 8);
-    test(S("eolhfgpjqk"), 'i', 10, 9);
-    test(S("pcdrofikas"), 'i', 11, 9);
-    test(S("nbatdlmekrgcfqsophij"), 'i', 0, 0);
-    test(S("bnrpehidofmqtcksjgla"), 'i', 1, 1);
-    test(S("jdmciepkaqgotsrfnhlb"), 'i', 10, 10);
-    test(S("jtdaefblsokrmhpgcnqi"), 'i', 19, 18);
-    test(S("hkbgspofltajcnedqmri"), 'i', 20, 18);
-    test(S("oselktgbcapndfjihrmq"), 'i', 21, 19);
+template <class S>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  test(S(""), 'i', 0, S::npos);
+  test(S(""), 'i', 1, S::npos);
+  test(S("kitcj"), 'i', 0, 0);
+  test(S("qkamf"), 'i', 1, 1);
+  test(S("nhmko"), 'i', 2, 2);
+  test(S("tpsaf"), 'i', 4, 4);
+  test(S("lahfb"), 'i', 5, 4);
+  test(S("irkhs"), 'i', 6, 4);
+  test(S("gmfhdaipsr"), 'i', 0, 0);
+  test(S("kantesmpgj"), 'i', 1, 1);
+  test(S("odaftiegpm"), 'i', 5, 4);
+  test(S("oknlrstdpi"), 'i', 9, 8);
+  test(S("eolhfgpjqk"), 'i', 10, 9);
+  test(S("pcdrofikas"), 'i', 11, 9);
+  test(S("nbatdlmekrgcfqsophij"), 'i', 0, 0);
+  test(S("bnrpehidofmqtcksjgla"), 'i', 1, 1);
+  test(S("jdmciepkaqgotsrfnhlb"), 'i', 10, 10);
+  test(S("jtdaefblsokrmhpgcnqi"), 'i', 19, 18);
+  test(S("hkbgspofltajcnedqmri"), 'i', 20, 18);
+  test(S("oselktgbcapndfjihrmq"), 'i', 21, 19);
 
-    test(S(""), 'i', S::npos);
-    test(S("csope"), 'i', 4);
-    test(S("gfsmthlkon"), 'i', 9);
-    test(S("laenfsbridchgotmkqpj"), 'i', 19);
-  }
-#if TEST_STD_VER >= 11
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    test(S(""), 'i', 0, S::npos);
-    test(S(""), 'i', 1, S::npos);
-    test(S("kitcj"), 'i', 0, 0);
-    test(S("qkamf"), 'i', 1, 1);
-    test(S("nhmko"), 'i', 2, 2);
-    test(S("tpsaf"), 'i', 4, 4);
-    test(S("lahfb"), 'i', 5, 4);
-    test(S("irkhs"), 'i', 6, 4);
-    test(S("gmfhdaipsr"), 'i', 0, 0);
-    test(S("kantesmpgj"), 'i', 1, 1);
-    test(S("odaftiegpm"), 'i', 5, 4);
-    test(S("oknlrstdpi"), 'i', 9, 8);
-    test(S("eolhfgpjqk"), 'i', 10, 9);
-    test(S("pcdrofikas"), 'i', 11, 9);
-    test(S("nbatdlmekrgcfqsophij"), 'i', 0, 0);
-    test(S("bnrpehidofmqtcksjgla"), 'i', 1, 1);
-    test(S("jdmciepkaqgotsrfnhlb"), 'i', 10, 10);
-    test(S("jtdaefblsokrmhpgcnqi"), 'i', 19, 18);
-    test(S("hkbgspofltajcnedqmri"), 'i', 20, 18);
-    test(S("oselktgbcapndfjihrmq"), 'i', 21, 19);
+  test(S(""), 'i', S::npos);
+  test(S("csope"), 'i', 4);
+  test(S("gfsmthlkon"), 'i', 9);
+  test(S("laenfsbridchgotmkqpj"), 'i', 19);
+}
 
-    test(S(""), 'i', S::npos);
-    test(S("csope"), 'i', 4);
-    test(S("gfsmthlkon"), 'i', 9);
-    test(S("laenfsbridchgotmkqpj"), 'i', 19);
-  }
+TEST_CONSTEXPR_CXX20 bool test() {
+  test_string<std::string>();
+#if TEST_STD_VER >= 11
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_find.last.not.of/pointer_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_find.last.not.of/pointer_size.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.ops/string_find.last.not.of/pointer_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_find.last.not.of/pointer_size.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -143,18 +144,17 @@
     test(S("pniotcfrhqsmgdkjbael"), "htaobedqikfplcgjsmrn", S::npos);
 }
 
+template <class S>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  test0<S>();
+  test1<S>();
+}
+
 TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    test0<S>();
-    test1<S>();
-  }
+  test_string<std::string>();
 #if TEST_STD_VER >= 11
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    test0<S>();
-    test1<S>();
-  }
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_find.last.not.of/pointer_size_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_find.last.not.of/pointer_size_size.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.ops/string_find.last.not.of/pointer_size_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_find.last.not.of/pointer_size_size.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -367,22 +368,19 @@
     test(S("hnbrcplsjfgiktoedmaq"), "qprlsfojamgndekthibc", 21, 20, S::npos);
 }
 
+template <class S>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  test0<S>();
+  test1<S>();
+  test2<S>();
+  test3<S>();
+}
+
 TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    test0<S>();
-    test1<S>();
-    test2<S>();
-    test3<S>();
-  }
+  test_string<std::string>();
 #if TEST_STD_VER >= 11
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    test0<S>();
-    test1<S>();
-    test2<S>();
-    test3<S>();
-  }
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_find.last.not.of/string_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_find.last.not.of/string_size.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.ops/string_find.last.not.of/string_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_find.last.not.of/string_size.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -142,21 +143,17 @@
     test(S("pniotcfrhqsmgdkjbael"), S("htaobedqikfplcgjsmrn"), S::npos);
 }
 
-TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    test0<S>();
-    test1<S>();
-  }
-#if TEST_STD_VER >= 11
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    test0<S>();
-    test1<S>();
-  }
-#endif
+template <class S>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  test0<S>();
+  test1<S>();
+}
 
+TEST_CONSTEXPR_CXX20 bool test() {
+  test_string<std::string>();
 #if TEST_STD_VER >= 11
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
   { // LWG 2946
     std::string s = " !";
     assert(s.find_last_not_of({"abc", 1}) == s.size() - 1);
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_find.last.not.of/string_view_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_find.last.not.of/string_view_size.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.ops/string_find.last.not.of/string_view_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_find.last.not.of/string_view_size.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S, class SV>
 TEST_CONSTEXPR_CXX20 void
@@ -142,20 +143,20 @@
     test(S("pniotcfrhqsmgdkjbael"), SV("htaobedqikfplcgjsmrn"), S::npos);
 }
 
+template <class CharT, template <class> class Alloc>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  using S  = std::basic_string<CharT, std::char_traits<CharT>, Alloc<CharT>>;
+  using SV = std::basic_string_view<CharT, std::char_traits<CharT>>;
+
+  test0<S, SV>();
+  test1<S, SV>();
+}
+
 TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    typedef std::string_view SV;
-    test0<S, SV>();
-    test1<S, SV>();
-  }
+  test_string<char, std::allocator>();
 #if TEST_STD_VER >= 11
-  {
-     typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-     typedef std::string_view SV;
-     test0<S, SV>();
-     test1<S, SV>();
-  }
+  test_string<char, min_allocator>();
+  test_string<char, fancy_pointer_allocator>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_find.last.of/char_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_find.last.of/char_size.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.ops/string_find.last.of/char_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_find.last.of/char_size.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -37,64 +38,40 @@
         assert(x < s.size());
 }
 
-TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    test(S(""), 'm', 0, S::npos);
-    test(S(""), 'm', 1, S::npos);
-    test(S("kitcj"), 'm', 0, S::npos);
-    test(S("qkamf"), 'm', 1, S::npos);
-    test(S("nhmko"), 'm', 2, 2);
-    test(S("tpsaf"), 'm', 4, S::npos);
-    test(S("lahfb"), 'm', 5, S::npos);
-    test(S("irkhs"), 'm', 6, S::npos);
-    test(S("gmfhdaipsr"), 'm', 0, S::npos);
-    test(S("kantesmpgj"), 'm', 1, S::npos);
-    test(S("odaftiegpm"), 'm', 5, S::npos);
-    test(S("oknlrstdpi"), 'm', 9, S::npos);
-    test(S("eolhfgpjqk"), 'm', 10, S::npos);
-    test(S("pcdrofikas"), 'm', 11, S::npos);
-    test(S("nbatdlmekrgcfqsophij"), 'm', 0, S::npos);
-    test(S("bnrpehidofmqtcksjgla"), 'm', 1, S::npos);
-    test(S("jdmciepkaqgotsrfnhlb"), 'm', 10, 2);
-    test(S("jtdaefblsokrmhpgcnqi"), 'm', 19, 12);
-    test(S("hkbgspofltajcnedqmri"), 'm', 20, 17);
-    test(S("oselktgbcapndfjihrmq"), 'm', 21, 18);
+template <class S>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  test(S(""), 'm', 0, S::npos);
+  test(S(""), 'm', 1, S::npos);
+  test(S("kitcj"), 'm', 0, S::npos);
+  test(S("qkamf"), 'm', 1, S::npos);
+  test(S("nhmko"), 'm', 2, 2);
+  test(S("tpsaf"), 'm', 4, S::npos);
+  test(S("lahfb"), 'm', 5, S::npos);
+  test(S("irkhs"), 'm', 6, S::npos);
+  test(S("gmfhdaipsr"), 'm', 0, S::npos);
+  test(S("kantesmpgj"), 'm', 1, S::npos);
+  test(S("odaftiegpm"), 'm', 5, S::npos);
+  test(S("oknlrstdpi"), 'm', 9, S::npos);
+  test(S("eolhfgpjqk"), 'm', 10, S::npos);
+  test(S("pcdrofikas"), 'm', 11, S::npos);
+  test(S("nbatdlmekrgcfqsophij"), 'm', 0, S::npos);
+  test(S("bnrpehidofmqtcksjgla"), 'm', 1, S::npos);
+  test(S("jdmciepkaqgotsrfnhlb"), 'm', 10, 2);
+  test(S("jtdaefblsokrmhpgcnqi"), 'm', 19, 12);
+  test(S("hkbgspofltajcnedqmri"), 'm', 20, 17);
+  test(S("oselktgbcapndfjihrmq"), 'm', 21, 18);
 
-    test(S(""), 'm', S::npos);
-    test(S("csope"), 'm', S::npos);
-    test(S("gfsmthlkon"), 'm', 3);
-    test(S("laenfsbridchgotmkqpj"), 'm', 15);
-  }
-#if TEST_STD_VER >= 11
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    test(S(""), 'm', 0, S::npos);
-    test(S(""), 'm', 1, S::npos);
-    test(S("kitcj"), 'm', 0, S::npos);
-    test(S("qkamf"), 'm', 1, S::npos);
-    test(S("nhmko"), 'm', 2, 2);
-    test(S("tpsaf"), 'm', 4, S::npos);
-    test(S("lahfb"), 'm', 5, S::npos);
-    test(S("irkhs"), 'm', 6, S::npos);
-    test(S("gmfhdaipsr"), 'm', 0, S::npos);
-    test(S("kantesmpgj"), 'm', 1, S::npos);
-    test(S("odaftiegpm"), 'm', 5, S::npos);
-    test(S("oknlrstdpi"), 'm', 9, S::npos);
-    test(S("eolhfgpjqk"), 'm', 10, S::npos);
-    test(S("pcdrofikas"), 'm', 11, S::npos);
-    test(S("nbatdlmekrgcfqsophij"), 'm', 0, S::npos);
-    test(S("bnrpehidofmqtcksjgla"), 'm', 1, S::npos);
-    test(S("jdmciepkaqgotsrfnhlb"), 'm', 10, 2);
-    test(S("jtdaefblsokrmhpgcnqi"), 'm', 19, 12);
-    test(S("hkbgspofltajcnedqmri"), 'm', 20, 17);
-    test(S("oselktgbcapndfjihrmq"), 'm', 21, 18);
+  test(S(""), 'm', S::npos);
+  test(S("csope"), 'm', S::npos);
+  test(S("gfsmthlkon"), 'm', 3);
+  test(S("laenfsbridchgotmkqpj"), 'm', 15);
+}
 
-    test(S(""), 'm', S::npos);
-    test(S("csope"), 'm', S::npos);
-    test(S("gfsmthlkon"), 'm', 3);
-    test(S("laenfsbridchgotmkqpj"), 'm', 15);
-  }
+TEST_CONSTEXPR_CXX20 bool test() {
+  test_string<std::string>();
+#if TEST_STD_VER >= 11
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_find.last.of/pointer_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_find.last.of/pointer_size.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.ops/string_find.last.of/pointer_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_find.last.of/pointer_size.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -143,18 +144,17 @@
     test(S("pniotcfrhqsmgdkjbael"), "htaobedqikfplcgjsmrn", 19);
 }
 
+template <class S>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  test0<S>();
+  test1<S>();
+}
+
 TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    test0<S>();
-    test1<S>();
-  }
+  test_string<std::string>();
 #if TEST_STD_VER >= 11
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    test0<S>();
-    test1<S>();
-  }
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_find.last.of/pointer_size_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_find.last.of/pointer_size_size.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.ops/string_find.last.of/pointer_size_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_find.last.of/pointer_size_size.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -367,22 +368,19 @@
     test(S("hnbrcplsjfgiktoedmaq"), "qprlsfojamgndekthibc", 21, 20, 19);
 }
 
+template <class S>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  test0<S>();
+  test1<S>();
+  test2<S>();
+  test3<S>();
+}
+
 TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    test0<S>();
-    test1<S>();
-    test2<S>();
-    test3<S>();
-  }
+  test_string<std::string>();
 #if TEST_STD_VER >= 11
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    test0<S>();
-    test1<S>();
-    test2<S>();
-    test3<S>();
-  }
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_find.last.of/string_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_find.last.of/string_size.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.ops/string_find.last.of/string_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_find.last.of/string_size.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -142,21 +143,17 @@
     test(S("pniotcfrhqsmgdkjbael"), S("htaobedqikfplcgjsmrn"), 19);
 }
 
-TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    test0<S>();
-    test1<S>();
-  }
-#if TEST_STD_VER >= 11
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    test0<S>();
-    test1<S>();
-  }
-#endif
+template <class S>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  test0<S>();
+  test1<S>();
+}
 
+TEST_CONSTEXPR_CXX20 bool test() {
+  test_string<std::string>();
 #if TEST_STD_VER >= 11
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
   { // LWG 2946
     std::string s = " !";
     assert(s.find_last_of({"abc", 1}) == std::string::npos);
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_find.last.of/string_view_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_find.last.of/string_view_size.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.ops/string_find.last.of/string_view_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_find.last.of/string_view_size.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S, class SV>
 TEST_CONSTEXPR_CXX20 void
@@ -142,20 +143,19 @@
     test(S("pniotcfrhqsmgdkjbael"), SV("htaobedqikfplcgjsmrn"), 19);
 }
 
+template <class CharT, template <class> class Alloc>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  using S  = std::basic_string<CharT, std::char_traits<CharT>, Alloc<CharT>>;
+  using SV = std::basic_string_view<CharT, std::char_traits<CharT>>;
+  test0<S, SV>();
+  test1<S, SV>();
+}
+
 TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    typedef std::string_view SV;
-    test0<S, SV>();
-    test1<S, SV>();
-  }
+  test_string<char, std::allocator>();
 #if TEST_STD_VER >= 11
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    typedef std::string_view SV;
-    test0<S, SV>();
-    test1<S, SV>();
-  }
+  test_string<char, min_allocator>();
+  test_string<char, fancy_pointer_allocator>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_find/char_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_find/char_size.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.ops/string_find/char_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_find/char_size.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -37,64 +38,40 @@
         assert(0 <= x && x + 1 <= s.size());
 }
 
-TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    test(S(""), 'c', 0, S::npos);
-    test(S(""), 'c', 1, S::npos);
-    test(S("abcde"), 'c', 0, 2);
-    test(S("abcde"), 'c', 1, 2);
-    test(S("abcde"), 'c', 2, 2);
-    test(S("abcde"), 'c', 4, S::npos);
-    test(S("abcde"), 'c', 5, S::npos);
-    test(S("abcde"), 'c', 6, S::npos);
-    test(S("abcdeabcde"), 'c', 0, 2);
-    test(S("abcdeabcde"), 'c', 1, 2);
-    test(S("abcdeabcde"), 'c', 5, 7);
-    test(S("abcdeabcde"), 'c', 9, S::npos);
-    test(S("abcdeabcde"), 'c', 10, S::npos);
-    test(S("abcdeabcde"), 'c', 11, S::npos);
-    test(S("abcdeabcdeabcdeabcde"), 'c', 0, 2);
-    test(S("abcdeabcdeabcdeabcde"), 'c', 1, 2);
-    test(S("abcdeabcdeabcdeabcde"), 'c', 10, 12);
-    test(S("abcdeabcdeabcdeabcde"), 'c', 19, S::npos);
-    test(S("abcdeabcdeabcdeabcde"), 'c', 20, S::npos);
-    test(S("abcdeabcdeabcdeabcde"), 'c', 21, S::npos);
+template <class S>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  test(S(""), 'c', 0, S::npos);
+  test(S(""), 'c', 1, S::npos);
+  test(S("abcde"), 'c', 0, 2);
+  test(S("abcde"), 'c', 1, 2);
+  test(S("abcde"), 'c', 2, 2);
+  test(S("abcde"), 'c', 4, S::npos);
+  test(S("abcde"), 'c', 5, S::npos);
+  test(S("abcde"), 'c', 6, S::npos);
+  test(S("abcdeabcde"), 'c', 0, 2);
+  test(S("abcdeabcde"), 'c', 1, 2);
+  test(S("abcdeabcde"), 'c', 5, 7);
+  test(S("abcdeabcde"), 'c', 9, S::npos);
+  test(S("abcdeabcde"), 'c', 10, S::npos);
+  test(S("abcdeabcde"), 'c', 11, S::npos);
+  test(S("abcdeabcdeabcdeabcde"), 'c', 0, 2);
+  test(S("abcdeabcdeabcdeabcde"), 'c', 1, 2);
+  test(S("abcdeabcdeabcdeabcde"), 'c', 10, 12);
+  test(S("abcdeabcdeabcdeabcde"), 'c', 19, S::npos);
+  test(S("abcdeabcdeabcdeabcde"), 'c', 20, S::npos);
+  test(S("abcdeabcdeabcdeabcde"), 'c', 21, S::npos);
 
-    test(S(""), 'c', S::npos);
-    test(S("abcde"), 'c', 2);
-    test(S("abcdeabcde"), 'c', 2);
-    test(S("abcdeabcdeabcdeabcde"), 'c', 2);
-  }
-#if TEST_STD_VER >= 11
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    test(S(""), 'c', 0, S::npos);
-    test(S(""), 'c', 1, S::npos);
-    test(S("abcde"), 'c', 0, 2);
-    test(S("abcde"), 'c', 1, 2);
-    test(S("abcde"), 'c', 2, 2);
-    test(S("abcde"), 'c', 4, S::npos);
-    test(S("abcde"), 'c', 5, S::npos);
-    test(S("abcde"), 'c', 6, S::npos);
-    test(S("abcdeabcde"), 'c', 0, 2);
-    test(S("abcdeabcde"), 'c', 1, 2);
-    test(S("abcdeabcde"), 'c', 5, 7);
-    test(S("abcdeabcde"), 'c', 9, S::npos);
-    test(S("abcdeabcde"), 'c', 10, S::npos);
-    test(S("abcdeabcde"), 'c', 11, S::npos);
-    test(S("abcdeabcdeabcdeabcde"), 'c', 0, 2);
-    test(S("abcdeabcdeabcdeabcde"), 'c', 1, 2);
-    test(S("abcdeabcdeabcdeabcde"), 'c', 10, 12);
-    test(S("abcdeabcdeabcdeabcde"), 'c', 19, S::npos);
-    test(S("abcdeabcdeabcdeabcde"), 'c', 20, S::npos);
-    test(S("abcdeabcdeabcdeabcde"), 'c', 21, S::npos);
+  test(S(""), 'c', S::npos);
+  test(S("abcde"), 'c', 2);
+  test(S("abcdeabcde"), 'c', 2);
+  test(S("abcdeabcdeabcdeabcde"), 'c', 2);
+}
 
-    test(S(""), 'c', S::npos);
-    test(S("abcde"), 'c', 2);
-    test(S("abcdeabcde"), 'c', 2);
-    test(S("abcdeabcdeabcdeabcde"), 'c', 2);
-  }
+TEST_CONSTEXPR_CXX20 bool test() {
+  test_string<std::string>();
+#if TEST_STD_VER >= 11
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_find/pointer_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_find/pointer_size.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.ops/string_find/pointer_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_find/pointer_size.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -149,18 +150,17 @@
     test(S("abcdeabcdeabcdeabcde"), "abcdeabcdeabcdeabcde", 0);
 }
 
+template <class S>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  test0<S>();
+  test1<S>();
+}
+
 TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    test0<S>();
-    test1<S>();
-  }
+  test_string<std::string>();
 #if TEST_STD_VER >= 11
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    test0<S>();
-    test1<S>();
-  }
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_find/pointer_size_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_find/pointer_size_size.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.ops/string_find/pointer_size_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_find/pointer_size_size.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -367,22 +368,19 @@
     test(S("abcdeabcdeabcdeabcde"), "abcdeabcdeabcdeabcde", 21, 20, S::npos);
 }
 
+template <class S>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  test0<S>();
+  test1<S>();
+  test2<S>();
+  test3<S>();
+}
+
 TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    test0<S>();
-    test1<S>();
-    test2<S>();
-    test3<S>();
-  }
+  test_string<std::string>();
 #if TEST_STD_VER >= 11
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    test0<S>();
-    test1<S>();
-    test2<S>();
-    test3<S>();
-  }
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_find/string_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_find/string_size.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.ops/string_find/string_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_find/string_size.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -142,20 +143,18 @@
     test(S("abcdeabcdeabcdeabcde"), S("abcdeabcdeabcdeabcde"), 0);
 }
 
+template <class S>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  test0<S>();
+  test1<S>();
+}
+
 TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    test0<S>();
-    test1<S>();
-  }
+  test_string<std::string>();
 #if TEST_STD_VER >= 11
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    test0<S>();
-    test1<S>();
-  }
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
-
 #if TEST_STD_VER >= 11
   { // LWG 2946
     std::string s = " !";
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_find/string_view_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_find/string_view_size.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.ops/string_find/string_view_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_find/string_view_size.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S, class SV>
 TEST_CONSTEXPR_CXX20 void
@@ -142,20 +143,19 @@
     test(S("abcdeabcdeabcdeabcde"), SV("abcdeabcdeabcdeabcde"), 0);
 }
 
+template <class CharT, template <class> class Alloc>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  using S  = std::basic_string<CharT, std::char_traits<CharT>, Alloc<CharT>>;
+  using SV = std::basic_string_view<CharT, std::char_traits<CharT>>;
+  test0<S, SV>();
+  test1<S, SV>();
+}
+
 TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    typedef std::string_view SV;
-    test0<S, SV>();
-    test1<S, SV>();
-  }
+  test_string<char, std::allocator>();
 #if TEST_STD_VER >= 11
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    typedef std::string_view SV;
-    test0<S, SV>();
-    test1<S, SV>();
-  }
+  test_string<char, min_allocator>();
+  test_string<char, fancy_pointer_allocator>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_rfind/char_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_rfind/char_size.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.ops/string_rfind/char_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_rfind/char_size.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -37,64 +38,40 @@
         assert(x + 1 <= s.size());
 }
 
-TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    test(S(""), 'b', 0, S::npos);
-    test(S(""), 'b', 1, S::npos);
-    test(S("abcde"), 'b', 0, S::npos);
-    test(S("abcde"), 'b', 1, 1);
-    test(S("abcde"), 'b', 2, 1);
-    test(S("abcde"), 'b', 4, 1);
-    test(S("abcde"), 'b', 5, 1);
-    test(S("abcde"), 'b', 6, 1);
-    test(S("abcdeabcde"), 'b', 0, S::npos);
-    test(S("abcdeabcde"), 'b', 1, 1);
-    test(S("abcdeabcde"), 'b', 5, 1);
-    test(S("abcdeabcde"), 'b', 9, 6);
-    test(S("abcdeabcde"), 'b', 10, 6);
-    test(S("abcdeabcde"), 'b', 11, 6);
-    test(S("abcdeabcdeabcdeabcde"), 'b', 0, S::npos);
-    test(S("abcdeabcdeabcdeabcde"), 'b', 1, 1);
-    test(S("abcdeabcdeabcdeabcde"), 'b', 10, 6);
-    test(S("abcdeabcdeabcdeabcde"), 'b', 19, 16);
-    test(S("abcdeabcdeabcdeabcde"), 'b', 20, 16);
-    test(S("abcdeabcdeabcdeabcde"), 'b', 21, 16);
+template <class S>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  test(S(""), 'b', 0, S::npos);
+  test(S(""), 'b', 1, S::npos);
+  test(S("abcde"), 'b', 0, S::npos);
+  test(S("abcde"), 'b', 1, 1);
+  test(S("abcde"), 'b', 2, 1);
+  test(S("abcde"), 'b', 4, 1);
+  test(S("abcde"), 'b', 5, 1);
+  test(S("abcde"), 'b', 6, 1);
+  test(S("abcdeabcde"), 'b', 0, S::npos);
+  test(S("abcdeabcde"), 'b', 1, 1);
+  test(S("abcdeabcde"), 'b', 5, 1);
+  test(S("abcdeabcde"), 'b', 9, 6);
+  test(S("abcdeabcde"), 'b', 10, 6);
+  test(S("abcdeabcde"), 'b', 11, 6);
+  test(S("abcdeabcdeabcdeabcde"), 'b', 0, S::npos);
+  test(S("abcdeabcdeabcdeabcde"), 'b', 1, 1);
+  test(S("abcdeabcdeabcdeabcde"), 'b', 10, 6);
+  test(S("abcdeabcdeabcdeabcde"), 'b', 19, 16);
+  test(S("abcdeabcdeabcdeabcde"), 'b', 20, 16);
+  test(S("abcdeabcdeabcdeabcde"), 'b', 21, 16);
 
-    test(S(""), 'b', S::npos);
-    test(S("abcde"), 'b', 1);
-    test(S("abcdeabcde"), 'b', 6);
-    test(S("abcdeabcdeabcdeabcde"), 'b', 16);
-  }
-#if TEST_STD_VER >= 11
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    test(S(""), 'b', 0, S::npos);
-    test(S(""), 'b', 1, S::npos);
-    test(S("abcde"), 'b', 0, S::npos);
-    test(S("abcde"), 'b', 1, 1);
-    test(S("abcde"), 'b', 2, 1);
-    test(S("abcde"), 'b', 4, 1);
-    test(S("abcde"), 'b', 5, 1);
-    test(S("abcde"), 'b', 6, 1);
-    test(S("abcdeabcde"), 'b', 0, S::npos);
-    test(S("abcdeabcde"), 'b', 1, 1);
-    test(S("abcdeabcde"), 'b', 5, 1);
-    test(S("abcdeabcde"), 'b', 9, 6);
-    test(S("abcdeabcde"), 'b', 10, 6);
-    test(S("abcdeabcde"), 'b', 11, 6);
-    test(S("abcdeabcdeabcdeabcde"), 'b', 0, S::npos);
-    test(S("abcdeabcdeabcdeabcde"), 'b', 1, 1);
-    test(S("abcdeabcdeabcdeabcde"), 'b', 10, 6);
-    test(S("abcdeabcdeabcdeabcde"), 'b', 19, 16);
-    test(S("abcdeabcdeabcdeabcde"), 'b', 20, 16);
-    test(S("abcdeabcdeabcdeabcde"), 'b', 21, 16);
+  test(S(""), 'b', S::npos);
+  test(S("abcde"), 'b', 1);
+  test(S("abcdeabcde"), 'b', 6);
+  test(S("abcdeabcdeabcdeabcde"), 'b', 16);
+}
 
-    test(S(""), 'b', S::npos);
-    test(S("abcde"), 'b', 1);
-    test(S("abcdeabcde"), 'b', 6);
-    test(S("abcdeabcdeabcdeabcde"), 'b', 16);
-  }
+TEST_CONSTEXPR_CXX20 bool test() {
+  test_string<std::string>();
+#if TEST_STD_VER >= 11
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_rfind/pointer_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_rfind/pointer_size.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.ops/string_rfind/pointer_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_rfind/pointer_size.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -150,18 +151,17 @@
     test(S("abcdeabcdeabcdeabcde"), "abcdeabcdeabcdeabcde", 0);
 }
 
+template <class S>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  test0<S>();
+  test1<S>();
+}
+
 TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    test0<S>();
-    test1<S>();
-  }
+  test_string<std::string>();
 #if TEST_STD_VER >= 11
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    test0<S>();
-    test1<S>();
-  }
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_rfind/pointer_size_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_rfind/pointer_size_size.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.ops/string_rfind/pointer_size_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_rfind/pointer_size_size.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -367,22 +368,19 @@
     test(S("abcdeabcdeabcdeabcde"), "abcdeabcdeabcdeabcde", 21, 20, 0);
 }
 
+template <class S>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  test0<S>();
+  test1<S>();
+  test2<S>();
+  test3<S>();
+}
+
 TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    test0<S>();
-    test1<S>();
-    test2<S>();
-    test3<S>();
-  }
+  test_string<std::string>();
 #if TEST_STD_VER >= 11
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    test0<S>();
-    test1<S>();
-    test2<S>();
-    test3<S>();
-  }
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_rfind/string_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_rfind/string_size.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.ops/string_rfind/string_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_rfind/string_size.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -142,21 +143,17 @@
     test(S("abcdeabcdeabcdeabcde"), S("abcdeabcdeabcdeabcde"), 0);
 }
 
-TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    test0<S>();
-    test1<S>();
-  }
-#if TEST_STD_VER >= 11
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    test0<S>();
-    test1<S>();
-  }
-#endif
+template <class S>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  test0<S>();
+  test1<S>();
+}
 
+TEST_CONSTEXPR_CXX20 bool test() {
+  test_string<std::string>();
 #if TEST_STD_VER >= 11
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
   { // LWG 2946
     std::string s = " !";
     assert(s.rfind({"abc", 1}) == std::string::npos);
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_rfind/string_view_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_rfind/string_view_size.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.ops/string_rfind/string_view_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_rfind/string_view_size.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S, class SV>
 TEST_CONSTEXPR_CXX20 void
@@ -142,20 +143,19 @@
     test(S("abcdeabcdeabcdeabcde"), SV("abcdeabcdeabcdeabcde"), 0);
 }
 
+template <class CharT, template <class> class Alloc>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  using S  = std::basic_string<CharT, std::char_traits<CharT>, Alloc<CharT>>;
+  using SV = std::basic_string_view<CharT, std::char_traits<CharT>>;
+  test0<S, SV>();
+  test1<S, SV>();
+}
+
 TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    typedef std::string_view SV;
-    test0<S, SV>();
-    test1<S, SV>();
-  }
+  test_string<char, std::allocator>();
 #if TEST_STD_VER >= 11
-  {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    typedef std::string_view SV;
-    test0<S, SV>();
-    test1<S, SV>();
-  }
+  test_string<char, min_allocator>();
+  test_string<char, fancy_pointer_allocator>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_substr/substr.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_substr/substr.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.ops/string_substr/substr.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_substr/substr.pass.cpp
@@ -17,6 +17,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -47,130 +48,73 @@
 #endif
 }
 
+template <class S>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  test(S(""), 0, 0);
+  test(S(""), 1, 0);
+  test(S("pniot"), 0, 0);
+  test(S("htaob"), 0, 1);
+  test(S("fodgq"), 0, 2);
+  test(S("hpqia"), 0, 4);
+  test(S("qanej"), 0, 5);
+  test(S("dfkap"), 1, 0);
+  test(S("clbao"), 1, 1);
+  test(S("ihqrf"), 1, 2);
+  test(S("mekdn"), 1, 3);
+  test(S("ngtjf"), 1, 4);
+  test(S("srdfq"), 2, 0);
+  test(S("qkdrs"), 2, 1);
+  test(S("ikcrq"), 2, 2);
+  test(S("cdaih"), 2, 3);
+  test(S("dmajb"), 4, 0);
+  test(S("karth"), 4, 1);
+  test(S("lhcdo"), 5, 0);
+  test(S("acbsj"), 6, 0);
+  test(S("pbsjikaole"), 0, 0);
+  test(S("pcbahntsje"), 0, 1);
+  test(S("mprdjbeiak"), 0, 5);
+  test(S("fhepcrntko"), 0, 9);
+  test(S("eqmpaidtls"), 0, 10);
+  test(S("joidhalcmq"), 1, 0);
+  test(S("omigsphflj"), 1, 1);
+  test(S("kocgbphfji"), 1, 4);
+  test(S("onmjekafbi"), 1, 8);
+  test(S("fbslrjiqkm"), 1, 9);
+  test(S("oqmrjahnkg"), 5, 0);
+  test(S("jeidpcmalh"), 5, 1);
+  test(S("schfalibje"), 5, 2);
+  test(S("crliponbqe"), 5, 4);
+  test(S("igdscopqtm"), 5, 5);
+  test(S("qngpdkimlc"), 9, 0);
+  test(S("thdjgafrlb"), 9, 1);
+  test(S("hcjitbfapl"), 10, 0);
+  test(S("mgojkldsqh"), 11, 0);
+  test(S("gfshlcmdjreqipbontak"), 0, 0);
+  test(S("nadkhpfemgclosibtjrq"), 0, 1);
+  test(S("nkodajteqplrbifhmcgs"), 0, 10);
+  test(S("ofdrqmkeblthacpgijsn"), 0, 19);
+  test(S("gbmetiprqdoasckjfhln"), 0, 20);
+  test(S("bdfjqgatlksriohemnpc"), 1, 0);
+  test(S("crnklpmegdqfiashtojb"), 1, 1);
+  test(S("ejqcnahdrkfsmptilgbo"), 1, 9);
+  test(S("jsbtafedocnirgpmkhql"), 1, 18);
+  test(S("prqgnlbaejsmkhdctoif"), 1, 19);
+  test(S("qnmodrtkebhpasifgcjl"), 10, 0);
+  test(S("pejafmnokrqhtisbcdgl"), 10, 1);
+  test(S("cpebqsfmnjdolhkratgi"), 10, 5);
+  test(S("odnqkgijrhabfmcestlp"), 10, 9);
+  test(S("lmofqdhpkibagnrcjste"), 10, 10);
+  test(S("lgjqketopbfahrmnsicd"), 19, 0);
+  test(S("ktsrmnqagdecfhijpobl"), 19, 1);
+  test(S("lsaijeqhtrbgcdmpfkno"), 20, 0);
+  test(S("dplqartnfgejichmoskb"), 21, 0);
+}
+
 TEST_CONSTEXPR_CXX20 bool test() {
-    {
-    typedef std::string S;
-    test(S(""), 0, 0);
-    test(S(""), 1, 0);
-    test(S("pniot"), 0, 0);
-    test(S("htaob"), 0, 1);
-    test(S("fodgq"), 0, 2);
-    test(S("hpqia"), 0, 4);
-    test(S("qanej"), 0, 5);
-    test(S("dfkap"), 1, 0);
-    test(S("clbao"), 1, 1);
-    test(S("ihqrf"), 1, 2);
-    test(S("mekdn"), 1, 3);
-    test(S("ngtjf"), 1, 4);
-    test(S("srdfq"), 2, 0);
-    test(S("qkdrs"), 2, 1);
-    test(S("ikcrq"), 2, 2);
-    test(S("cdaih"), 2, 3);
-    test(S("dmajb"), 4, 0);
-    test(S("karth"), 4, 1);
-    test(S("lhcdo"), 5, 0);
-    test(S("acbsj"), 6, 0);
-    test(S("pbsjikaole"), 0, 0);
-    test(S("pcbahntsje"), 0, 1);
-    test(S("mprdjbeiak"), 0, 5);
-    test(S("fhepcrntko"), 0, 9);
-    test(S("eqmpaidtls"), 0, 10);
-    test(S("joidhalcmq"), 1, 0);
-    test(S("omigsphflj"), 1, 1);
-    test(S("kocgbphfji"), 1, 4);
-    test(S("onmjekafbi"), 1, 8);
-    test(S("fbslrjiqkm"), 1, 9);
-    test(S("oqmrjahnkg"), 5, 0);
-    test(S("jeidpcmalh"), 5, 1);
-    test(S("schfalibje"), 5, 2);
-    test(S("crliponbqe"), 5, 4);
-    test(S("igdscopqtm"), 5, 5);
-    test(S("qngpdkimlc"), 9, 0);
-    test(S("thdjgafrlb"), 9, 1);
-    test(S("hcjitbfapl"), 10, 0);
-    test(S("mgojkldsqh"), 11, 0);
-    test(S("gfshlcmdjreqipbontak"), 0, 0);
-    test(S("nadkhpfemgclosibtjrq"), 0, 1);
-    test(S("nkodajteqplrbifhmcgs"), 0, 10);
-    test(S("ofdrqmkeblthacpgijsn"), 0, 19);
-    test(S("gbmetiprqdoasckjfhln"), 0, 20);
-    test(S("bdfjqgatlksriohemnpc"), 1, 0);
-    test(S("crnklpmegdqfiashtojb"), 1, 1);
-    test(S("ejqcnahdrkfsmptilgbo"), 1, 9);
-    test(S("jsbtafedocnirgpmkhql"), 1, 18);
-    test(S("prqgnlbaejsmkhdctoif"), 1, 19);
-    test(S("qnmodrtkebhpasifgcjl"), 10, 0);
-    test(S("pejafmnokrqhtisbcdgl"), 10, 1);
-    test(S("cpebqsfmnjdolhkratgi"), 10, 5);
-    test(S("odnqkgijrhabfmcestlp"), 10, 9);
-    test(S("lmofqdhpkibagnrcjste"), 10, 10);
-    test(S("lgjqketopbfahrmnsicd"), 19, 0);
-    test(S("ktsrmnqagdecfhijpobl"), 19, 1);
-    test(S("lsaijeqhtrbgcdmpfkno"), 20, 0);
-    test(S("dplqartnfgejichmoskb"), 21, 0);
-    }
+  test_string<std::string>();
 #if TEST_STD_VER >= 11
-    {
-    typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
-    test(S(""), 0, 0);
-    test(S(""), 1, 0);
-    test(S("pniot"), 0, 0);
-    test(S("htaob"), 0, 1);
-    test(S("fodgq"), 0, 2);
-    test(S("hpqia"), 0, 4);
-    test(S("qanej"), 0, 5);
-    test(S("dfkap"), 1, 0);
-    test(S("clbao"), 1, 1);
-    test(S("ihqrf"), 1, 2);
-    test(S("mekdn"), 1, 3);
-    test(S("ngtjf"), 1, 4);
-    test(S("srdfq"), 2, 0);
-    test(S("qkdrs"), 2, 1);
-    test(S("ikcrq"), 2, 2);
-    test(S("cdaih"), 2, 3);
-    test(S("dmajb"), 4, 0);
-    test(S("karth"), 4, 1);
-    test(S("lhcdo"), 5, 0);
-    test(S("acbsj"), 6, 0);
-    test(S("pbsjikaole"), 0, 0);
-    test(S("pcbahntsje"), 0, 1);
-    test(S("mprdjbeiak"), 0, 5);
-    test(S("fhepcrntko"), 0, 9);
-    test(S("eqmpaidtls"), 0, 10);
-    test(S("joidhalcmq"), 1, 0);
-    test(S("omigsphflj"), 1, 1);
-    test(S("kocgbphfji"), 1, 4);
-    test(S("onmjekafbi"), 1, 8);
-    test(S("fbslrjiqkm"), 1, 9);
-    test(S("oqmrjahnkg"), 5, 0);
-    test(S("jeidpcmalh"), 5, 1);
-    test(S("schfalibje"), 5, 2);
-    test(S("crliponbqe"), 5, 4);
-    test(S("igdscopqtm"), 5, 5);
-    test(S("qngpdkimlc"), 9, 0);
-    test(S("thdjgafrlb"), 9, 1);
-    test(S("hcjitbfapl"), 10, 0);
-    test(S("mgojkldsqh"), 11, 0);
-    test(S("gfshlcmdjreqipbontak"), 0, 0);
-    test(S("nadkhpfemgclosibtjrq"), 0, 1);
-    test(S("nkodajteqplrbifhmcgs"), 0, 10);
-    test(S("ofdrqmkeblthacpgijsn"), 0, 19);
-    test(S("gbmetiprqdoasckjfhln"), 0, 20);
-    test(S("bdfjqgatlksriohemnpc"), 1, 0);
-    test(S("crnklpmegdqfiashtojb"), 1, 1);
-    test(S("ejqcnahdrkfsmptilgbo"), 1, 9);
-    test(S("jsbtafedocnirgpmkhql"), 1, 18);
-    test(S("prqgnlbaejsmkhdctoif"), 1, 19);
-    test(S("qnmodrtkebhpasifgcjl"), 10, 0);
-    test(S("pejafmnokrqhtisbcdgl"), 10, 1);
-    test(S("cpebqsfmnjdolhkratgi"), 10, 5);
-    test(S("odnqkgijrhabfmcestlp"), 10, 9);
-    test(S("lmofqdhpkibagnrcjste"), 10, 10);
-    test(S("lgjqketopbfahrmnsicd"), 19, 0);
-    test(S("ktsrmnqagdecfhijpobl"), 19, 1);
-    test(S("lsaijeqhtrbgcdmpfkno"), 20, 0);
-    test(S("dplqartnfgejichmoskb"), 21, 0);
-    }
+  test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.require/contiguous.pass.cpp b/libcxx/test/std/strings/basic.string/string.require/contiguous.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.require/contiguous.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.require/contiguous.pass.cpp
@@ -25,29 +25,39 @@
         assert ( *(c.begin() + static_cast<typename C::difference_type>(i)) == *(std::addressof(*c.begin()) + i));
 }
 
-TEST_CONSTEXPR_CXX20 bool test() {
-  {
-    typedef std::string S;
-    test_contiguous(S());
-    test_contiguous(S("1"));
-    test_contiguous(S("1234567890123456789012345678901234567890123456789012345678901234567890"));
-  }
+template <class CharT, template <class> class Alloc>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  typedef Alloc<CharT> A;
+  typedef std::basic_string<CharT, std::char_traits<CharT>, Alloc<CharT>> S;
+  test_contiguous(S(A{}));
+  test_contiguous(S("1", A()));
+  test_contiguous(S("1234567890123456789012345678901234567890123456789012345678901234567890", A()));
+}
+
+template <>
+TEST_CONSTEXPR_CXX20 void test_string<char, std::allocator>() {
+  typedef std::allocator<char> A;
+  typedef std::basic_string<char, std::char_traits<char>, A> S;
+  test_contiguous(S());
+  test_contiguous(S("1"));
+  test_contiguous(S("1234567890123456789012345678901234567890123456789012345678901234567890"));
+}
 
-  {
-    typedef test_allocator<char> A;
-    typedef std::basic_string<char, std::char_traits<char>, A> S;
-    test_contiguous(S(A(3)));
-    test_contiguous(S("1", A(5)));
-    test_contiguous(S("1234567890123456789012345678901234567890123456789012345678901234567890", A(7)));
-  }
+template <>
+TEST_CONSTEXPR_CXX20 void test_string<char, test_allocator>() {
+  typedef test_allocator<char> A;
+  typedef std::basic_string<char, std::char_traits<char>, A> S;
+  test_contiguous(S(A(3)));
+  test_contiguous(S("1", A(5)));
+  test_contiguous(S("1234567890123456789012345678901234567890123456789012345678901234567890", A(7)));
+}
+
+TEST_CONSTEXPR_CXX20 bool test() {
+  test_string<char, std::allocator>();
+  test_string<char, test_allocator>();
 #if TEST_STD_VER >= 11
-  {
-    typedef min_allocator<char> A;
-    typedef std::basic_string<char, std::char_traits<char>, A> S;
-    test_contiguous(S(A{}));
-    test_contiguous(S("1", A()));
-    test_contiguous(S("1234567890123456789012345678901234567890123456789012345678901234567890", A()));
-  }
+  test_string<char, min_allocator>();
+  test_string<char, fancy_pointer_allocator>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.starts_with/starts_with.char.pass.cpp b/libcxx/test/std/strings/basic.string/string.starts_with/starts_with.char.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.starts_with/starts_with.char.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.starts_with/starts_with.char.pass.cpp
@@ -15,20 +15,26 @@
 #include <cassert>
 
 #include "test_macros.h"
+#include "test_allocator.h"
 
-constexpr bool test() {
-  {
-    typedef std::string S;
-    S  s1 {};
-    S  s2 { "abcde", 5 };
+template <class S>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  S s1{};
+  S s2{"abcde", 5};
 
-    ASSERT_NOEXCEPT(s1.starts_with('e'));
+  ASSERT_NOEXCEPT(s1.starts_with('e'));
 
-    assert (!s1.starts_with('a'));
-    assert (!s1.starts_with('x'));
-    assert ( s2.starts_with('a'));
-    assert (!s2.starts_with('x'));
-  }
+  assert(!s1.starts_with('a'));
+  assert(!s1.starts_with('x'));
+  assert(s2.starts_with('a'));
+  assert(!s2.starts_with('x'));
+}
+
+TEST_CONSTEXPR_CXX20 bool test() {
+  test_string<std::string>();
+#if TEST_STD_VER >= 11
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
+#endif
 
   return true;
 }
diff --git a/libcxx/test/std/strings/basic.string/string.starts_with/starts_with.ptr.pass.cpp b/libcxx/test/std/strings/basic.string/string.starts_with/starts_with.ptr.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.starts_with/starts_with.ptr.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.starts_with/starts_with.ptr.pass.cpp
@@ -15,48 +15,54 @@
 #include <cassert>
 
 #include "test_macros.h"
+#include "test_allocator.h"
 
-constexpr bool test() {
-  {
-    typedef std::string S;
-    const char *s = "abcde";
-    S  s0 {};
-    S  s1 { s, 1 };
-    S  s2 { s, 2 };
-//     S  s3 { s, 3 };
-//     S  s4 { s, 4 };
-//     S  s5 { s, 5 };
-    S  sNot {"def", 3 };
+template <class S>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  const char* s = "abcde";
+  S s0{};
+  S s1{s, 1};
+  S s2{s, 2};
+  //     S  s3 { s, 3 };
+  //     S  s4 { s, 4 };
+  //     S  s5 { s, 5 };
+  S sNot{"def", 3};
 
-    LIBCPP_ASSERT_NOEXCEPT(s0.starts_with(""));
+  LIBCPP_ASSERT_NOEXCEPT(s0.starts_with(""));
 
-    assert ( s0.starts_with(""));
-    assert (!s0.starts_with("a"));
+  assert(s0.starts_with(""));
+  assert(!s0.starts_with("a"));
 
-    assert ( s1.starts_with(""));
-    assert ( s1.starts_with("a"));
-    assert (!s1.starts_with("ab"));
-    assert (!s1.starts_with("abc"));
-    assert (!s1.starts_with("abcd"));
-    assert (!s1.starts_with("abcde"));
-    assert (!s1.starts_with("def"));
+  assert(s1.starts_with(""));
+  assert(s1.starts_with("a"));
+  assert(!s1.starts_with("ab"));
+  assert(!s1.starts_with("abc"));
+  assert(!s1.starts_with("abcd"));
+  assert(!s1.starts_with("abcde"));
+  assert(!s1.starts_with("def"));
 
-    assert ( s2.starts_with(""));
-    assert ( s2.starts_with("a"));
-    assert ( s2.starts_with("ab"));
-    assert (!s2.starts_with("abc"));
-    assert (!s2.starts_with("abcd"));
-    assert (!s2.starts_with("abcde"));
-    assert (!s2.starts_with("def"));
+  assert(s2.starts_with(""));
+  assert(s2.starts_with("a"));
+  assert(s2.starts_with("ab"));
+  assert(!s2.starts_with("abc"));
+  assert(!s2.starts_with("abcd"));
+  assert(!s2.starts_with("abcde"));
+  assert(!s2.starts_with("def"));
 
-    assert ( sNot.starts_with(""));
-    assert (!sNot.starts_with("a"));
-    assert (!sNot.starts_with("ab"));
-    assert (!sNot.starts_with("abc"));
-    assert (!sNot.starts_with("abcd"));
-    assert (!sNot.starts_with("abcde"));
-    assert ( sNot.starts_with("def"));
-  }
+  assert(sNot.starts_with(""));
+  assert(!sNot.starts_with("a"));
+  assert(!sNot.starts_with("ab"));
+  assert(!sNot.starts_with("abc"));
+  assert(!sNot.starts_with("abcd"));
+  assert(!sNot.starts_with("abcde"));
+  assert(sNot.starts_with("def"));
+}
+
+TEST_CONSTEXPR_CXX20 bool test() {
+  test_string<std::string>();
+#if TEST_STD_VER >= 11
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
+#endif
 
   return true;
 }
diff --git a/libcxx/test/std/strings/basic.string/string.starts_with/starts_with.string_view.pass.cpp b/libcxx/test/std/strings/basic.string/string.starts_with/starts_with.string_view.pass.cpp
--- a/libcxx/test/std/strings/basic.string/string.starts_with/starts_with.string_view.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.starts_with/starts_with.string_view.pass.cpp
@@ -15,58 +15,67 @@
 #include <cassert>
 
 #include "test_macros.h"
+#include "test_allocator.h"
 
-constexpr bool test() {
-    typedef std::string S;
-    typedef std::string_view SV;
-    const char *s = "abcde";
-
-    S   s0;
-    S   s1  { s, 1 };
-    S   s2  { s, 2 };
-//  S   s3  { s, 3 };
-//  S   s4  { s, 4 };
-//  S   s5  { s, 5 };
-    S  sNot { "def", 3 };
-
-    SV  sv0;
-    SV  sv1 { s, 1 };
-    SV  sv2 { s, 2 };
-    SV  sv3 { s, 3 };
-    SV  sv4 { s, 4 };
-    SV  sv5 { s, 5 };
-    SV svNot {"def", 3 };
-
-    ASSERT_NOEXCEPT(s0.starts_with(sv0));
-
-    assert ( s0.starts_with(sv0));
-    assert (!s0.starts_with(sv1));
-
-    assert ( s1.starts_with(sv0));
-    assert ( s1.starts_with(sv1));
-    assert (!s1.starts_with(sv2));
-    assert (!s1.starts_with(sv3));
-    assert (!s1.starts_with(sv4));
-    assert (!s1.starts_with(sv5));
-    assert (!s1.starts_with(svNot));
-
-    assert ( s2.starts_with(sv0));
-    assert ( s2.starts_with(sv1));
-    assert ( s2.starts_with(sv2));
-    assert (!s2.starts_with(sv3));
-    assert (!s2.starts_with(sv4));
-    assert (!s2.starts_with(sv5));
-    assert (!s2.starts_with(svNot));
-
-    assert ( sNot.starts_with(sv0));
-    assert (!sNot.starts_with(sv1));
-    assert (!sNot.starts_with(sv2));
-    assert (!sNot.starts_with(sv3));
-    assert (!sNot.starts_with(sv4));
-    assert (!sNot.starts_with(sv5));
-    assert ( sNot.starts_with(svNot));
-
-    return true;
+template <class CharT, template <class> class Alloc>
+TEST_CONSTEXPR_CXX20 void test_string() {
+  using S       = std::basic_string<CharT, std::char_traits<CharT>, Alloc<CharT>>;
+  using SV      = std::basic_string_view<CharT, std::char_traits<CharT>>;
+  const char* s = "abcde";
+
+  S s0;
+  S s1{s, 1};
+  S s2{s, 2};
+  //  S   s3  { s, 3 };
+  //  S   s4  { s, 4 };
+  //  S   s5  { s, 5 };
+  S sNot{"def", 3};
+
+  SV sv0;
+  SV sv1{s, 1};
+  SV sv2{s, 2};
+  SV sv3{s, 3};
+  SV sv4{s, 4};
+  SV sv5{s, 5};
+  SV svNot{"def", 3};
+
+  ASSERT_NOEXCEPT(s0.starts_with(sv0));
+
+  assert(s0.starts_with(sv0));
+  assert(!s0.starts_with(sv1));
+
+  assert(s1.starts_with(sv0));
+  assert(s1.starts_with(sv1));
+  assert(!s1.starts_with(sv2));
+  assert(!s1.starts_with(sv3));
+  assert(!s1.starts_with(sv4));
+  assert(!s1.starts_with(sv5));
+  assert(!s1.starts_with(svNot));
+
+  assert(s2.starts_with(sv0));
+  assert(s2.starts_with(sv1));
+  assert(s2.starts_with(sv2));
+  assert(!s2.starts_with(sv3));
+  assert(!s2.starts_with(sv4));
+  assert(!s2.starts_with(sv5));
+  assert(!s2.starts_with(svNot));
+
+  assert(sNot.starts_with(sv0));
+  assert(!sNot.starts_with(sv1));
+  assert(!sNot.starts_with(sv2));
+  assert(!sNot.starts_with(sv3));
+  assert(!sNot.starts_with(sv4));
+  assert(!sNot.starts_with(sv5));
+  assert(sNot.starts_with(svNot));
+}
+
+TEST_CONSTEXPR_CXX20 bool test() {
+  test_string<char, std::allocator>();
+#if TEST_STD_VER >= 11
+  test_string<char, fancy_pointer_allocator>();
+#endif
+
+  return true;
 }
 
 int main(int, char**)
diff --git a/libcxx/test/std/strings/basic.string/types.pass.cpp b/libcxx/test/std/strings/basic.string/types.pass.cpp
--- a/libcxx/test/std/strings/basic.string/types.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/types.pass.cpp
@@ -39,6 +39,7 @@
 #include "test_traits.h"
 #include "test_allocator.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class Traits, class Allocator>
 void
@@ -81,6 +82,7 @@
                                 std::allocator<char> >::value), "");
 #if TEST_STD_VER >= 11
     test<std::char_traits<char>, min_allocator<char> >();
+    test<std::char_traits<char>, fancy_pointer_allocator<char> >();
 #endif
 
   return 0;
diff --git a/libcxx/test/std/strings/strings.erasure/erase.pass.cpp b/libcxx/test/std/strings/strings.erasure/erase.pass.cpp
--- a/libcxx/test/std/strings/strings.erasure/erase.pass.cpp
+++ b/libcxx/test/std/strings/strings.erasure/erase.pass.cpp
@@ -71,6 +71,7 @@
     test<std::string>();
     test<std::basic_string<char, std::char_traits<char>, min_allocator<char>>> ();
     test<std::basic_string<char, std::char_traits<char>, test_allocator<char>>> ();
+    test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 
-  return 0;
+    return 0;
 }
diff --git a/libcxx/test/std/strings/strings.erasure/erase_if.pass.cpp b/libcxx/test/std/strings/strings.erasure/erase_if.pass.cpp
--- a/libcxx/test/std/strings/strings.erasure/erase_if.pass.cpp
+++ b/libcxx/test/std/strings/strings.erasure/erase_if.pass.cpp
@@ -72,6 +72,7 @@
     test<std::string>();
     test<std::basic_string<char, std::char_traits<char>, min_allocator<char>>> ();
     test<std::basic_string<char, std::char_traits<char>, test_allocator<char>>> ();
+    test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 
-  return 0;
+    return 0;
 }
diff --git a/libcxx/test/support/test_allocator.h b/libcxx/test/support/test_allocator.h
--- a/libcxx/test/support/test_allocator.h
+++ b/libcxx/test/support/test_allocator.h
@@ -17,6 +17,7 @@
 #include <cstdlib>
 #include <climits>
 #include <cassert>
+#include <iterator>
 
 #include "test_macros.h"
 
@@ -28,38 +29,38 @@
 
 struct test_allocator_statistics {
   int time_to_throw = 0;
-  int throw_after = INT_MAX;
-  int count = 0;
-  int alloc_count = 0;
-  int copied = 0;
-  int moved = 0;
-  int converted = 0;
+  int throw_after   = INT_MAX;
+  int count         = 0;
+  int alloc_count   = 0;
+  int copied        = 0;
+  int moved         = 0;
+  int converted     = 0;
 
   TEST_CONSTEXPR_CXX14 void clear() {
     assert(count == 0 && "clearing leaking allocator data?");
-    count = 0;
+    count         = 0;
     time_to_throw = 0;
-    alloc_count = 0;
-    throw_after = INT_MAX;
+    alloc_count   = 0;
+    throw_after   = INT_MAX;
     clear_ctor_counters();
   }
 
   TEST_CONSTEXPR_CXX14 void clear_ctor_counters() {
-    copied = 0;
-    moved = 0;
+    copied    = 0;
+    moved     = 0;
     converted = 0;
   }
 };
 
 struct test_alloc_base {
   TEST_CONSTEXPR static const int destructed_value = -1;
-  TEST_CONSTEXPR static const int moved_value = INT_MAX;
+  TEST_CONSTEXPR static const int moved_value      = INT_MAX;
 };
 
 template <class T>
 class test_allocator {
-  int data_ = 0; // participates in equality
-  int id_ = 0;   // unique identifier, doesn't participate in equality
+  int data_                         = 0; // participates in equality
+  int id_                           = 0; // unique identifier, doesn't participate in equality
   test_allocator_statistics* stats_ = nullptr;
 
   template <class U>
@@ -89,7 +90,8 @@
   TEST_CONSTEXPR explicit test_allocator(int data) TEST_NOEXCEPT : data_(data) {}
 
   TEST_CONSTEXPR_CXX14 explicit test_allocator(int data, test_allocator_statistics* stats) TEST_NOEXCEPT
-      : data_(data), stats_(stats) {
+      : data_(data),
+        stats_(stats) {
     if (stats != nullptr)
       ++stats_->count;
   }
@@ -97,13 +99,17 @@
   TEST_CONSTEXPR explicit test_allocator(int data, int id) TEST_NOEXCEPT : data_(data), id_(id) {}
 
   TEST_CONSTEXPR_CXX14 explicit test_allocator(int data, int id, test_allocator_statistics* stats) TEST_NOEXCEPT
-      : data_(data), id_(id), stats_(stats) {
+      : data_(data),
+        id_(id),
+        stats_(stats) {
     if (stats_ != nullptr)
       ++stats_->count;
   }
 
   TEST_CONSTEXPR_CXX14 test_allocator(const test_allocator& a) TEST_NOEXCEPT
-    : data_(a.data_), id_(a.id_), stats_(a.stats_) {
+      : data_(a.data_),
+        id_(a.id_),
+        stats_(a.stats_) {
     assert(a.data_ != test_alloc_base::destructed_value && a.id_ != test_alloc_base::destructed_value &&
            "copying from destroyed allocator");
     if (stats_ != nullptr) {
@@ -120,12 +126,14 @@
     assert(a.data_ != test_alloc_base::destructed_value && a.id_ != test_alloc_base::destructed_value &&
            "moving from destroyed allocator");
     a.data_ = test_alloc_base::moved_value;
-    a.id_ = test_alloc_base::moved_value;
+    a.id_   = test_alloc_base::moved_value;
   }
 
   template <class U>
   TEST_CONSTEXPR_CXX14 test_allocator(const test_allocator<U>& a) TEST_NOEXCEPT
-      : data_(a.data_), id_(a.id_), stats_(a.stats_) {
+      : data_(a.data_),
+        id_(a.id_),
+        stats_(a.stats_) {
     if (stats_ != nullptr) {
       ++stats_->count;
       ++stats_->converted;
@@ -138,7 +146,7 @@
     if (stats_ != nullptr)
       --stats_->count;
     data_ = test_alloc_base::destructed_value;
-    id_ = test_alloc_base::destructed_value;
+    id_   = test_alloc_base::destructed_value;
   }
 
   TEST_CONSTEXPR pointer address(reference x) const { return &x; }
@@ -183,7 +191,7 @@
 
 template <class T>
 class non_default_test_allocator {
-  int data_ = 0;
+  int data_                         = 0;
   test_allocator_statistics* stats_ = nullptr;
 
   template <class U>
@@ -205,7 +213,8 @@
 
   TEST_CONSTEXPR_CXX14
   explicit non_default_test_allocator(int i, test_allocator_statistics* stats = nullptr) TEST_NOEXCEPT
-      : data_(i), stats_(stats) {
+      : data_(i),
+        stats_(stats) {
     if (stats_ != nullptr) {
       ++stats_->count;
     }
@@ -219,7 +228,8 @@
 
   template <class U>
   TEST_CONSTEXPR_CXX14 non_default_test_allocator(const non_default_test_allocator<U>& a) TEST_NOEXCEPT
-      : data_(a.data_), stats_(a.stats_) {
+      : data_(a.data_),
+        stats_(a.stats_) {
     if (stats_ != nullptr)
       ++stats_->count;
   }
@@ -265,8 +275,8 @@
 
 template <>
 class test_allocator<void> {
-  int data_ = 0;
-  int id_ = 0;
+  int data_                         = 0;
+  int id_                           = 0;
   test_allocator_statistics* stats_ = nullptr;
 
   template <class U>
@@ -291,27 +301,30 @@
   TEST_CONSTEXPR explicit test_allocator(int data) TEST_NOEXCEPT : data_(data) {}
 
   TEST_CONSTEXPR explicit test_allocator(int data, test_allocator_statistics* stats) TEST_NOEXCEPT
-      : data_(data), stats_(stats)
-  {}
+      : data_(data),
+        stats_(stats) {}
 
   TEST_CONSTEXPR explicit test_allocator(int data, int id) : data_(data), id_(id) {}
 
   TEST_CONSTEXPR_CXX14 explicit test_allocator(int data, int id, test_allocator_statistics* stats) TEST_NOEXCEPT
-      : data_(data), id_(id), stats_(stats)
-  {}
+      : data_(data),
+        id_(id),
+        stats_(stats) {}
 
   TEST_CONSTEXPR_CXX14 explicit test_allocator(const test_allocator& a) TEST_NOEXCEPT
-      : data_(a.data_), id_(a.id_), stats_(a.stats_)
-  {}
+      : data_(a.data_),
+        id_(a.id_),
+        stats_(a.stats_) {}
 
   template <class U>
   TEST_CONSTEXPR_CXX14 test_allocator(const test_allocator<U>& a) TEST_NOEXCEPT
-      : data_(a.data_), id_(a.id_), stats_(a.stats_)
-  {}
+      : data_(a.data_),
+        id_(a.id_),
+        stats_(a.stats_) {}
 
   TEST_CONSTEXPR_CXX20 ~test_allocator() TEST_NOEXCEPT {
     data_ = test_alloc_base::destructed_value;
-    id_ = test_alloc_base::destructed_value;
+    id_   = test_alloc_base::destructed_value;
   }
 
   TEST_CONSTEXPR int get_id() const { return id_; }
@@ -377,9 +390,9 @@
   TEST_CONSTEXPR Tag_X(Ctor_Tag, Args&&...) {}
 
   // not DefaultConstructible, CopyConstructible or MoveConstructible.
-  Tag_X() = delete;
+  Tag_X()             = delete;
   Tag_X(const Tag_X&) = delete;
-  Tag_X(Tag_X&&) = delete;
+  Tag_X(Tag_X&&)      = delete;
 
   // CopyAssignable.
   TEST_CONSTEXPR_CXX14 Tag_X& operator=(const Tag_X&) { return *this; };
@@ -396,7 +409,7 @@
 template <typename T>
 class TaggingAllocator {
 public:
-  using value_type = T;
+  using value_type   = T;
   TaggingAllocator() = default;
 
   template <typename U>
@@ -423,13 +436,13 @@
 template <std::size_t MaxAllocs>
 struct limited_alloc_handle {
   std::size_t outstanding_ = 0;
-  void* last_alloc_ = nullptr;
+  void* last_alloc_        = nullptr;
 
   template <class T>
   TEST_CONSTEXPR_CXX20 T* allocate(std::size_t N) {
     if (N + outstanding_ > MaxAllocs)
       TEST_THROW(std::bad_alloc());
-    auto alloc = std::allocator<T>().allocate(N);
+    auto alloc  = std::allocator<T>().allocate(N);
     last_alloc_ = alloc;
     outstanding_ += N;
     return alloc;
@@ -499,8 +512,196 @@
 
   return ptr;
 }
+
 } // namespace detail
 
+template <class T>
+class fancy_pointer {
+public:
+  // For the std::pointer_traits interface.
+  using pointer         = T*;
+  using element_type    = T;
+  using difference_type = std::ptrdiff_t;
+
+  template <class U>
+  using rebind = fancy_pointer<U>;
+
+  // For the std::iterator_traits interface.
+  using value_type        = typename std::remove_cv<T>::type;
+  using reference         = typename std::add_lvalue_reference<T>::type;
+  using iterator_category = std::random_access_iterator_tag;
+
+  TEST_CONSTEXPR_CXX14 fancy_pointer() TEST_NOEXCEPT : ptr_(nullptr) {}
+  TEST_CONSTEXPR_CXX14 fancy_pointer(T* p) TEST_NOEXCEPT : ptr_(p) {}
+
+  template <typename T2>
+  TEST_CONSTEXPR_CXX14 fancy_pointer(const fancy_pointer<T2>& other) TEST_NOEXCEPT : ptr_(other.get()) {}
+
+  TEST_CONSTEXPR_CXX14 operator T*() const TEST_NOEXCEPT { return ptr_; }
+  TEST_CONSTEXPR_CXX14 fancy_pointer(fancy_pointer&&) TEST_NOEXCEPT                 = default;
+  TEST_CONSTEXPR_CXX14 fancy_pointer(const fancy_pointer&) TEST_NOEXCEPT            = default;
+  TEST_CONSTEXPR_CXX14 fancy_pointer& operator=(fancy_pointer&&) TEST_NOEXCEPT      = default;
+  TEST_CONSTEXPR_CXX14 fancy_pointer& operator=(const fancy_pointer&) TEST_NOEXCEPT = default;
+  TEST_CONSTEXPR_CXX14 ~fancy_pointer() TEST_NOEXCEPT                               = default;
+  TEST_CONSTEXPR_CXX14 operator fancy_pointer<const T>() const TEST_NOEXCEPT { return fancy_pointer<const T>(get()); }
+  TEST_CONSTEXPR_CXX14 T& operator*() const TEST_NOEXCEPT { return *ptr_; }
+  TEST_CONSTEXPR_CXX14 T* operator->() const TEST_NOEXCEPT { return ptr_; }
+  TEST_CONSTEXPR_CXX14 explicit operator bool() const TEST_NOEXCEPT { return ptr_; }
+  TEST_CONSTEXPR_CXX14 T* get() const TEST_NOEXCEPT { return ptr_; }
+
+  TEST_CONSTEXPR_CXX14 fancy_pointer& operator++() TEST_NOEXCEPT {
+    ++ptr_;
+    return *this;
+  }
+  TEST_CONSTEXPR_CXX14 fancy_pointer operator++(int) TEST_NOEXCEPT {
+    fancy_pointer tmp(*this);
+    ++ptr_;
+    return tmp;
+  }
+
+  TEST_CONSTEXPR_CXX14 fancy_pointer& operator--() TEST_NOEXCEPT {
+    --ptr_;
+    return *this;
+  }
+  TEST_CONSTEXPR_CXX14 fancy_pointer operator--(int) TEST_NOEXCEPT {
+    fancy_pointer tmp(*this);
+    --ptr_;
+    return tmp;
+  }
+
+  TEST_CONSTEXPR_CXX14 fancy_pointer& operator+=(difference_type n) TEST_NOEXCEPT {
+    ptr_ += n;
+    return *this;
+  }
+
+  TEST_CONSTEXPR_CXX14 fancy_pointer& operator-=(difference_type n) TEST_NOEXCEPT {
+    ptr_ -= n;
+    return *this;
+  }
+
+  TEST_CONSTEXPR_CXX14 fancy_pointer operator+(difference_type n) const TEST_NOEXCEPT {
+    fancy_pointer tmp(*this);
+    tmp += n;
+    return tmp;
+  }
+
+  TEST_CONSTEXPR_CXX14 fancy_pointer operator-(difference_type n) const TEST_NOEXCEPT {
+    fancy_pointer tmp(*this);
+    tmp -= n;
+    return tmp;
+  }
+
+  TEST_CONSTEXPR_CXX14 reference operator[](difference_type n) const TEST_NOEXCEPT { return ptr_[n]; }
+
+  friend TEST_CONSTEXPR_CXX14 fancy_pointer operator+(difference_type x, fancy_pointer y) TEST_NOEXCEPT {
+    return y + x;
+  }
+
+  friend TEST_CONSTEXPR_CXX14 bool operator<(fancy_pointer x, fancy_pointer y) TEST_NOEXCEPT { return x.ptr_ < y.ptr_; }
+  friend TEST_CONSTEXPR_CXX14 bool operator>(fancy_pointer x, fancy_pointer y) TEST_NOEXCEPT { return y < x; }
+  friend TEST_CONSTEXPR_CXX14 bool operator<=(fancy_pointer x, fancy_pointer y) TEST_NOEXCEPT { return !(y < x); }
+  friend TEST_CONSTEXPR_CXX14 bool operator>=(fancy_pointer x, fancy_pointer y) TEST_NOEXCEPT { return !(x < y); }
+
+  static TEST_CONSTEXPR_CXX14 fancy_pointer pointer_to(reference ref) TEST_NOEXCEPT { return fancy_pointer(&ref); }
+
+  T* ptr_;
+};
+
+template <typename T>
+TEST_CONSTEXPR_CXX14 typename fancy_pointer<T>::difference_type
+operator-(fancy_pointer<T> x, fancy_pointer<T> y) TEST_NOEXCEPT {
+  return x.ptr_ - y.ptr_;
+}
+
+template <typename T>
+TEST_CONSTEXPR_CXX14 typename fancy_pointer<T>::difference_type
+operator-(fancy_pointer<const T> x, fancy_pointer<T> y) TEST_NOEXCEPT {
+  return x.ptr_ - y.ptr_;
+}
+
+template <typename T>
+TEST_CONSTEXPR_CXX14 typename fancy_pointer<T>::difference_type
+operator-(fancy_pointer<T> x, fancy_pointer<const T> y) TEST_NOEXCEPT {
+  return x.ptr_ - y.ptr_;
+}
+
+template <typename T>
+TEST_CONSTEXPR_CXX14 typename fancy_pointer<T>::difference_type
+operator-(fancy_pointer<const T> x, fancy_pointer<const T> y) TEST_NOEXCEPT {
+  return x.ptr_ - y.ptr_;
+}
+
+template <typename T>
+TEST_CONSTEXPR_CXX14 bool operator==(fancy_pointer<T> x, fancy_pointer<T> y) TEST_NOEXCEPT {
+  return x.get() == y.get();
+}
+
+template <typename T>
+TEST_CONSTEXPR_CXX14 bool operator==(fancy_pointer<const T> x, fancy_pointer<T> y) TEST_NOEXCEPT {
+  return x.get() == y.get();
+}
+
+template <typename T>
+TEST_CONSTEXPR_CXX14 bool operator==(fancy_pointer<T> x, fancy_pointer<const T> y) TEST_NOEXCEPT {
+  return x.get() == y.get();
+}
+
+template <typename T>
+TEST_CONSTEXPR_CXX14 bool operator==(fancy_pointer<const T> x, fancy_pointer<const T> y) TEST_NOEXCEPT {
+  return x.get() == y.get();
+}
+
+template <typename T>
+TEST_CONSTEXPR_CXX14 bool operator!=(fancy_pointer<T> x, fancy_pointer<T> y) TEST_NOEXCEPT {
+  return !(x == y);
+}
+
+template <typename T>
+TEST_CONSTEXPR_CXX14 bool operator!=(fancy_pointer<const T> x, fancy_pointer<T> y) TEST_NOEXCEPT {
+  return !(x == y);
+}
+
+template <typename T>
+TEST_CONSTEXPR_CXX14 bool operator!=(fancy_pointer<T> x, fancy_pointer<const T> y) TEST_NOEXCEPT {
+  return !(x == y);
+}
+
+template <typename T>
+TEST_CONSTEXPR_CXX14 bool operator!=(fancy_pointer<const T> x, fancy_pointer<const T> y) TEST_NOEXCEPT {
+  return !(x == y);
+}
+
+template <class T>
+class fancy_pointer_allocator : public std::allocator<T> {
+  typedef std::allocator<T> base;
+
+public:
+  typedef T value_type;
+  typedef fancy_pointer<T> pointer;
+  typedef fancy_pointer<const T> const_pointer;
+  typedef value_type& reference;
+  typedef const value_type& const_reference;
+  typedef std::size_t size_type;
+  typedef std::ptrdiff_t difference_type;
+
+  template <class U>
+  struct rebind {
+    typedef fancy_pointer_allocator<U> other;
+  };
+
+  TEST_CONSTEXPR_CXX20 fancy_pointer_allocator() TEST_NOEXCEPT {}
+
+  template <class U>
+  TEST_CONSTEXPR explicit fancy_pointer_allocator(fancy_pointer_allocator<U>) TEST_NOEXCEPT {}
+
+  TEST_CONSTEXPR_CXX20 pointer allocate(size_t n) { return base::allocate(n); }
+  TEST_CONSTEXPR_CXX20 void deallocate(pointer p, size_t n) { return base::deallocate(p, n); }
+
+#if TEST_STD_VER >= 20
+  TEST_CONSTEXPR_CXX20 std::allocation_result<pointer> allocate_at_least(std::size_t n) { return {allocate(n), n}; }
+#endif
+};
+
 template <class T, std::size_t N>
 class limited_allocator {
   template <class U, std::size_t UN>