Add cli deploy tests (#15116)
This commit is contained in:
@ -1554,7 +1554,7 @@ impl fmt::Display for CliUpgradeableProgram {
|
|||||||
pub struct CliUpgradeableBuffer {
|
pub struct CliUpgradeableBuffer {
|
||||||
pub address: String,
|
pub address: String,
|
||||||
pub authority: String,
|
pub authority: String,
|
||||||
pub program_len: usize,
|
pub data_len: usize,
|
||||||
}
|
}
|
||||||
impl QuietDisplay for CliUpgradeableBuffer {}
|
impl QuietDisplay for CliUpgradeableBuffer {}
|
||||||
impl VerboseDisplay for CliUpgradeableBuffer {}
|
impl VerboseDisplay for CliUpgradeableBuffer {}
|
||||||
@ -1565,8 +1565,8 @@ impl fmt::Display for CliUpgradeableBuffer {
|
|||||||
writeln_name_value(f, "Authority:", &self.authority)?;
|
writeln_name_value(f, "Authority:", &self.authority)?;
|
||||||
writeln_name_value(
|
writeln_name_value(
|
||||||
f,
|
f,
|
||||||
"Program Length:",
|
"Data Length:",
|
||||||
&format!("{:?} ({:#x?}) bytes", self.program_len, self.program_len),
|
&format!("{:?} ({:#x?}) bytes", self.data_len, self.data_len),
|
||||||
)?;
|
)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -973,7 +973,7 @@ fn process_show(
|
|||||||
authority: authority_address
|
authority: authority_address
|
||||||
.map(|pubkey| pubkey.to_string())
|
.map(|pubkey| pubkey.to_string())
|
||||||
.unwrap_or_else(|| "none".to_string()),
|
.unwrap_or_else(|| "none".to_string()),
|
||||||
program_len: account.data.len()
|
data_len: account.data.len()
|
||||||
- UpgradeableLoaderState::buffer_data_offset()?,
|
- UpgradeableLoaderState::buffer_data_offset()?,
|
||||||
}))
|
}))
|
||||||
} else {
|
} else {
|
||||||
|
@ -15,7 +15,7 @@ use solana_sdk::{
|
|||||||
pubkey::Pubkey,
|
pubkey::Pubkey,
|
||||||
signature::{Keypair, Signer},
|
signature::{Keypair, Signer},
|
||||||
};
|
};
|
||||||
use std::{fs::File, io::Read, path::PathBuf, str::FromStr};
|
use std::{env, fs::File, io::Read, path::PathBuf, str::FromStr};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_cli_program_deploy_non_upgradeable() {
|
fn test_cli_program_deploy_non_upgradeable() {
|
||||||
@ -438,6 +438,25 @@ fn test_cli_program_deploy_with_authority() {
|
|||||||
program_data[..]
|
program_data[..]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Get upgrade authority
|
||||||
|
config.signers = vec![&keypair];
|
||||||
|
config.command = CliCommand::Program(ProgramCliCommand::Show {
|
||||||
|
account_pubkey: Some(program_pubkey),
|
||||||
|
});
|
||||||
|
let response = process_command(&config);
|
||||||
|
let json: Value = serde_json::from_str(&response.unwrap()).unwrap();
|
||||||
|
let authority_pubkey_str = json
|
||||||
|
.as_object()
|
||||||
|
.unwrap()
|
||||||
|
.get("authority")
|
||||||
|
.unwrap()
|
||||||
|
.as_str()
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
new_upgrade_authority.pubkey(),
|
||||||
|
Pubkey::from_str(&authority_pubkey_str).unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
// Set no authority
|
// Set no authority
|
||||||
config.signers = vec![&keypair, &new_upgrade_authority];
|
config.signers = vec![&keypair, &new_upgrade_authority];
|
||||||
config.command = CliCommand::Program(ProgramCliCommand::SetUpgradeAuthority {
|
config.command = CliCommand::Program(ProgramCliCommand::SetUpgradeAuthority {
|
||||||
@ -506,6 +525,22 @@ fn test_cli_program_deploy_with_authority() {
|
|||||||
} else {
|
} else {
|
||||||
panic!("not a buffer account");
|
panic!("not a buffer account");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get buffer authority
|
||||||
|
config.signers = vec![&keypair];
|
||||||
|
config.command = CliCommand::Program(ProgramCliCommand::Show {
|
||||||
|
account_pubkey: Some(program_pubkey),
|
||||||
|
});
|
||||||
|
let response = process_command(&config);
|
||||||
|
let json: Value = serde_json::from_str(&response.unwrap()).unwrap();
|
||||||
|
let authority_pubkey_str = json
|
||||||
|
.as_object()
|
||||||
|
.unwrap()
|
||||||
|
.get("authority")
|
||||||
|
.unwrap()
|
||||||
|
.as_str()
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!("none", authority_pubkey_str);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -621,6 +656,25 @@ fn test_cli_program_write_buffer() {
|
|||||||
program_data[..]
|
program_data[..]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Get buffer authority
|
||||||
|
config.signers = vec![&keypair];
|
||||||
|
config.command = CliCommand::Program(ProgramCliCommand::Show {
|
||||||
|
account_pubkey: Some(buffer_keypair.pubkey()),
|
||||||
|
});
|
||||||
|
let response = process_command(&config);
|
||||||
|
let json: Value = serde_json::from_str(&response.unwrap()).unwrap();
|
||||||
|
let authority_pubkey_str = json
|
||||||
|
.as_object()
|
||||||
|
.unwrap()
|
||||||
|
.get("authority")
|
||||||
|
.unwrap()
|
||||||
|
.as_str()
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
keypair.pubkey(),
|
||||||
|
Pubkey::from_str(&authority_pubkey_str).unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
// Specify buffer authority
|
// Specify buffer authority
|
||||||
let buffer_keypair = Keypair::new();
|
let buffer_keypair = Keypair::new();
|
||||||
let authority_keypair = Keypair::new();
|
let authority_keypair = Keypair::new();
|
||||||
@ -691,6 +745,25 @@ fn test_cli_program_write_buffer() {
|
|||||||
buffer_account.data[UpgradeableLoaderState::buffer_data_offset().unwrap()..],
|
buffer_account.data[UpgradeableLoaderState::buffer_data_offset().unwrap()..],
|
||||||
program_data[..]
|
program_data[..]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Get buffer authority
|
||||||
|
config.signers = vec![&keypair];
|
||||||
|
config.command = CliCommand::Program(ProgramCliCommand::Show {
|
||||||
|
account_pubkey: Some(buffer_pubkey),
|
||||||
|
});
|
||||||
|
let response = process_command(&config);
|
||||||
|
let json: Value = serde_json::from_str(&response.unwrap()).unwrap();
|
||||||
|
let authority_pubkey_str = json
|
||||||
|
.as_object()
|
||||||
|
.unwrap()
|
||||||
|
.get("authority")
|
||||||
|
.unwrap()
|
||||||
|
.as_str()
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
authority_keypair.pubkey(),
|
||||||
|
Pubkey::from_str(&authority_pubkey_str).unwrap()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -896,3 +969,253 @@ fn test_cli_program_mismatch_buffer_authority() {
|
|||||||
});
|
});
|
||||||
process_command(&config).unwrap();
|
process_command(&config).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_cli_program_show() {
|
||||||
|
solana_logger::setup();
|
||||||
|
|
||||||
|
let mut pathbuf = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
|
||||||
|
pathbuf.push("tests");
|
||||||
|
pathbuf.push("fixtures");
|
||||||
|
pathbuf.push("noop");
|
||||||
|
pathbuf.set_extension("so");
|
||||||
|
|
||||||
|
let mint_keypair = Keypair::new();
|
||||||
|
let test_validator = TestValidator::with_no_fees(mint_keypair.pubkey());
|
||||||
|
let faucet_addr = run_local_faucet(mint_keypair, None);
|
||||||
|
|
||||||
|
let rpc_client =
|
||||||
|
RpcClient::new_with_commitment(test_validator.rpc_url(), CommitmentConfig::processed());
|
||||||
|
|
||||||
|
let mut file = File::open(pathbuf.to_str().unwrap()).unwrap();
|
||||||
|
let mut program_data = Vec::new();
|
||||||
|
file.read_to_end(&mut program_data).unwrap();
|
||||||
|
let max_len = program_data.len();
|
||||||
|
let minimum_balance_for_buffer = rpc_client
|
||||||
|
.get_minimum_balance_for_rent_exemption(
|
||||||
|
UpgradeableLoaderState::programdata_len(max_len).unwrap(),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let mut config = CliConfig::recent_for_tests();
|
||||||
|
let keypair = Keypair::new();
|
||||||
|
config.json_rpc_url = test_validator.rpc_url();
|
||||||
|
config.output_format = OutputFormat::Json;
|
||||||
|
|
||||||
|
// Airdrop
|
||||||
|
config.signers = vec![&keypair];
|
||||||
|
config.command = CliCommand::Airdrop {
|
||||||
|
faucet_host: None,
|
||||||
|
faucet_port: faucet_addr.port(),
|
||||||
|
pubkey: None,
|
||||||
|
lamports: 100 * minimum_balance_for_buffer,
|
||||||
|
};
|
||||||
|
process_command(&config).unwrap();
|
||||||
|
|
||||||
|
// Write a buffer
|
||||||
|
let buffer_keypair = Keypair::new();
|
||||||
|
let authority_keypair = Keypair::new();
|
||||||
|
config.signers = vec![&keypair, &buffer_keypair, &authority_keypair];
|
||||||
|
config.command = CliCommand::Program(ProgramCliCommand::WriteBuffer {
|
||||||
|
program_location: pathbuf.to_str().unwrap().to_string(),
|
||||||
|
buffer_signer_index: Some(1),
|
||||||
|
buffer_pubkey: Some(buffer_keypair.pubkey()),
|
||||||
|
buffer_authority_signer_index: Some(2),
|
||||||
|
max_len: None,
|
||||||
|
});
|
||||||
|
process_command(&config).unwrap();
|
||||||
|
|
||||||
|
// Verify show
|
||||||
|
config.signers = vec![&keypair];
|
||||||
|
config.command = CliCommand::Program(ProgramCliCommand::Show {
|
||||||
|
account_pubkey: Some(buffer_keypair.pubkey()),
|
||||||
|
});
|
||||||
|
let response = process_command(&config);
|
||||||
|
let json: Value = serde_json::from_str(&response.unwrap()).unwrap();
|
||||||
|
let address_str = json
|
||||||
|
.as_object()
|
||||||
|
.unwrap()
|
||||||
|
.get("address")
|
||||||
|
.unwrap()
|
||||||
|
.as_str()
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
buffer_keypair.pubkey(),
|
||||||
|
Pubkey::from_str(&address_str).unwrap()
|
||||||
|
);
|
||||||
|
let authority_str = json
|
||||||
|
.as_object()
|
||||||
|
.unwrap()
|
||||||
|
.get("authority")
|
||||||
|
.unwrap()
|
||||||
|
.as_str()
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
authority_keypair.pubkey(),
|
||||||
|
Pubkey::from_str(&authority_str).unwrap()
|
||||||
|
);
|
||||||
|
let data_len = json
|
||||||
|
.as_object()
|
||||||
|
.unwrap()
|
||||||
|
.get("dataLen")
|
||||||
|
.unwrap()
|
||||||
|
.as_u64()
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(max_len, data_len as usize);
|
||||||
|
|
||||||
|
// Deploy
|
||||||
|
let program_keypair = Keypair::new();
|
||||||
|
config.signers = vec![&keypair, &authority_keypair, &program_keypair];
|
||||||
|
config.command = CliCommand::Program(ProgramCliCommand::Deploy {
|
||||||
|
program_location: Some(pathbuf.to_str().unwrap().to_string()),
|
||||||
|
program_signer_index: Some(2),
|
||||||
|
program_pubkey: Some(program_keypair.pubkey()),
|
||||||
|
buffer_signer_index: None,
|
||||||
|
buffer_pubkey: None,
|
||||||
|
allow_excessive_balance: false,
|
||||||
|
upgrade_authority_signer_index: 1,
|
||||||
|
is_final: false,
|
||||||
|
max_len: Some(max_len),
|
||||||
|
});
|
||||||
|
config.output_format = OutputFormat::JsonCompact;
|
||||||
|
process_command(&config).unwrap();
|
||||||
|
let slot = rpc_client.get_slot().unwrap();
|
||||||
|
|
||||||
|
// Verify show
|
||||||
|
config.signers = vec![&keypair];
|
||||||
|
config.command = CliCommand::Program(ProgramCliCommand::Show {
|
||||||
|
account_pubkey: Some(program_keypair.pubkey()),
|
||||||
|
});
|
||||||
|
let response = process_command(&config);
|
||||||
|
let json: Value = serde_json::from_str(&response.unwrap()).unwrap();
|
||||||
|
let address_str = json
|
||||||
|
.as_object()
|
||||||
|
.unwrap()
|
||||||
|
.get("programId")
|
||||||
|
.unwrap()
|
||||||
|
.as_str()
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
program_keypair.pubkey(),
|
||||||
|
Pubkey::from_str(&address_str).unwrap()
|
||||||
|
);
|
||||||
|
let programdata_address_str = json
|
||||||
|
.as_object()
|
||||||
|
.unwrap()
|
||||||
|
.get("programdataAddress")
|
||||||
|
.unwrap()
|
||||||
|
.as_str()
|
||||||
|
.unwrap();
|
||||||
|
let (programdata_pubkey, _) = Pubkey::find_program_address(
|
||||||
|
&[program_keypair.pubkey().as_ref()],
|
||||||
|
&bpf_loader_upgradeable::id(),
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
programdata_pubkey,
|
||||||
|
Pubkey::from_str(&programdata_address_str).unwrap()
|
||||||
|
);
|
||||||
|
let authority_str = json
|
||||||
|
.as_object()
|
||||||
|
.unwrap()
|
||||||
|
.get("authority")
|
||||||
|
.unwrap()
|
||||||
|
.as_str()
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
authority_keypair.pubkey(),
|
||||||
|
Pubkey::from_str(&authority_str).unwrap()
|
||||||
|
);
|
||||||
|
let deployed_slot = json
|
||||||
|
.as_object()
|
||||||
|
.unwrap()
|
||||||
|
.get("lastDeploySlot")
|
||||||
|
.unwrap()
|
||||||
|
.as_u64()
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(slot, deployed_slot);
|
||||||
|
let data_len = json
|
||||||
|
.as_object()
|
||||||
|
.unwrap()
|
||||||
|
.get("dataLen")
|
||||||
|
.unwrap()
|
||||||
|
.as_u64()
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(max_len, data_len as usize);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_cli_program_dump() {
|
||||||
|
solana_logger::setup();
|
||||||
|
|
||||||
|
let mut pathbuf = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
|
||||||
|
pathbuf.push("tests");
|
||||||
|
pathbuf.push("fixtures");
|
||||||
|
pathbuf.push("noop");
|
||||||
|
pathbuf.set_extension("so");
|
||||||
|
|
||||||
|
let mint_keypair = Keypair::new();
|
||||||
|
let test_validator = TestValidator::with_no_fees(mint_keypair.pubkey());
|
||||||
|
let faucet_addr = run_local_faucet(mint_keypair, None);
|
||||||
|
|
||||||
|
let rpc_client =
|
||||||
|
RpcClient::new_with_commitment(test_validator.rpc_url(), CommitmentConfig::processed());
|
||||||
|
|
||||||
|
let mut file = File::open(pathbuf.to_str().unwrap()).unwrap();
|
||||||
|
let mut program_data = Vec::new();
|
||||||
|
file.read_to_end(&mut program_data).unwrap();
|
||||||
|
let max_len = program_data.len();
|
||||||
|
let minimum_balance_for_buffer = rpc_client
|
||||||
|
.get_minimum_balance_for_rent_exemption(
|
||||||
|
UpgradeableLoaderState::programdata_len(max_len).unwrap(),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let mut config = CliConfig::recent_for_tests();
|
||||||
|
let keypair = Keypair::new();
|
||||||
|
config.json_rpc_url = test_validator.rpc_url();
|
||||||
|
config.output_format = OutputFormat::Json;
|
||||||
|
|
||||||
|
// Airdrop
|
||||||
|
config.signers = vec![&keypair];
|
||||||
|
config.command = CliCommand::Airdrop {
|
||||||
|
faucet_host: None,
|
||||||
|
faucet_port: faucet_addr.port(),
|
||||||
|
pubkey: None,
|
||||||
|
lamports: 100 * minimum_balance_for_buffer,
|
||||||
|
};
|
||||||
|
process_command(&config).unwrap();
|
||||||
|
|
||||||
|
// Write a buffer
|
||||||
|
let buffer_keypair = Keypair::new();
|
||||||
|
let authority_keypair = Keypair::new();
|
||||||
|
config.signers = vec![&keypair, &buffer_keypair, &authority_keypair];
|
||||||
|
config.command = CliCommand::Program(ProgramCliCommand::WriteBuffer {
|
||||||
|
program_location: pathbuf.to_str().unwrap().to_string(),
|
||||||
|
buffer_signer_index: Some(1),
|
||||||
|
buffer_pubkey: Some(buffer_keypair.pubkey()),
|
||||||
|
buffer_authority_signer_index: Some(2),
|
||||||
|
max_len: None,
|
||||||
|
});
|
||||||
|
process_command(&config).unwrap();
|
||||||
|
|
||||||
|
// Verify dump
|
||||||
|
let mut out_file = {
|
||||||
|
let current_exe = env::current_exe().unwrap();
|
||||||
|
PathBuf::from(current_exe.parent().unwrap().parent().unwrap())
|
||||||
|
};
|
||||||
|
out_file.set_file_name("out.txt");
|
||||||
|
config.signers = vec![&keypair];
|
||||||
|
config.command = CliCommand::Program(ProgramCliCommand::Dump {
|
||||||
|
account_pubkey: Some(buffer_keypair.pubkey()),
|
||||||
|
output_location: out_file.clone().into_os_string().into_string().unwrap(),
|
||||||
|
});
|
||||||
|
process_command(&config).unwrap();
|
||||||
|
|
||||||
|
let mut file = File::open(out_file).unwrap();
|
||||||
|
let mut out_data = Vec::new();
|
||||||
|
file.read_to_end(&mut out_data).unwrap();
|
||||||
|
assert_eq!(program_data.len(), out_data.len());
|
||||||
|
for i in 0..program_data.len() {
|
||||||
|
assert_eq!(program_data[i], out_data[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user