add tests

This commit is contained in:
Armani Ferrante 2022-02-17 13:42:00 -05:00
parent ecad170937
commit a8acf640c0
No known key found for this signature in database
GPG Key ID: D597A80BCF8E12B7
17 changed files with 307 additions and 15 deletions

View File

@ -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"))]

6
tests/deprecated-layout/.gitignore vendored Normal file
View File

@ -0,0 +1,6 @@
.anchor
.DS_Store
target
**/*.rs.bk
node_modules

View File

@ -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"

View File

@ -0,0 +1,4 @@
[workspace]
members = [
"programs/*"
]

View File

@ -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.
}

View File

@ -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"
}
}

View File

@ -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"] }

View File

@ -0,0 +1,2 @@
[target.bpfel-unknown-unknown.dependencies.std]
features = []

View File

@ -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,
}

View File

@ -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" }

View File

@ -0,0 +1,2 @@
[target.bpfel-unknown-unknown.dependencies.std]
features = []

View File

@ -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,
}

View File

@ -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";
}
);
});
});

View File

@ -0,0 +1,10 @@
{
"compilerOptions": {
"types": ["mocha", "chai"],
"typeRoots": ["./node_modules/@types"],
"lib": ["es2015"],
"module": "commonjs",
"target": "es6",
"esModuleInterop": true
}
}

View File

@ -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);

View File

@ -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);

View File

@ -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;
}