xrpld
Loading...
Searching...
No Matches
EscrowCreateTests.cpp
1// Auto-generated unit tests for transaction EscrowCreate
2
3
4#include <gtest/gtest.h>
5
6#include <protocol_autogen/TestHelpers.h>
7
8#include <xrpl/protocol/SecretKey.h>
9#include <xrpl/protocol/Seed.h>
10#include <xrpl/protocol/STTx.h>
11#include <xrpl/protocol_autogen/transactions/EscrowCreate.h>
12#include <xrpl/protocol_autogen/transactions/AccountSet.h>
13
14#include <string>
15
16namespace xrpl::transactions {
17
18// 1 & 4) Set fields via builder setters, build, then read them back via
19// wrapper getters. After build(), validate() should succeed.
20TEST(TransactionsEscrowCreateTests, BuilderSettersRoundTrip)
21{
22 // Generate a deterministic keypair for signing
23 auto const [publicKey, secretKey] =
25
26 // Common transaction fields
27 auto const accountValue = calcAccountID(publicKey);
28 std::uint32_t const sequenceValue = 1;
29 auto const feeValue = canonical_AMOUNT();
30
31 // Transaction-specific field values
32 auto const destinationValue = canonical_ACCOUNT();
33 auto const destinationTagValue = canonical_UINT32();
34 auto const amountValue = canonical_AMOUNT();
35 auto const conditionValue = canonical_VL();
36 auto const cancelAfterValue = canonical_UINT32();
37 auto const finishAfterValue = canonical_UINT32();
38 auto const bytecodeValue = canonical_VL();
39 auto const dataValue = canonical_VL();
40
41 EscrowCreateBuilder builder{
42 accountValue,
43 destinationValue,
44 amountValue,
45 sequenceValue,
46 feeValue
47 };
48
49 // Set optional fields
50 builder.setDestinationTag(destinationTagValue);
51 builder.setCondition(conditionValue);
52 builder.setCancelAfter(cancelAfterValue);
53 builder.setFinishAfter(finishAfterValue);
54 builder.setBytecode(bytecodeValue);
55 builder.setData(dataValue);
56
57 auto tx = builder.build(publicKey, secretKey);
58
59 std::string reason;
60 EXPECT_TRUE(tx.validate(reason)) << reason;
61
62 // Verify signing was applied
63 EXPECT_FALSE(tx.getSigningPubKey().empty());
64 EXPECT_TRUE(tx.hasTxnSignature());
65
66 // Verify common fields
67 EXPECT_EQ(tx.getAccount(), accountValue);
68 EXPECT_EQ(tx.getSequence(), sequenceValue);
69 EXPECT_EQ(tx.getFee(), feeValue);
70
71 // Verify required fields
72 {
73 auto const& expected = destinationValue;
74 auto const actual = tx.getDestination();
75 expectEqualField(expected, actual, "sfDestination");
76 }
77
78 {
79 auto const& expected = amountValue;
80 auto const actual = tx.getAmount();
81 expectEqualField(expected, actual, "sfAmount");
82 }
83
84 // Verify optional fields
85 {
86 auto const& expected = destinationTagValue;
87 auto const actualOpt = tx.getDestinationTag();
88 ASSERT_TRUE(actualOpt.has_value()) << "Optional field sfDestinationTag should be present";
89 expectEqualField(expected, *actualOpt, "sfDestinationTag");
90 EXPECT_TRUE(tx.hasDestinationTag());
91 }
92
93 {
94 auto const& expected = conditionValue;
95 auto const actualOpt = tx.getCondition();
96 ASSERT_TRUE(actualOpt.has_value()) << "Optional field sfCondition should be present";
97 expectEqualField(expected, *actualOpt, "sfCondition");
98 EXPECT_TRUE(tx.hasCondition());
99 }
100
101 {
102 auto const& expected = cancelAfterValue;
103 auto const actualOpt = tx.getCancelAfter();
104 ASSERT_TRUE(actualOpt.has_value()) << "Optional field sfCancelAfter should be present";
105 expectEqualField(expected, *actualOpt, "sfCancelAfter");
106 EXPECT_TRUE(tx.hasCancelAfter());
107 }
108
109 {
110 auto const& expected = finishAfterValue;
111 auto const actualOpt = tx.getFinishAfter();
112 ASSERT_TRUE(actualOpt.has_value()) << "Optional field sfFinishAfter should be present";
113 expectEqualField(expected, *actualOpt, "sfFinishAfter");
114 EXPECT_TRUE(tx.hasFinishAfter());
115 }
116
117 {
118 auto const& expected = bytecodeValue;
119 auto const actualOpt = tx.getBytecode();
120 ASSERT_TRUE(actualOpt.has_value()) << "Optional field sfBytecode should be present";
121 expectEqualField(expected, *actualOpt, "sfBytecode");
122 EXPECT_TRUE(tx.hasBytecode());
123 }
124
125 {
126 auto const& expected = dataValue;
127 auto const actualOpt = tx.getData();
128 ASSERT_TRUE(actualOpt.has_value()) << "Optional field sfData should be present";
129 expectEqualField(expected, *actualOpt, "sfData");
130 EXPECT_TRUE(tx.hasData());
131 }
132
133}
134
135// 2 & 4) Start from an STTx, construct a builder from it, build a new wrapper,
136// and verify all fields match.
137TEST(TransactionsEscrowCreateTests, BuilderFromStTxRoundTrip)
138{
139 // Generate a deterministic keypair for signing
140 auto const [publicKey, secretKey] =
141 generateKeyPair(KeyType::Secp256k1, generateSeed("testEscrowCreateFromTx"));
142
143 // Common transaction fields
144 auto const accountValue = calcAccountID(publicKey);
145 std::uint32_t const sequenceValue = 2;
146 auto const feeValue = canonical_AMOUNT();
147
148 // Transaction-specific field values
149 auto const destinationValue = canonical_ACCOUNT();
150 auto const destinationTagValue = canonical_UINT32();
151 auto const amountValue = canonical_AMOUNT();
152 auto const conditionValue = canonical_VL();
153 auto const cancelAfterValue = canonical_UINT32();
154 auto const finishAfterValue = canonical_UINT32();
155 auto const bytecodeValue = canonical_VL();
156 auto const dataValue = canonical_VL();
157
158 // Build an initial transaction
159 EscrowCreateBuilder initialBuilder{
160 accountValue,
161 destinationValue,
162 amountValue,
163 sequenceValue,
164 feeValue
165 };
166
167 initialBuilder.setDestinationTag(destinationTagValue);
168 initialBuilder.setCondition(conditionValue);
169 initialBuilder.setCancelAfter(cancelAfterValue);
170 initialBuilder.setFinishAfter(finishAfterValue);
171 initialBuilder.setBytecode(bytecodeValue);
172 initialBuilder.setData(dataValue);
173
174 auto initialTx = initialBuilder.build(publicKey, secretKey);
175
176 // Create builder from existing STTx
177 EscrowCreateBuilder builderFromTx{initialTx.getSTTx()};
178
179 auto rebuiltTx = builderFromTx.build(publicKey, secretKey);
180
181 std::string reason;
182 EXPECT_TRUE(rebuiltTx.validate(reason)) << reason;
183
184 // Verify common fields
185 EXPECT_EQ(rebuiltTx.getAccount(), accountValue);
186 EXPECT_EQ(rebuiltTx.getSequence(), sequenceValue);
187 EXPECT_EQ(rebuiltTx.getFee(), feeValue);
188
189 // Verify required fields
190 {
191 auto const& expected = destinationValue;
192 auto const actual = rebuiltTx.getDestination();
193 expectEqualField(expected, actual, "sfDestination");
194 }
195
196 {
197 auto const& expected = amountValue;
198 auto const actual = rebuiltTx.getAmount();
199 expectEqualField(expected, actual, "sfAmount");
200 }
201
202 // Verify optional fields
203 {
204 auto const& expected = destinationTagValue;
205 auto const actualOpt = rebuiltTx.getDestinationTag();
206 ASSERT_TRUE(actualOpt.has_value()) << "Optional field sfDestinationTag should be present";
207 expectEqualField(expected, *actualOpt, "sfDestinationTag");
208 }
209
210 {
211 auto const& expected = conditionValue;
212 auto const actualOpt = rebuiltTx.getCondition();
213 ASSERT_TRUE(actualOpt.has_value()) << "Optional field sfCondition should be present";
214 expectEqualField(expected, *actualOpt, "sfCondition");
215 }
216
217 {
218 auto const& expected = cancelAfterValue;
219 auto const actualOpt = rebuiltTx.getCancelAfter();
220 ASSERT_TRUE(actualOpt.has_value()) << "Optional field sfCancelAfter should be present";
221 expectEqualField(expected, *actualOpt, "sfCancelAfter");
222 }
223
224 {
225 auto const& expected = finishAfterValue;
226 auto const actualOpt = rebuiltTx.getFinishAfter();
227 ASSERT_TRUE(actualOpt.has_value()) << "Optional field sfFinishAfter should be present";
228 expectEqualField(expected, *actualOpt, "sfFinishAfter");
229 }
230
231 {
232 auto const& expected = bytecodeValue;
233 auto const actualOpt = rebuiltTx.getBytecode();
234 ASSERT_TRUE(actualOpt.has_value()) << "Optional field sfBytecode should be present";
235 expectEqualField(expected, *actualOpt, "sfBytecode");
236 }
237
238 {
239 auto const& expected = dataValue;
240 auto const actualOpt = rebuiltTx.getData();
241 ASSERT_TRUE(actualOpt.has_value()) << "Optional field sfData should be present";
242 expectEqualField(expected, *actualOpt, "sfData");
243 }
244
245}
246
247// 3) Verify wrapper throws when constructed from wrong transaction type.
248TEST(TransactionsEscrowCreateTests, WrapperThrowsOnWrongTxType)
249{
250 // Build a valid transaction of a different type
251 auto const [pk, sk] =
253 auto const account = calcAccountID(pk);
254
255 AccountSetBuilder wrongBuilder{account, 1, canonical_AMOUNT()};
256 auto wrongTx = wrongBuilder.build(pk, sk);
257
258 EXPECT_THROW(EscrowCreate{wrongTx.getSTTx()}, std::runtime_error);
259}
260
261// 4) Verify builder throws when constructed from wrong transaction type.
262TEST(TransactionsEscrowCreateTests, BuilderThrowsOnWrongTxType)
263{
264 // Build a valid transaction of a different type
265 auto const [pk, sk] =
266 generateKeyPair(KeyType::Secp256k1, generateSeed("testWrongTypeBuilder"));
267 auto const account = calcAccountID(pk);
268
269 AccountSetBuilder wrongBuilder{account, 1, canonical_AMOUNT()};
270 auto wrongTx = wrongBuilder.build(pk, sk);
271
272 EXPECT_THROW(EscrowCreateBuilder{wrongTx.getSTTx()}, std::runtime_error);
273}
274
275// 5) Build with only required fields and verify optional fields return nullopt.
276TEST(TransactionsEscrowCreateTests, OptionalFieldsReturnNullopt)
277{
278 // Generate a deterministic keypair for signing
279 auto const [publicKey, secretKey] =
280 generateKeyPair(KeyType::Secp256k1, generateSeed("testEscrowCreateNullopt"));
281
282 // Common transaction fields
283 auto const accountValue = calcAccountID(publicKey);
284 std::uint32_t const sequenceValue = 3;
285 auto const feeValue = canonical_AMOUNT();
286
287 // Transaction-specific required field values
288 auto const destinationValue = canonical_ACCOUNT();
289 auto const amountValue = canonical_AMOUNT();
290
291 EscrowCreateBuilder builder{
292 accountValue,
293 destinationValue,
294 amountValue,
295 sequenceValue,
296 feeValue
297 };
298
299 // Do NOT set optional fields
300
301 auto tx = builder.build(publicKey, secretKey);
302
303 // Verify optional fields are not present
304 EXPECT_FALSE(tx.hasDestinationTag());
305 EXPECT_FALSE(tx.getDestinationTag().has_value());
306 EXPECT_FALSE(tx.hasCondition());
307 EXPECT_FALSE(tx.getCondition().has_value());
308 EXPECT_FALSE(tx.hasCancelAfter());
309 EXPECT_FALSE(tx.getCancelAfter().has_value());
310 EXPECT_FALSE(tx.hasFinishAfter());
311 EXPECT_FALSE(tx.getFinishAfter().has_value());
312 EXPECT_FALSE(tx.hasBytecode());
313 EXPECT_FALSE(tx.getBytecode().has_value());
314 EXPECT_FALSE(tx.hasData());
315 EXPECT_FALSE(tx.getData().has_value());
316}
317
318}
AccountSet build(PublicKey const &publicKey, SecretKey const &secretKey)
Build and return the AccountSet wrapper.
EscrowCreateBuilder & setCondition(std::decay_t< typename SF_VL::type::value_type > const &value)
Set sfCondition (SoeOptional).
EscrowCreateBuilder & setDestinationTag(std::decay_t< typename SF_UINT32::type::value_type > const &value)
Set sfDestinationTag (SoeOptional).
EscrowCreateBuilder & setBytecode(std::decay_t< typename SF_VL::type::value_type > const &value)
Set sfBytecode (SoeOptional).
EscrowCreateBuilder & setFinishAfter(std::decay_t< typename SF_UINT32::type::value_type > const &value)
Set sfFinishAfter (SoeOptional).
EscrowCreate build(PublicKey const &publicKey, SecretKey const &secretKey)
Build and return the EscrowCreate wrapper.
EscrowCreateBuilder & setData(std::decay_t< typename SF_VL::type::value_type > const &value)
Set sfData (SoeOptional).
EscrowCreateBuilder & setCancelAfter(std::decay_t< typename SF_UINT32::type::value_type > const &value)
Set sfCancelAfter (SoeOptional).
TEST(TransactionsAccountDeleteTests, BuilderSettersRoundTrip)
Seed generateSeed(std::string const &passPhrase)
Generate a seed deterministically.
Definition Seed.cpp:58
std::pair< PublicKey, SecretKey > generateKeyPair(KeyType type, Seed const &seed)
Generate a key pair deterministically.
AccountID calcAccountID(PublicKey const &pk)
void expectEqualField(T const &expected, T const &actual, char const *fieldName)