add tests
This commit is contained in:
parent
ecad170937
commit
a8acf640c0
|
@ -41,7 +41,7 @@ pub fn read_data_mut(account_data: &mut [u8]) -> &mut [u8] {
|
|||
pub fn write_discriminator(account_data: &mut [u8], discriminator: &[u8]) {
|
||||
#[cfg(feature = "deprecated-layout")]
|
||||
{
|
||||
let mut cursor = Cursor::new(account_dst);
|
||||
let mut cursor = Cursor::new(account_data);
|
||||
cursor.write_all(discriminator).unwrap();
|
||||
}
|
||||
#[cfg(not(feature = "deprecated-layout"))]
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
|
||||
.anchor
|
||||
.DS_Store
|
||||
target
|
||||
**/*.rs.bk
|
||||
node_modules
|
|
@ -0,0 +1,16 @@
|
|||
[features]
|
||||
seeds = false
|
||||
|
||||
[programs.localnet]
|
||||
deprecated_layout = "Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS"
|
||||
new_layout = "9LA72twzmEHH6EH8oEiNnb2CsUdN9CqAtDNXCkj1c9Uw"
|
||||
|
||||
[registry]
|
||||
url = "https://anchor.projectserum.com"
|
||||
|
||||
[provider]
|
||||
cluster = "localnet"
|
||||
wallet = "/home/armaniferrante/.config/solana/id.json"
|
||||
|
||||
[scripts]
|
||||
test = "yarn run ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts"
|
|
@ -0,0 +1,4 @@
|
|||
[workspace]
|
||||
members = [
|
||||
"programs/*"
|
||||
]
|
|
@ -0,0 +1,12 @@
|
|||
// Migrations are an early feature. Currently, they're nothing more than this
|
||||
// single deploy script that's invoked from the CLI, injecting a provider
|
||||
// configured from the workspace's Anchor.toml.
|
||||
|
||||
const anchor = require("@project-serum/anchor");
|
||||
|
||||
module.exports = async function (provider) {
|
||||
// Configure client to use the provider.
|
||||
anchor.setProvider(provider);
|
||||
|
||||
// Add your deploy script here.
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
"name": "deprecated-layout",
|
||||
"version": "0.21.0",
|
||||
"license": "(MIT OR Apache-2.0)",
|
||||
"homepage": "https://github.com/project-serum/anchor#readme",
|
||||
"bugs": {
|
||||
"url": "https://github.com/project-serum/anchor/issues"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/project-serum/anchor.git"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=11"
|
||||
},
|
||||
"dependencies": {
|
||||
"@project-serum/anchor": "^0.21.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"chai": "^4.3.4",
|
||||
"mocha": "^9.0.3",
|
||||
"ts-mocha": "^8.0.0",
|
||||
"@types/mocha": "^9.0.0",
|
||||
"typescript": "^4.3.5"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
[package]
|
||||
name = "deprecated-layout"
|
||||
version = "0.1.0"
|
||||
description = "Created with Anchor"
|
||||
edition = "2018"
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib", "lib"]
|
||||
name = "deprecated_layout"
|
||||
|
||||
[features]
|
||||
no-entrypoint = []
|
||||
no-idl = []
|
||||
no-log-ix-name = []
|
||||
cpi = ["no-entrypoint"]
|
||||
default = []
|
||||
|
||||
[dependencies]
|
||||
anchor-lang = { path = "../../../../lang", features = ["deprecated-layout"] }
|
|
@ -0,0 +1,2 @@
|
|||
[target.bpfel-unknown-unknown.dependencies.std]
|
||||
features = []
|
|
@ -0,0 +1,31 @@
|
|||
use anchor_lang::prelude::*;
|
||||
|
||||
declare_id!("Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS");
|
||||
|
||||
#[program]
|
||||
pub mod deprecated_layout {
|
||||
use super::*;
|
||||
|
||||
pub fn initialize(ctx: Context<Initialize>) -> ProgramResult {
|
||||
ctx.accounts.data.data = 2;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Accounts)]
|
||||
pub struct Initialize<'info> {
|
||||
#[account(
|
||||
init,
|
||||
payer = payer,
|
||||
space = 16,
|
||||
)]
|
||||
data: Account<'info, Data>,
|
||||
#[account(mut)]
|
||||
payer: Signer<'info>,
|
||||
system_program: Program<'info, System>,
|
||||
}
|
||||
|
||||
#[account]
|
||||
pub struct Data {
|
||||
data: u64,
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
[package]
|
||||
name = "new-layout"
|
||||
version = "0.1.0"
|
||||
description = "Created with Anchor"
|
||||
edition = "2018"
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib", "lib"]
|
||||
name = "new_layout"
|
||||
|
||||
[features]
|
||||
no-entrypoint = []
|
||||
no-idl = []
|
||||
no-log-ix-name = []
|
||||
cpi = ["no-entrypoint"]
|
||||
default = []
|
||||
|
||||
[dependencies]
|
||||
anchor-lang = { path = "../../../../lang" }
|
|
@ -0,0 +1,2 @@
|
|||
[target.bpfel-unknown-unknown.dependencies.std]
|
||||
features = []
|
|
@ -0,0 +1,31 @@
|
|||
use anchor_lang::prelude::*;
|
||||
|
||||
declare_id!("9LA72twzmEHH6EH8oEiNnb2CsUdN9CqAtDNXCkj1c9Uw");
|
||||
|
||||
#[program]
|
||||
pub mod new_layout {
|
||||
use super::*;
|
||||
|
||||
pub fn initialize(ctx: Context<Initialize>) -> ProgramResult {
|
||||
ctx.accounts.data.data = 2;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Accounts)]
|
||||
pub struct Initialize<'info> {
|
||||
#[account(
|
||||
init,
|
||||
payer = payer,
|
||||
space = 16,
|
||||
)]
|
||||
data: Account<'info, Data>,
|
||||
#[account(mut)]
|
||||
payer: Signer<'info>,
|
||||
system_program: Program<'info, System>,
|
||||
}
|
||||
|
||||
#[account]
|
||||
pub struct Data {
|
||||
data: u64,
|
||||
}
|
|
@ -0,0 +1,100 @@
|
|||
import * as assert from "assert";
|
||||
//import * as anchor from '@project-serum/anchor';
|
||||
//import { Program, BorshAccountHeader } from '@project-serum/anchor';
|
||||
import * as anchor from "../../../ts";
|
||||
import { Program, BorshAccountHeader } from "../../../ts";
|
||||
import { Keypair } from "@solana/web3.js";
|
||||
import { DeprecatedLayout } from "../target/types/deprecated_layout";
|
||||
import { NewLayout } from "../target/types/new_layout";
|
||||
|
||||
describe("deprecated-layout", () => {
|
||||
// Configure the client to use the local cluster.
|
||||
anchor.setProvider(anchor.Provider.env());
|
||||
|
||||
it("Has an 8 byte discriminator", async () => {
|
||||
anchor.utils.features.set("deprecated-layout");
|
||||
|
||||
const program = anchor.workspace
|
||||
.DeprecatedLayout as Program<DeprecatedLayout>;
|
||||
|
||||
const dataKeypair = Keypair.generate();
|
||||
await program.methods
|
||||
.initialize()
|
||||
.accounts({ data: dataKeypair.publicKey })
|
||||
.signers([dataKeypair])
|
||||
.rpc();
|
||||
const accountInfo = await program.account.data.getAccountInfo(
|
||||
dataKeypair.publicKey
|
||||
);
|
||||
const data = accountInfo.data;
|
||||
const header = data.slice(0, 8);
|
||||
const accountData = data.slice(8);
|
||||
const expectedDiscriminator = BorshAccountHeader.discriminator("data");
|
||||
|
||||
assert.ok(
|
||||
"0xce9c3bbc124ff0e8" ===
|
||||
anchor.utils.bytes.hex.encode(expectedDiscriminator)
|
||||
);
|
||||
assert.ok(expectedDiscriminator.length === 8);
|
||||
assert.ok(header.compare(expectedDiscriminator) === 0);
|
||||
assert.ok(accountData.compare(Buffer.from([2, 0, 0, 0, 0, 0, 0, 0])) === 0);
|
||||
|
||||
const dataAccount = await program.account.data.fetch(dataKeypair.publicKey);
|
||||
assert.ok(dataAccount.data.toNumber() === 2);
|
||||
|
||||
assert.rejects(
|
||||
async () => {
|
||||
anchor.utils.features.unset("deprecated-layout");
|
||||
await program.account.data.fetch(dataKeypair.publicKey);
|
||||
},
|
||||
(err) => {
|
||||
return err.toString() === "Error: Invalid account discriminator";
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it("Has a 4 byte discriminator and 8 byte header", async () => {
|
||||
anchor.utils.features.unset("deprecated-layout");
|
||||
|
||||
const program = anchor.workspace.NewLayout as Program<NewLayout>;
|
||||
|
||||
const dataKeypair = Keypair.generate();
|
||||
await program.methods
|
||||
.initialize()
|
||||
.accounts({ data: dataKeypair.publicKey })
|
||||
.signers([dataKeypair])
|
||||
.rpc();
|
||||
const accountInfo = await program.account.data.getAccountInfo(
|
||||
dataKeypair.publicKey
|
||||
);
|
||||
const data = accountInfo.data;
|
||||
const header = data.slice(0, 8);
|
||||
const givenDiscriminator = header.slice(2, 6);
|
||||
const accountData = data.slice(8);
|
||||
const expectedDiscriminator = BorshAccountHeader.discriminator("data");
|
||||
|
||||
assert.ok(
|
||||
"0xce9c3bbc" === anchor.utils.bytes.hex.encode(expectedDiscriminator)
|
||||
);
|
||||
assert.ok(expectedDiscriminator.length === 4);
|
||||
assert.ok(givenDiscriminator.compare(expectedDiscriminator) === 0);
|
||||
assert.ok(accountData.compare(Buffer.from([2, 0, 0, 0, 0, 0, 0, 0])) === 0);
|
||||
assert.ok(header[0] === 0);
|
||||
assert.ok(header[1] === 0);
|
||||
assert.ok(header[6] === 0);
|
||||
assert.ok(header[7] === 0);
|
||||
|
||||
const dataAccount = await program.account.data.fetch(dataKeypair.publicKey);
|
||||
assert.ok(dataAccount.data.toNumber() === 2);
|
||||
|
||||
assert.rejects(
|
||||
async () => {
|
||||
anchor.utils.features.set("deprecated-layout");
|
||||
await program.account.data.fetch(dataKeypair.publicKey);
|
||||
},
|
||||
(err) => {
|
||||
return err.toString() === "Error: Invalid account discriminator";
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"types": ["mocha", "chai"],
|
||||
"typeRoots": ["./node_modules/@types"],
|
||||
"lib": ["es2015"],
|
||||
"module": "commonjs",
|
||||
"target": "es6",
|
||||
"esModuleInterop": true
|
||||
}
|
||||
}
|
|
@ -9,6 +9,7 @@ import { IdlCoder } from "./idl.js";
|
|||
import { AccountsCoder } from "../index.js";
|
||||
import { accountSize } from "../common.js";
|
||||
import * as features from "../../utils/features";
|
||||
import { Features } from "../../utils/features";
|
||||
|
||||
/**
|
||||
* Number of bytes of the account header.
|
||||
|
@ -103,7 +104,7 @@ export class BorshAccountHeader {
|
|||
* Returns the default account header for an account with the given name.
|
||||
*/
|
||||
public static encode(accountName: string, nameSpace?: string): Buffer {
|
||||
if (features.isSet("deprecated-layout")) {
|
||||
if (features.isSet(Features.DeprecatedLayout)) {
|
||||
return BorshAccountHeader.discriminator(accountName, nameSpace);
|
||||
} else {
|
||||
return Buffer.concat([
|
||||
|
@ -129,7 +130,7 @@ export class BorshAccountHeader {
|
|||
}
|
||||
|
||||
public static discriminatorSize(): number {
|
||||
return features.isSet("deprecated-layout")
|
||||
return features.isSet(Features.DeprecatedLayout)
|
||||
? DEPRECATED_ACCOUNT_DISCRIMINATOR_SIZE
|
||||
: ACCOUNT_DISCRIMINATOR_SIZE;
|
||||
}
|
||||
|
@ -138,7 +139,7 @@ export class BorshAccountHeader {
|
|||
* Returns the account data index at which the discriminator starts.
|
||||
*/
|
||||
public static discriminatorOffset(): number {
|
||||
if (features.isSet("deprecated-layout")) {
|
||||
if (features.isSet(Features.DeprecatedLayout)) {
|
||||
return 0;
|
||||
} else {
|
||||
return 2;
|
||||
|
@ -156,7 +157,7 @@ export class BorshAccountHeader {
|
|||
* Returns the discriminator from the given account data.
|
||||
*/
|
||||
public static parseDiscriminator(data: Buffer): Buffer {
|
||||
if (features.isSet("deprecated-layout")) {
|
||||
if (features.isSet(Features.DeprecatedLayout)) {
|
||||
return data.slice(0, 8);
|
||||
} else {
|
||||
return data.slice(2, 6);
|
||||
|
|
|
@ -7,6 +7,7 @@ import { Event, EventData } from "../../program/event.js";
|
|||
import { IdlCoder } from "./idl.js";
|
||||
import { EventCoder } from "../index.js";
|
||||
import * as features from "../../utils/features";
|
||||
import { Features } from "../../utils/features";
|
||||
|
||||
export class BorshEventCoder implements EventCoder {
|
||||
/**
|
||||
|
@ -84,7 +85,7 @@ export function eventDiscriminator(name: string): Buffer {
|
|||
|
||||
class EventHeader {
|
||||
public static parseDiscriminator(data: Buffer): Buffer {
|
||||
if (features.isSet("deprecated-layout")) {
|
||||
if (features.isSet(Features.DeprecatedLayout)) {
|
||||
return data.slice(0, 8);
|
||||
} else {
|
||||
return data.slice(0, 4);
|
||||
|
@ -92,7 +93,7 @@ class EventHeader {
|
|||
}
|
||||
|
||||
public static size(): number {
|
||||
if (features.isSet("deprecated-layout")) {
|
||||
if (features.isSet(Features.DeprecatedLayout)) {
|
||||
return 8;
|
||||
} else {
|
||||
return 4;
|
||||
|
@ -100,7 +101,7 @@ class EventHeader {
|
|||
}
|
||||
|
||||
public static discriminator(name: string): Buffer {
|
||||
if (features.isSet("deprecated-layout")) {
|
||||
if (features.isSet(Features.DeprecatedLayout)) {
|
||||
return Buffer.from(sha256.digest(`event:${name}`)).slice(0, 8);
|
||||
} else {
|
||||
return Buffer.from(sha256.digest(`event:${name}`)).slice(0, 4);
|
||||
|
|
|
@ -1,9 +1,14 @@
|
|||
const _AVAILABLE_FEATURES = new Set([
|
||||
"anchor-deprecated-state",
|
||||
"debug-logs",
|
||||
"deprecated-layout",
|
||||
]);
|
||||
export const Features = {
|
||||
DeprecatedState: "anchor-deprecated-state",
|
||||
DebugLogs: "debug-logs",
|
||||
DeprecatedLayout: "deprecated-layout",
|
||||
};
|
||||
|
||||
const _AVAILABLE_FEATURES = new Set([
|
||||
Features.DeprecatedState,
|
||||
Features.DebugLogs,
|
||||
Features.DeprecatedLayout,
|
||||
]);
|
||||
const _FEATURES = new Map();
|
||||
|
||||
export function set(key: string) {
|
||||
|
@ -13,6 +18,13 @@ export function set(key: string) {
|
|||
_FEATURES.set(key, true);
|
||||
}
|
||||
|
||||
export function isSet(key: string): boolean {
|
||||
return _FEATURES.get(key) !== undefined;
|
||||
export function unset(key: string) {
|
||||
if (!_AVAILABLE_FEATURES.has(key)) {
|
||||
throw new Error("Invalid feature");
|
||||
}
|
||||
_FEATURES.delete(key);
|
||||
}
|
||||
|
||||
export function isSet(key: string): boolean {
|
||||
return _FEATURES.get(key) === true;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue