1 //===-- c_api_test.cpp ----------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file is a part of the ORC runtime.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "orc_rt/c_api.h"
14 #include "gtest/gtest.h"
15 
16 TEST(CAPITest, CWrapperFunctionResultInit) {
17   __orc_rt_CWrapperFunctionResult R;
18   __orc_rt_CWrapperFunctionResultInit(&R);
19 
20   EXPECT_EQ(R.Size, 0U);
21   EXPECT_EQ(R.Data.ValuePtr, nullptr);
22 
23   // Check that this value isn't treated as an out-of-band error.
24   EXPECT_EQ(__orc_rt_CWrapperFunctionResultGetOutOfBandError(&R), nullptr);
25 
26   // Check that we can dispose of the value.
27   __orc_rt_DisposeCWrapperFunctionResult(&R);
28 }
29 
30 TEST(CAPITest, CWrapperFunctionResultAllocSmall) {
31   constexpr size_t SmallAllocSize = sizeof(const char *);
32 
33   auto R = __orc_rt_CWrapperFunctionResultAllocate(SmallAllocSize);
34   char *DataPtr = __orc_rt_CWrapperFunctionResultData(&R);
35 
36   for (size_t I = 0; I != SmallAllocSize; ++I)
37     DataPtr[I] = 0x55 + I;
38 
39   // Check that the inline storage in R.Data.Value contains the expected
40   // sequence.
41   EXPECT_EQ(R.Size, SmallAllocSize);
42   for (size_t I = 0; I != SmallAllocSize; ++I)
43     EXPECT_EQ(R.Data.Value[I], (char)(0x55 + I))
44         << "Unexpected value at index " << I;
45 
46   // Check that this value isn't treated as an out-of-band error.
47   EXPECT_EQ(__orc_rt_CWrapperFunctionResultGetOutOfBandError(&R), nullptr);
48 
49   // Check that __orc_rt_CWrapperFunctionResult(Data|Result|Size) and
50   // __orc_rt_CWrapperFunctionResultGetOutOfBandError behave as expected.
51   EXPECT_EQ(__orc_rt_CWrapperFunctionResultData(&R), R.Data.Value);
52   EXPECT_EQ(__orc_rt_CWrapperFunctionResultSize(&R), SmallAllocSize);
53   EXPECT_FALSE(__orc_rt_CWrapperFunctionResultEmpty(&R));
54   EXPECT_EQ(__orc_rt_CWrapperFunctionResultGetOutOfBandError(&R), nullptr);
55 
56   // Check that we can dispose of the value.
57   __orc_rt_DisposeCWrapperFunctionResult(&R);
58 }
59 
60 TEST(CAPITest, CWrapperFunctionResultAllocLarge) {
61   constexpr size_t LargeAllocSize = sizeof(const char *) + 1;
62 
63   auto R = __orc_rt_CWrapperFunctionResultAllocate(LargeAllocSize);
64   char *DataPtr = __orc_rt_CWrapperFunctionResultData(&R);
65 
66   for (size_t I = 0; I != LargeAllocSize; ++I)
67     DataPtr[I] = 0x55 + I;
68 
69   // Check that the inline storage in R.Data.Value contains the expected
70   // sequence.
71   EXPECT_EQ(R.Size, LargeAllocSize);
72   EXPECT_EQ(R.Data.ValuePtr, DataPtr);
73   for (size_t I = 0; I != LargeAllocSize; ++I)
74     EXPECT_EQ(R.Data.ValuePtr[I], (char)(0x55 + I))
75         << "Unexpected value at index " << I;
76 
77   // Check that this value isn't treated as an out-of-band error.
78   EXPECT_EQ(__orc_rt_CWrapperFunctionResultGetOutOfBandError(&R), nullptr);
79 
80   // Check that __orc_rt_CWrapperFunctionResult(Data|Result|Size) and
81   // __orc_rt_CWrapperFunctionResultGetOutOfBandError behave as expected.
82   EXPECT_EQ(__orc_rt_CWrapperFunctionResultData(&R), R.Data.ValuePtr);
83   EXPECT_EQ(__orc_rt_CWrapperFunctionResultSize(&R), LargeAllocSize);
84   EXPECT_FALSE(__orc_rt_CWrapperFunctionResultEmpty(&R));
85   EXPECT_EQ(__orc_rt_CWrapperFunctionResultGetOutOfBandError(&R), nullptr);
86 
87   // Check that we can dispose of the value.
88   __orc_rt_DisposeCWrapperFunctionResult(&R);
89 }
90 
91 TEST(CAPITest, CWrapperFunctionResultFromRangeSmall) {
92   constexpr size_t SmallAllocSize = sizeof(const char *);
93 
94   char Source[SmallAllocSize];
95   for (size_t I = 0; I != SmallAllocSize; ++I)
96     Source[I] = 0x55 + I;
97 
98   __orc_rt_CWrapperFunctionResult R =
99       __orc_rt_CreateCWrapperFunctionResultFromRange(Source, SmallAllocSize);
100 
101   // Check that the inline storage in R.Data.Value contains the expected
102   // sequence.
103   EXPECT_EQ(R.Size, SmallAllocSize);
104   for (size_t I = 0; I != SmallAllocSize; ++I)
105     EXPECT_EQ(R.Data.Value[I], (char)(0x55 + I))
106         << "Unexpected value at index " << I;
107 
108   // Check that we can dispose of the value.
109   __orc_rt_DisposeCWrapperFunctionResult(&R);
110 }
111 
112 TEST(CAPITest, CWrapperFunctionResultFromRangeLarge) {
113   constexpr size_t LargeAllocSize = sizeof(const char *) + 1;
114 
115   char Source[LargeAllocSize];
116   for (size_t I = 0; I != LargeAllocSize; ++I)
117     Source[I] = 0x55 + I;
118 
119   __orc_rt_CWrapperFunctionResult R =
120       __orc_rt_CreateCWrapperFunctionResultFromRange(Source, LargeAllocSize);
121 
122   // Check that the inline storage in R.Data.Value contains the expected
123   // sequence.
124   EXPECT_EQ(R.Size, LargeAllocSize);
125   for (size_t I = 0; I != LargeAllocSize; ++I)
126     EXPECT_EQ(R.Data.ValuePtr[I], (char)(0x55 + I))
127         << "Unexpected value at index " << I;
128 
129   // Check that we can dispose of the value.
130   __orc_rt_DisposeCWrapperFunctionResult(&R);
131 }
132 
133 TEST(CAPITest, CWrapperFunctionResultFromStringSmall) {
134   constexpr size_t SmallAllocSize = sizeof(const char *);
135 
136   char Source[SmallAllocSize];
137   for (size_t I = 0; I != SmallAllocSize - 1; ++I)
138     Source[I] = 'a' + I;
139   Source[SmallAllocSize - 1] = '\0';
140 
141   __orc_rt_CWrapperFunctionResult R =
142       __orc_rt_CreateCWrapperFunctionResultFromString(Source);
143 
144   // Check that the inline storage in R.Data.Value contains the expected
145   // sequence.
146   EXPECT_EQ(R.Size, SmallAllocSize);
147   for (size_t I = 0; I != SmallAllocSize - 1; ++I)
148     EXPECT_EQ(R.Data.Value[I], (char)('a' + I))
149         << "Unexpected value at index " << I;
150   EXPECT_EQ(R.Data.Value[SmallAllocSize - 1], '\0')
151       << "Unexpected value at index " << (SmallAllocSize - 1);
152 
153   // Check that we can dispose of the value.
154   __orc_rt_DisposeCWrapperFunctionResult(&R);
155 }
156 
157 TEST(CAPITest, CWrapperFunctionResultFromStringLarge) {
158   constexpr size_t LargeAllocSize = sizeof(const char *) + 1;
159 
160   char Source[LargeAllocSize];
161   for (size_t I = 0; I != LargeAllocSize - 1; ++I)
162     Source[I] = 'a' + I;
163   Source[LargeAllocSize - 1] = '\0';
164 
165   __orc_rt_CWrapperFunctionResult R =
166       __orc_rt_CreateCWrapperFunctionResultFromString(Source);
167 
168   // Check that the inline storage in R.Data.Value contains the expected
169   // sequence.
170   EXPECT_EQ(R.Size, LargeAllocSize);
171   for (size_t I = 0; I != LargeAllocSize - 1; ++I)
172     EXPECT_EQ(R.Data.ValuePtr[I], (char)('a' + I))
173         << "Unexpected value at index " << I;
174   EXPECT_EQ(R.Data.ValuePtr[LargeAllocSize - 1], '\0')
175       << "Unexpected value at index " << (LargeAllocSize - 1);
176 
177   // Check that we can dispose of the value.
178   __orc_rt_DisposeCWrapperFunctionResult(&R);
179 }
180 
181 TEST(CAPITest, CWrapperFunctionResultFromOutOfBandError) {
182   constexpr const char *ErrMsg = "test error message";
183   __orc_rt_CWrapperFunctionResult R =
184       __orc_rt_CreateCWrapperFunctionResultFromOutOfBandError(ErrMsg);
185 
186 #ifndef NDEBUG
187   EXPECT_DEATH({ __orc_rt_CWrapperFunctionResultData(&R); },
188                "Cannot get data for out-of-band error value");
189   EXPECT_DEATH({ __orc_rt_CWrapperFunctionResultSize(&R); },
190                "Cannot get size for out-of-band error value");
191 #endif
192 
193   EXPECT_FALSE(__orc_rt_CWrapperFunctionResultEmpty(&R));
194   const char *OOBErrMsg = __orc_rt_CWrapperFunctionResultGetOutOfBandError(&R);
195   EXPECT_NE(OOBErrMsg, nullptr);
196   EXPECT_NE(OOBErrMsg, ErrMsg);
197   EXPECT_TRUE(strcmp(OOBErrMsg, ErrMsg) == 0);
198 
199   __orc_rt_DisposeCWrapperFunctionResult(&R);
200 }
201