1+ #ifndef TESTS_COMMON_HPP
2+ #define TESTS_COMMON_HPP
3+ /*
4+ * Copyright (c) 2024 PlayEveryWare
5+ *
6+ * Permission is hereby granted, free of charge, to any person obtaining a copy
7+ * of this software and associated documentation files (the "Software"), to deal
8+ * in the Software without restriction, including without limitation the rights
9+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+ * copies of the Software, and to permit persons to whom the Software is
11+ * furnished to do so, subject to the following conditions:
12+ *
13+ * The above copyright notice and this permission notice shall be included in
14+ * all copies or substantial portions of the Software.
15+ *
16+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+ * SOFTWARE.
23+ */
24+
25+ #include " pch.h"
26+
27+ #include " eos_helpers.h"
28+
29+ namespace pew ::eos::tests
30+ {
31+ // Helper trait to detect if a type supports the << operator
32+ template <typename T, typename Stream, typename = void >
33+ struct supports_streaming : std::false_type {};
34+
35+ // Specialization if the << operator is valid
36+ template <typename T, typename Stream>
37+ struct supports_streaming <T, Stream, std::void_t <decltype (std::declval<Stream&>() << std::declval<T>())>> : std::true_type {};
38+
39+ template <typename T, typename Stream>
40+ inline constexpr bool supports_streaming_v = supports_streaming<T, Stream>::value;
41+
42+ /* *
43+ * \brief Utility to convert unsupported types for wide streams.
44+ */
45+ struct WideStreamHelper {
46+ static std::wstring Convert (const std::string& str) {
47+ return std::wstring (str.begin (), str.end ()); // Naive conversion for ASCII strings
48+ }
49+
50+ static const std::wstring& Convert (const std::wstring& str) {
51+ return str;
52+ }
53+
54+ template <typename T>
55+ static const T& Convert (const T& value) {
56+ return value; // Pass through for types that are natively streamable
57+ }
58+ };
59+
60+ /* *
61+ * \brief Construct a message to display if an equality assert fails.
62+ * \tparam T1 The type of the unmanaged value.
63+ * \tparam T2 The type of the managed value.
64+ * \param name The name for the value.
65+ * \param unmanaged_value The unmanaged value.
66+ * \param managed_value The managed value.
67+ * \return A string message describing the inequality between two values.
68+ */
69+ template <typename T1, typename T2,
70+ std::enable_if_t <
71+ (supports_streaming_v<decltype (WideStreamHelper::Convert(std::declval<T1>())), std::wostream>&&
72+ supports_streaming_v<decltype (WideStreamHelper::Convert(std::declval<T2>())), std::wostream>),
73+ int > = 0 >
74+ static std::wstring ConstructMessage (const wchar_t * name, const T1& unmanaged_value, const T2& managed_value)
75+ {
76+ std::wstringbuf buffer;
77+ std::wostream os (&buffer);
78+
79+ os << name << L" is not equal (Native: "
80+ << WideStreamHelper::Convert (unmanaged_value)
81+ << L" , Managed: "
82+ << WideStreamHelper::Convert (managed_value)
83+ << L" )." ;
84+
85+ return buffer.str ();
86+ }
87+
88+ /* *
89+ * @brief Determine whether the value with the indicated name is equal from managed and unmanaged.
90+ * @param name Checks the equality of two values.
91+ * @param c_str The unmanaged value.
92+ * @param str The managed value.
93+ */
94+ inline void CheckEquality (const wchar_t * name, const char * c_str, System::String^ str)
95+ {
96+ const auto managed = msclr::interop::marshal_as<std::string>(str);
97+ const std::string unmanaged = c_str;
98+
99+ EXPECT_TRUE (managed == unmanaged) << ConstructMessage (name, unmanaged, managed);
100+ }
101+
102+ /* *
103+ * This function will check equality between a const char* value and a Utf8String, but it will consider a nullptr Utf8String to be equal to "" for the sake of
104+ * comparison.
105+ *
106+ * @param name The name of the property being examined for equality.
107+ * @param c_str The const char* version of the string.
108+ * @param str The Utf8String object.
109+ */
110+ inline void CheckEquality (const wchar_t * name, const char * c_str, Epic::OnlineServices::Utf8String^ str)
111+ {
112+ System::String^ string_value = " " ;
113+ if (str != nullptr )
114+ {
115+ string_value = str->ToString ();
116+ }
117+
118+ CheckEquality (name, c_str, string_value);
119+ }
120+
121+ /* *
122+ * @brief Determine whether the value with the indicated name is equal from managed and unmanaged.
123+ * @param name Checks the equality of two values.
124+ * @param unmanaged_value The unmanaged value.
125+ * @param managed_value The managed value.
126+ */
127+ inline void CheckEquality (const wchar_t * name, const uint64_t & unmanaged_value, const uint64_t & managed_value)
128+ {
129+ EXPECT_TRUE (unmanaged_value == managed_value) << ConstructMessage (name, unmanaged_value, managed_value);
130+ }
131+
132+ /* *
133+ * @brief Determine whether the value with the indicated name is equal from managed and unmanaged.
134+ * @param name Checks the equality of two values.
135+ * @param unmanaged_value The unmanaged value.
136+ * @param managed_value The managed value.
137+ */
138+ inline void CheckEquality (const wchar_t * name, const uint32_t & unmanaged_value, const unsigned int managed_value)
139+ {
140+ EXPECT_TRUE (unmanaged_value == managed_value) << ConstructMessage (name, unmanaged_value, managed_value);
141+ }
142+
143+ /* *
144+ * @brief Determine whether the value with the indicated name is equal from managed and unmanaged.
145+ * @param name Checks the equality of two values.
146+ * @param unmanaged_value The unmanaged value.
147+ * @param managed_value The managed value.
148+ */
149+ inline void CheckEquality (const wchar_t * name, const double * unmanaged_value, System::Nullable<double >& managed_value)
150+ {
151+ // Helper to extract value or default for System::Nullable<double>
152+ auto get_managed_value = [](System::Nullable<double >& value, double default_value = 0.0 ) -> double {
153+ return value.HasValue ? value.Value : default_value;
154+ };
155+
156+ // Helper to extract value or default for unmanaged pointer
157+ auto get_unmanaged_value = [](const double * value, double default_value = 0.0 ) -> double {
158+ return value ? *value : default_value;
159+ };
160+
161+ // If both are "null," they are considered equal
162+ if (!unmanaged_value && !managed_value.HasValue )
163+ {
164+ return ; // Equal; no need to proceed
165+ }
166+
167+ // If only one is "null," they cannot be equal
168+ if (!unmanaged_value || !managed_value.HasValue )
169+ {
170+ EXPECT_TRUE (false ) << " Mismatch: "
171+ << (unmanaged_value ? *unmanaged_value : NAN)
172+ << " vs. "
173+ << (managed_value.HasValue ? managed_value.Value : NAN)
174+ << " (unmanaged vs. managed)." ;
175+ return ;
176+ }
177+
178+ // Extract the actual values
179+ double unmanaged_dbl_value = get_unmanaged_value (unmanaged_value);
180+ double managed_dbl_value = get_managed_value (managed_value);
181+
182+ // Construct message for failure reporting
183+ const auto message = ConstructMessage (name, unmanaged_dbl_value, managed_dbl_value);
184+
185+ // Assert equality
186+ EXPECT_TRUE (unmanaged_dbl_value == managed_dbl_value) << message;
187+ }
188+
189+ /* *
190+ * @brief Determine whether the value with the indicated name is equal from managed and unmanaged.
191+ * @param name Checks the equality of two values.
192+ * @param unmanaged_value The unmanaged value.
193+ * @param managed_value The managed value.
194+ */
195+ inline void CheckEquality (const wchar_t * name, const EOS_Bool& unmanaged_value, const bool managed_value)
196+ {
197+ bool unmanaged_bool_value = (unmanaged_value == 1 );
198+
199+ EXPECT_TRUE (unmanaged_bool_value == managed_value) << ConstructMessage (name, unmanaged_value, managed_value);
200+ }
201+
202+ /* *
203+ * @brief Determine whether the value with the indicated name is equal from managed and unmanaged.
204+ * @param name Checks the equality of two values.
205+ * @param unmanaged_value The unmanaged value.
206+ * @param managed_value The managed value.
207+ */
208+ inline void CheckEquality (const wchar_t * name, const int32_t & unmanaged_value, const int32_t & managed_value)
209+ {
210+ EXPECT_TRUE (unmanaged_value == managed_value) << ConstructMessage (name, unmanaged_value, managed_value);
211+ }
212+ }
213+
214+ #endif
0 commit comments