Browse Source

cli: Support upgradeable program in anchor test (#2642)

Resolves #2641
Nick Guo 2 years ago
parent
commit
5602244e1a
4 changed files with 47 additions and 6 deletions
  1. 1 0
      CHANGELOG.md
  2. 7 0
      cli/src/config.rs
  3. 25 6
      cli/src/lib.rs
  4. 14 0
      docs/src/pages/docs/manifest.md

+ 1 - 0
CHANGELOG.md

@@ -29,6 +29,7 @@ The minor version will be incremented upon a breaking change and the patch versi
 - syn: Add `IdlBuild` trait to implement IDL support for custom types ([#2629](https://github.com/coral-xyz/anchor/pull/2629)).
 - syn: Add `IdlBuild` trait to implement IDL support for custom types ([#2629](https://github.com/coral-xyz/anchor/pull/2629)).
 - spl: Add `idl-build` feature. IDL build method will not work without enabling this feature when using `anchor-spl` ([#2629](https://github.com/coral-xyz/anchor/pull/2629)).
 - spl: Add `idl-build` feature. IDL build method will not work without enabling this feature when using `anchor-spl` ([#2629](https://github.com/coral-xyz/anchor/pull/2629)).
 - lang: Add support for type aliases in IDLs ([#2637](https://github.com/coral-xyz/anchor/pull/2637)).
 - lang: Add support for type aliases in IDLs ([#2637](https://github.com/coral-xyz/anchor/pull/2637)).
+- cli: Add `test.upgradeable`, `test.genesis.upgradeable` setting in anchor.toml to support testing upgradeable programs ([#2641](https://github.com/coral-xyz/anchor/pull/2642)).
 
 
 ### Fixes
 ### Fixes
 
 

+ 7 - 0
cli/src/config.rs

@@ -706,6 +706,7 @@ pub struct TestValidator {
     pub validator: Option<Validator>,
     pub validator: Option<Validator>,
     pub startup_wait: i32,
     pub startup_wait: i32,
     pub shutdown_wait: i32,
     pub shutdown_wait: i32,
+    pub upgradeable: bool,
 }
 }
 
 
 #[derive(Default, Debug, Clone, Serialize, Deserialize)]
 #[derive(Default, Debug, Clone, Serialize, Deserialize)]
@@ -718,6 +719,8 @@ pub struct _TestValidator {
     pub startup_wait: Option<i32>,
     pub startup_wait: Option<i32>,
     #[serde(skip_serializing_if = "Option::is_none")]
     #[serde(skip_serializing_if = "Option::is_none")]
     pub shutdown_wait: Option<i32>,
     pub shutdown_wait: Option<i32>,
+    #[serde(skip_serializing_if = "Option::is_none")]
+    pub upgradeable: Option<bool>,
 }
 }
 
 
 pub const STARTUP_WAIT: i32 = 5000;
 pub const STARTUP_WAIT: i32 = 5000;
@@ -730,6 +733,7 @@ impl From<_TestValidator> for TestValidator {
             startup_wait: _test_validator.startup_wait.unwrap_or(STARTUP_WAIT),
             startup_wait: _test_validator.startup_wait.unwrap_or(STARTUP_WAIT),
             genesis: _test_validator.genesis,
             genesis: _test_validator.genesis,
             validator: _test_validator.validator.map(Into::into),
             validator: _test_validator.validator.map(Into::into),
+            upgradeable: _test_validator.upgradeable.unwrap_or(false),
         }
         }
     }
     }
 }
 }
@@ -741,6 +745,7 @@ impl From<TestValidator> for _TestValidator {
             startup_wait: Some(test_validator.startup_wait),
             startup_wait: Some(test_validator.startup_wait),
             genesis: test_validator.genesis,
             genesis: test_validator.genesis,
             validator: test_validator.validator.map(Into::into),
             validator: test_validator.validator.map(Into::into),
+            upgradeable: Some(test_validator.upgradeable),
         }
         }
     }
     }
 }
 }
@@ -949,6 +954,8 @@ pub struct GenesisEntry {
     pub address: String,
     pub address: String,
     // Filepath to the compiled program to embed into the genesis.
     // Filepath to the compiled program to embed into the genesis.
     pub program: String,
     pub program: String,
+    // Whether the genesis program is upgradeable.
+    pub upgradeable: Option<bool>,
 }
 }
 
 
 #[derive(Debug, Clone, Serialize, Deserialize)]
 #[derive(Debug, Clone, Serialize, Deserialize)]

+ 25 - 6
cli/src/lib.rs

@@ -3025,6 +3025,11 @@ fn validator_flags(
 ) -> Result<Vec<String>> {
 ) -> Result<Vec<String>> {
     let programs = cfg.programs.get(&Cluster::Localnet);
     let programs = cfg.programs.get(&Cluster::Localnet);
 
 
+    let test_upgradeable_program = test_validator
+        .as_ref()
+        .map(|test_validator| test_validator.upgradeable)
+        .unwrap_or(false);
+
     let mut flags = Vec::new();
     let mut flags = Vec::new();
     for mut program in cfg.read_all_programs()? {
     for mut program in cfg.read_all_programs()? {
         let binary_path = program.binary_path().display().to_string();
         let binary_path = program.binary_path().display().to_string();
@@ -3036,9 +3041,16 @@ fn validator_flags(
             .map(|deployment| Ok(deployment.address.to_string()))
             .map(|deployment| Ok(deployment.address.to_string()))
             .unwrap_or_else(|| program.pubkey().map(|p| p.to_string()))?;
             .unwrap_or_else(|| program.pubkey().map(|p| p.to_string()))?;
 
 
-        flags.push("--bpf-program".to_string());
-        flags.push(address.clone());
-        flags.push(binary_path);
+        if test_upgradeable_program {
+            flags.push("--upgradeable-program".to_string());
+            flags.push(address.clone());
+            flags.push(binary_path);
+            flags.push(cfg.wallet_kp()?.pubkey().to_string());
+        } else {
+            flags.push("--bpf-program".to_string());
+            flags.push(address.clone());
+            flags.push(binary_path);
+        }
 
 
         if let Some(idl) = program.idl.as_mut() {
         if let Some(idl) = program.idl.as_mut() {
             // Add program address to the IDL.
             // Add program address to the IDL.
@@ -3062,9 +3074,16 @@ fn validator_flags(
                         program_path.display()
                         program_path.display()
                     ));
                     ));
                 }
                 }
-                flags.push("--bpf-program".to_string());
-                flags.push(entry.address.clone());
-                flags.push(entry.program.clone());
+                if entry.upgradeable.unwrap_or(false) {
+                    flags.push("--upgradeable-program".to_string());
+                    flags.push(entry.address.clone());
+                    flags.push(entry.program.clone());
+                    flags.push(cfg.wallet_kp()?.pubkey().to_string());
+                } else {
+                    flags.push("--bpf-program".to_string());
+                    flags.push(entry.address.clone());
+                    flags.push(entry.program.clone());
+                }
             }
             }
         }
         }
         if let Some(validator) = &test.validator {
         if let Some(validator) = &test.validator {

+ 14 - 0
docs/src/pages/docs/manifest.md

@@ -122,6 +122,20 @@ program = "dex.so"
 [[test.genesis]]
 [[test.genesis]]
 address = "22Y43yTVxuUkoRKdm9thyRhQ3SdgQS7c7kB6UNCiaczD"
 address = "22Y43yTVxuUkoRKdm9thyRhQ3SdgQS7c7kB6UNCiaczD"
 program = "swap.so"
 program = "swap.so"
+upgradeable = true
+```
+
+#### upgradeable
+
+Deploys the program-to-test using `--upgradeable-program`. This makes it possible to test that certain instructions can only be executed by the program's upgrade authority. The initial upgrade authority will be set to `provider.wallet`.
+
+If unspecified or explicitly set to false, then the test program will be deployed with `--bpf-program`, disabling upgrades to it.
+
+Example:
+
+```toml
+[test]
+upgradeable = true
 ```
 ```
 
 
 ## test.validator
 ## test.validator