10
10
signature:: { Keypair , Signer } ,
11
11
system_instruction:: { self , SystemError , MAX_PERMITTED_DATA_LENGTH } ,
12
12
system_program,
13
- transaction:: Transaction ,
13
+ transaction:: { Transaction , TransactionError } ,
14
14
} ,
15
15
} ;
16
16
@@ -19,10 +19,11 @@ mod common;
19
19
#[ tokio:: test]
20
20
async fn test_extend_program ( ) {
21
21
let mut context = setup_test_context ( ) . await ;
22
+ let program_file = find_file ( "noop.so" ) . expect ( "Failed to find the file" ) ;
23
+ let data = read_file ( program_file) ;
22
24
23
25
let program_address = Pubkey :: new_unique ( ) ;
24
26
let ( programdata_address, _) = Pubkey :: find_program_address ( & [ program_address. as_ref ( ) ] , & id ( ) ) ;
25
- let program_data_len = 100 ;
26
27
add_upgradeable_loader_account (
27
28
& mut context,
28
29
& program_address,
@@ -33,6 +34,8 @@ async fn test_extend_program() {
33
34
|_| { } ,
34
35
)
35
36
. await ;
37
+ let programdata_data_offset = UpgradeableLoaderState :: size_of_programdata_metadata ( ) ;
38
+ let program_data_len = data. len ( ) + programdata_data_offset;
36
39
add_upgradeable_loader_account (
37
40
& mut context,
38
41
& programdata_address,
@@ -41,9 +44,68 @@ async fn test_extend_program() {
41
44
upgrade_authority_address : Some ( Pubkey :: new_unique ( ) ) ,
42
45
} ,
43
46
program_data_len,
47
+ |account| account. data_as_mut_slice ( ) [ programdata_data_offset..] . copy_from_slice ( & data) ,
48
+ )
49
+ . await ;
50
+
51
+ let client = & mut context. banks_client ;
52
+ let payer = & context. payer ;
53
+ let recent_blockhash = context. last_blockhash ;
54
+ const ADDITIONAL_BYTES : u32 = 42 ;
55
+ let transaction = Transaction :: new_signed_with_payer (
56
+ & [ extend_program (
57
+ & program_address,
58
+ Some ( & payer. pubkey ( ) ) ,
59
+ ADDITIONAL_BYTES ,
60
+ ) ] ,
61
+ Some ( & payer. pubkey ( ) ) ,
62
+ & [ payer] ,
63
+ recent_blockhash,
64
+ ) ;
65
+
66
+ assert_matches ! ( client. process_transaction( transaction) . await , Ok ( ( ) ) ) ;
67
+ let updated_program_data_account = client
68
+ . get_account ( programdata_address)
69
+ . await
70
+ . unwrap ( )
71
+ . unwrap ( ) ;
72
+ assert_eq ! (
73
+ updated_program_data_account. data( ) . len( ) ,
74
+ program_data_len + ADDITIONAL_BYTES as usize
75
+ ) ;
76
+ }
77
+
78
+ #[ tokio:: test]
79
+ async fn test_failed_extend_twice_in_same_slot ( ) {
80
+ let mut context = setup_test_context ( ) . await ;
81
+ let program_file = find_file ( "noop.so" ) . expect ( "Failed to find the file" ) ;
82
+ let data = read_file ( program_file) ;
83
+
84
+ let program_address = Pubkey :: new_unique ( ) ;
85
+ let ( programdata_address, _) = Pubkey :: find_program_address ( & [ program_address. as_ref ( ) ] , & id ( ) ) ;
86
+ add_upgradeable_loader_account (
87
+ & mut context,
88
+ & program_address,
89
+ & UpgradeableLoaderState :: Program {
90
+ programdata_address,
91
+ } ,
92
+ UpgradeableLoaderState :: size_of_program ( ) ,
44
93
|_| { } ,
45
94
)
46
95
. await ;
96
+ let programdata_data_offset = UpgradeableLoaderState :: size_of_programdata_metadata ( ) ;
97
+ let program_data_len = data. len ( ) + programdata_data_offset;
98
+ add_upgradeable_loader_account (
99
+ & mut context,
100
+ & programdata_address,
101
+ & UpgradeableLoaderState :: ProgramData {
102
+ slot : 0 ,
103
+ upgrade_authority_address : Some ( Pubkey :: new_unique ( ) ) ,
104
+ } ,
105
+ program_data_len,
106
+ |account| account. data_as_mut_slice ( ) [ programdata_data_offset..] . copy_from_slice ( & data) ,
107
+ )
108
+ . await ;
47
109
48
110
let client = & mut context. banks_client ;
49
111
let payer = & context. payer ;
@@ -70,6 +132,31 @@ async fn test_extend_program() {
70
132
updated_program_data_account. data( ) . len( ) ,
71
133
program_data_len + ADDITIONAL_BYTES as usize
72
134
) ;
135
+
136
+ let recent_blockhash = client
137
+ . get_new_latest_blockhash ( & recent_blockhash)
138
+ . await
139
+ . unwrap ( ) ;
140
+ // Extending the program in the same slot should fail
141
+ let transaction = Transaction :: new_signed_with_payer (
142
+ & [ extend_program (
143
+ & program_address,
144
+ Some ( & payer. pubkey ( ) ) ,
145
+ ADDITIONAL_BYTES ,
146
+ ) ] ,
147
+ Some ( & payer. pubkey ( ) ) ,
148
+ & [ payer] ,
149
+ recent_blockhash,
150
+ ) ;
151
+
152
+ assert_matches ! (
153
+ client
154
+ . process_transaction( transaction)
155
+ . await
156
+ . unwrap_err( )
157
+ . unwrap( ) ,
158
+ TransactionError :: InstructionError ( 0 , InstructionError :: InvalidArgument )
159
+ ) ;
73
160
}
74
161
75
162
#[ tokio:: test]
@@ -293,6 +380,9 @@ async fn test_extend_program_without_payer() {
293
380
let mut context = setup_test_context ( ) . await ;
294
381
let rent = context. banks_client . get_rent ( ) . await . unwrap ( ) ;
295
382
383
+ let program_file = find_file ( "noop.so" ) . expect ( "Failed to find the file" ) ;
384
+ let data = read_file ( program_file) ;
385
+
296
386
let program_address = Pubkey :: new_unique ( ) ;
297
387
let ( programdata_address, _) = Pubkey :: find_program_address ( & [ program_address. as_ref ( ) ] , & id ( ) ) ;
298
388
add_upgradeable_loader_account (
@@ -305,7 +395,8 @@ async fn test_extend_program_without_payer() {
305
395
|_| { } ,
306
396
)
307
397
. await ;
308
- let program_data_len = 100 ;
398
+ let programdata_data_offset = UpgradeableLoaderState :: size_of_programdata_metadata ( ) ;
399
+ let program_data_len = data. len ( ) + programdata_data_offset;
309
400
add_upgradeable_loader_account (
310
401
& mut context,
311
402
& programdata_address,
@@ -314,7 +405,7 @@ async fn test_extend_program_without_payer() {
314
405
upgrade_authority_address : Some ( Pubkey :: new_unique ( ) ) ,
315
406
} ,
316
407
program_data_len,
317
- |_| { } ,
408
+ |account| account . data_as_mut_slice ( ) [ programdata_data_offset.. ] . copy_from_slice ( & data ) ,
318
409
)
319
410
. await ;
320
411
0 commit comments