From a042366bb9385ac1abdc2765407a7b1dc4349229 Mon Sep 17 00:00:00 2001 From: raykast Date: Thu, 4 Aug 2022 17:39:47 -0700 Subject: [PATCH 1/5] Updated pre-push script. --- scripts/pre-push.sh | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/scripts/pre-push.sh b/scripts/pre-push.sh index 4f8d3218e..4a4c3d170 100755 --- a/scripts/pre-push.sh +++ b/scripts/pre-push.sh @@ -5,14 +5,17 @@ set -e cd "$(dirname "$0")/.." lib_flags=(--workspace --lib --all-features) -build_flags=("${lib_flags[@]}") -build_flags+=(--bins) +bin_flags=(--workspace --bins --all-features) [[ -z "$CARGO" ]] && CARGO=cargo diff --unified <(./diesel.sh print-schema) crates/core/src/db/schema.rs "$CARGO" fmt --all --check -"$CARGO" clippy "${build_flags[@]}" --no-deps +"$CARGO" clippy "${lib_flags[@]}" --no-deps "$CARGO" doc "${lib_flags[@]}" --no-deps -"$CARGO" build "${build_flags[@]}" -"$CARGO" test "${build_flags[@]}" +"$CARGO" build "${lib_flags[@]}" +"$CARGO" test "${lib_flags[@]}" + +"$CARGO" clippy "${bin_flags[@]}" --no-deps +"$CARGO" build "${bin_flags[@]}" +"$CARGO" test "${bin_flags[@]}" From 84084cb2072ae3d5f7e781b6c74517fa278f9c38 Mon Sep 17 00:00:00 2001 From: raykast Date: Thu, 4 Aug 2022 17:45:48 -0700 Subject: [PATCH 2/5] Update GitHub workflows. --- .github/workflows/cargo.yml | 35 +++++++--- .github/workflows/cargo_test.yml | 64 +++++++++++++++++-- .../workflows/deploy_to_heroku_production.yml | 50 --------------- .../workflows/deploy_to_heroku_staging.yml | 40 ------------ 4 files changed, 83 insertions(+), 106 deletions(-) delete mode 100644 .github/workflows/deploy_to_heroku_production.yml delete mode 100644 .github/workflows/deploy_to_heroku_staging.yml diff --git a/.github/workflows/cargo.yml b/.github/workflows/cargo.yml index 668f46f44..24cf4acbc 100644 --- a/.github/workflows/cargo.yml +++ b/.github/workflows/cargo.yml @@ -17,7 +17,8 @@ jobs: components: cargo, rustc, rustfmt profile: minimal - - uses: actions-rs/cargo@v1 + - name: cargo fmt + uses: actions-rs/cargo@v1 with: command: fmt args: --all --check @@ -43,19 +44,27 @@ jobs: target/ key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock', 'rust-toolchain.toml') }} - - uses: actions-rs/cargo@v1 + - name: cargo clippy --lib + uses: actions-rs/cargo@v1 with: command: clippy - args: --all --lib --bins --all-features --no-deps --profile=debug-lite + args: --workspace --lib --all-features --no-deps --profile=debug-lite + + - name: cargo clippy --bins + uses: actions-rs/cargo@v1 + with: + command: clippy + args: --workspace --bins --all-features --no-deps --profile=debug-lite - name: check lockfile run: | diff Cargo.lock <(git show HEAD:Cargo.lock) - - uses: actions-rs/cargo@v1 + - name: cargo doc --lib + uses: actions-rs/cargo@v1 with: command: doc - args: --all --lib --all-features --no-deps --profile=debug-lite + args: --workspace --lib --all-features --no-deps --profile=debug-lite release-check: name: cargo check/doc/clippy (release profile) @@ -78,12 +87,20 @@ jobs: target/ key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock', 'rust-toolchain.toml') }} - - uses: actions-rs/cargo@v1 + - name: cargo clippy --lib --release + uses: actions-rs/cargo@v1 + with: + command: clippy + args: --workspace --lib --all-features --profile=release-lite + + - name: cargo clippy --bins --release + uses: actions-rs/cargo@v1 with: command: clippy - args: --all --lib --bins --all-features --profile=release-lite + args: --workspace --bins --all-features --profile=release-lite - - uses: actions-rs/cargo@v1 + - name: cargo doc --lib --release + uses: actions-rs/cargo@v1 with: command: doc - args: --all --lib --all-features --no-deps --profile=release-lite + args: --workspace --lib --all-features --no-deps --profile=release-lite diff --git a/.github/workflows/cargo_test.yml b/.github/workflows/cargo_test.yml index cc5bb8f6a..8466527d9 100644 --- a/.github/workflows/cargo_test.yml +++ b/.github/workflows/cargo_test.yml @@ -2,14 +2,28 @@ name: Cargo test on: pull_request: - branches: [master] + branches: [dev, master] push: branches: [dev, master] jobs: - debug-build: + debug-test: name: cargo build/test (debug profile) runs-on: indexer-test-runner + + services: + postgres: + image: postgres:14.1 + + env: + POSTGRES_USER: ci + POSTGRES_PASSWORD: ci + POSTGRES_PORT: 5432 + POSTGRES_DB: ci + + ports: + - 5432:5432 + steps: - uses: actions/checkout@v2 - uses: actions-rs/toolchain@v1 @@ -28,14 +42,39 @@ jobs: target/ key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock', 'rust-toolchain.toml') }} - - uses: actions-rs/cargo@v1 + - name: cargo test --lib + uses: actions-rs/cargo@v1 + env: + DATABASE_URL: postgres://ci:ci@127.0.0.1:5432/ci + with: + command: test + args: --workspace --lib --all-features --profile=debug-lite + + - name: cargo test --bins + uses: actions-rs/cargo@v1 + env: + DATABASE_URL: postgres://ci:ci@127.0.0.1:5432/ci with: command: test - args: --all --lib --bins --all-features --profile=debug-lite + args: --workspace --bins --all-features --profile=debug-lite - release-build: + release-test: name: cargo build/test (release profile) runs-on: indexer-test-runner + + services: + postgres: + image: postgres:14.1 + + env: + POSTGRES_USER: ci + POSTGRES_PASSWORD: ci + POSTGRES_PORT: 5432 + POSTGRES_DB: ci + + ports: + - 5432:5432 + steps: - uses: actions/checkout@v2 - uses: actions-rs/toolchain@v1 @@ -54,7 +93,18 @@ jobs: target/ key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock', 'rust-toolchain.toml') }} - - uses: actions-rs/cargo@v1 + - name: cargo test --lib --release + uses: actions-rs/cargo@v1 + env: + DATABASE_URL: postgres://ci:ci@127.0.0.1:5432/ci + with: + command: test + args: --workspace --lib --all-features --profile=release-lite + + - name: cargo test --bins --release + uses: actions-rs/cargo@v1 + env: + DATABASE_URL: postgres://ci:ci@127.0.0.1:5432/ci with: command: test - args: --all --lib --bins --all-features --profile=release-lite + args: --workspace --bins --all-features --profile=release-lite diff --git a/.github/workflows/deploy_to_heroku_production.yml b/.github/workflows/deploy_to_heroku_production.yml deleted file mode 100644 index 5343585cf..000000000 --- a/.github/workflows/deploy_to_heroku_production.yml +++ /dev/null @@ -1,50 +0,0 @@ -name: Heroku (production) - -on: - push: - branches: [master] - -jobs: - build: - runs-on: ubuntu-20.04 - steps: - - uses: actions/checkout@v2 - - - name: Geyser consumer - uses: gonuit/heroku-docker-deploy@v1.3.3 - with: - email: ${{ secrets.HEROKU_EMAIL }} - heroku_api_key: ${{ secrets.HEROKU_API_KEY }} - heroku_app_name: accounts-db-consumer - dockerfile_name: Dockerfile - docker_options: '--target geyser-consumer' - process_type: worker - - - name: HTTP consumer - uses: gonuit/heroku-docker-deploy@v1.3.3 - with: - email: ${{ secrets.HEROKU_EMAIL }} - heroku_api_key: ${{ secrets.HEROKU_API_KEY }} - heroku_app_name: accountsdbhttpconsumer - dockerfile_name: Dockerfile - docker_options: '--target http-consumer' - process_type: worker - - - name: GraphQL server - uses: gonuit/heroku-docker-deploy@v1.3.3 - with: - email: ${{ secrets.HEROKU_EMAIL }} - heroku_api_key: ${{ secrets.HEROKU_API_KEY }} - heroku_app_name: indexer-graphql - dockerfile_name: Dockerfile - docker_options: '--target graphql' - - - name: Storefronts Indexer - uses: gonuit/heroku-docker-deploy@v1.3.3 - with: - email: ${{ secrets.HEROKU_EMAIL }} - heroku_api_key: ${{ secrets.HEROKU_API_KEY }} - heroku_app_name: legacy-storefronts - dockerfile_name: Dockerfile - docker_options: '--target legacy-storefronts' - process_type: worker diff --git a/.github/workflows/deploy_to_heroku_staging.yml b/.github/workflows/deploy_to_heroku_staging.yml deleted file mode 100644 index 565452a4d..000000000 --- a/.github/workflows/deploy_to_heroku_staging.yml +++ /dev/null @@ -1,40 +0,0 @@ -name: Heroku (staging) - -on: - push: - branches: [dev, deploy_config, debug_validator] - -jobs: - build: - runs-on: ubuntu-20.04 - steps: - - uses: actions/checkout@v2 - - - name: Geyser consumer - uses: gonuit/heroku-docker-deploy@v1.3.3 - with: - email: ${{ secrets.HEROKU_EMAIL }} - heroku_api_key: ${{ secrets.HEROKU_API_KEY }} - heroku_app_name: accounts-db-consumer-staging - dockerfile_name: Dockerfile - docker_options: '--target geyser-consumer' - process_type: worker - - - name: HTTP consumer - uses: gonuit/heroku-docker-deploy@v1.3.3 - with: - email: ${{ secrets.HEROKU_EMAIL }} - heroku_api_key: ${{ secrets.HEROKU_API_KEY }} - heroku_app_name: accountsdbhttpconsumerstaging - dockerfile_name: Dockerfile - docker_options: '--target http-consumer' - process_type: worker - - - name: GraphQL server - uses: gonuit/heroku-docker-deploy@v1.3.3 - with: - email: ${{ secrets.HEROKU_EMAIL }} - heroku_api_key: ${{ secrets.HEROKU_API_KEY }} - heroku_app_name: indexer-graphql-staging - dockerfile_name: Dockerfile - docker_options: '--target graphql' From af008b228771131b18e0f54726be09c2dea4a24c Mon Sep 17 00:00:00 2001 From: Austin Milt Date: Mon, 18 Jul 2022 11:57:51 -0700 Subject: [PATCH 3/5] basic tests --- Cargo.lock | 1 + crates/core/Cargo.toml | 4 + crates/core/src/db/mod.rs | 375 ++++++++++++++++++++++ crates/core/src/db/queries/collections.rs | 48 +++ crates/core/src/db/queries/nft_count.rs | 16 + 5 files changed, 444 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index c55c5f979..65202e5c8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2939,6 +2939,7 @@ dependencies = [ "diesel_migrations", "dotenv", "env_logger", + "lazy_static", "log", "md5", "meilisearch-sdk", diff --git a/crates/core/Cargo.toml b/crates/core/Cargo.toml index 232557651..2370af57d 100644 --- a/crates/core/Cargo.toml +++ b/crates/core/Cargo.toml @@ -71,3 +71,7 @@ solana-program = { version = "1.9.4", optional = true } cid = { version = "0.7.0", optional = true } url = "2.2.2" md5 = { version = "0.7.0", optional = true } + + +[dev-dependencies] +lazy_static = "1.4.0" \ No newline at end of file diff --git a/crates/core/src/db/mod.rs b/crates/core/src/db/mod.rs index b750bb57e..2a221e1b0 100644 --- a/crates/core/src/db/mod.rs +++ b/crates/core/src/db/mod.rs @@ -209,3 +209,378 @@ pub fn connect(args: ConnectArgs, mode: ConnectMode) -> Result { Ok(ConnectResult { pool, ty, migrated }) } + +#[cfg(test)] +pub mod test { + use diesel::{insert_into, prelude::*}; + use uuid::Uuid; + + use super::{ + connect, models, + schema::{ + auction_houses, listings, metadata_collection_keys, metadata_jsons, metadatas, + purchases, + }, + ConnectArgs, + }; + use crate::prelude::*; + + fn initialize() -> super::Pool { + let conn_args = ConnectArgs { + database_read_url: None, + database_write_url: Some( + "postgres://postgres:holap1ex@localhost:5337/holaplex-indexer".into(), + ), + database_url: None, + }; + let (pool, _) = connect(conn_args, crate::db::ConnectMode::Write) + .expect("failed to connect to database"); + let conn = pool.get().expect("failed to get connection to database"); + + let nft_a_metadata_address = Borrowed("metadata_a"); + let nft_b_metadata_address = Borrowed("metadata_b"); + let nft_c_metadata_address = Borrowed("metadata_c"); + let nft_d_metadata_address = Borrowed("metadata_d"); + let nft_d_purchase_id = Some( + Uuid::parse_str("00000000-0000-0000-0000-000000000009").expect("failed to parse UUID"), + ); + let collection_metadata_address = Borrowed("collection_a"); + let auction_house_address = Borrowed("auction_house_a"); + let seller_address = Borrowed("seller_a"); + let buyer_address = Borrowed("buyer_a"); + + insert_into(metadata_collection_keys::table) + .values(vec![ + models::MetadataCollectionKey { + metadata_address: nft_a_metadata_address.clone(), + collection_address: collection_metadata_address.clone(), + verified: true, + }, + models::MetadataCollectionKey { + metadata_address: nft_b_metadata_address.clone(), + collection_address: collection_metadata_address.clone(), + verified: true, + }, + models::MetadataCollectionKey { + metadata_address: nft_c_metadata_address.clone(), + collection_address: collection_metadata_address.clone(), + verified: true, + }, + models::MetadataCollectionKey { + metadata_address: nft_d_metadata_address.clone(), + collection_address: collection_metadata_address.clone(), + verified: true, + }, + ]) + .on_conflict_do_nothing() + .execute(&conn) + .expect("failed to seed metadata_collection_keys"); + + insert_into(metadatas::table) + .values(vec![ + models::Metadata { + address: nft_a_metadata_address.clone(), + name: Borrowed("nft A"), + symbol: Borrowed("symbol"), + uri: Borrowed("http://example.com/nft-a-uri"), + seller_fee_basis_points: 100, + update_authority_address: Borrowed("update authority"), + mint_address: collection_metadata_address.clone(), + primary_sale_happened: true, + is_mutable: false, + edition_nonce: None, + edition_pda: Borrowed("nft edition pda"), + token_standard: None, + slot: Some(0), + burned: false, + }, + models::Metadata { + address: nft_b_metadata_address.clone(), + name: Borrowed("nft B"), + symbol: Borrowed("symbol"), + uri: Borrowed("http://example.com/nft-b-uri"), + seller_fee_basis_points: 100, + update_authority_address: Borrowed("update authority"), + mint_address: collection_metadata_address.clone(), + primary_sale_happened: true, + is_mutable: false, + edition_nonce: None, + edition_pda: Borrowed("nft edition pda"), + token_standard: None, + slot: Some(0), + burned: false, + }, + models::Metadata { + address: nft_c_metadata_address.clone(), + name: Borrowed("nft C"), + symbol: Borrowed("symbol"), + uri: Borrowed("http://example.com/nft-c-uri"), + seller_fee_basis_points: 100, + update_authority_address: Borrowed("update authority"), + mint_address: collection_metadata_address.clone(), + primary_sale_happened: true, + is_mutable: false, + edition_nonce: None, + edition_pda: Borrowed("nft edition pda"), + token_standard: None, + slot: Some(0), + burned: false, + }, + models::Metadata { + address: nft_d_metadata_address.clone(), + name: Borrowed("nft D"), + symbol: Borrowed("symbol"), + uri: Borrowed("http://example.com/nft-d-uri"), + seller_fee_basis_points: 100, + update_authority_address: Borrowed("update authority"), + mint_address: collection_metadata_address.clone(), + primary_sale_happened: true, + is_mutable: false, + edition_nonce: None, + edition_pda: Borrowed("nft edition pda"), + token_standard: None, + slot: Some(0), + burned: false, + }, + models::Metadata { + address: collection_metadata_address.clone(), + name: Borrowed("collection name"), + symbol: Borrowed("symbol"), + uri: Borrowed("http://example.com/collection-uri"), + seller_fee_basis_points: 100, + update_authority_address: Borrowed("update authority"), + mint_address: Borrowed("collection mint"), + primary_sale_happened: true, + is_mutable: false, + edition_nonce: None, + edition_pda: Borrowed("collection edition pda"), + token_standard: None, + slot: Some(0), + burned: false, + }, + ]) + .on_conflict_do_nothing() + .execute(&conn) + .expect("failed to seed metadatas"); + + insert_into(auction_houses::table) + .values(vec![models::AuctionHouse { + address: auction_house_address.clone(), + treasury_mint: Borrowed("So11111111111111111111111111111111111111112"), + auction_house_treasury: Borrowed("treasury"), + treasury_withdrawal_destination: Borrowed("treasury withdrawal"), + fee_withdrawal_destination: Borrowed("fee withdrawal"), + authority: Borrowed("auction house authority"), + creator: Borrowed("auction house creator"), + bump: 0, + treasury_bump: 0, + fee_payer_bump: 0, + seller_fee_basis_points: 100, + requires_sign_off: false, + can_change_sale_price: false, + auction_house_fee_account: Borrowed("auction house fee account"), + }]) + .on_conflict_do_nothing() + .execute(&conn) + .expect("failed to seed auction_houses"); + + insert_into(listings::table) + .values(vec![ + models::Listing { + id: Some( + Uuid::parse_str("00000000-0000-0000-0000-000000000001") + .expect("failed to parse UUID"), + ), + trade_state: Borrowed("nft_a trade state"), + auction_house: auction_house_address.clone(), + seller: seller_address.clone(), + metadata: nft_a_metadata_address.clone(), + purchase_id: None, + price: 1, + token_size: 1, + trade_state_bump: 0, + created_at: NaiveDate::from_ymd(2020, 1, 2).and_hms(0, 0, 0), + canceled_at: None, + slot: 0, + write_version: Some(0), + }, + models::Listing { + id: Some( + Uuid::parse_str("00000000-0000-0000-0000-000000000002") + .expect("failed to parse UUID"), + ), + trade_state: Borrowed("nft_b trade state"), + auction_house: auction_house_address.clone(), + seller: seller_address.clone(), + metadata: nft_b_metadata_address.clone(), + purchase_id: None, + price: 1, + token_size: 1, + trade_state_bump: 0, + created_at: NaiveDate::from_ymd(2020, 1, 2).and_hms(0, 0, 0), + canceled_at: None, + slot: 0, + write_version: Some(0), + }, + models::Listing { + id: Some( + Uuid::parse_str("00000000-0000-0000-0000-000000000003") + .expect("failed to parse UUID"), + ), + trade_state: Borrowed("nft_c trade state"), + auction_house: auction_house_address.clone(), + seller: seller_address.clone(), + metadata: nft_c_metadata_address.clone(), + purchase_id: None, + price: 1, + token_size: 1, + trade_state_bump: 0, + created_at: NaiveDate::from_ymd(2020, 1, 2).and_hms(0, 0, 0), + canceled_at: None, + slot: 0, + write_version: Some(0), + }, + models::Listing { + id: Some( + Uuid::parse_str("00000000-0000-0000-0000-000000000004") + .expect("failed to parse UUID"), + ), + trade_state: Borrowed("nft_d trade state"), + auction_house: auction_house_address.clone(), + seller: seller_address.clone(), + metadata: nft_d_metadata_address.clone(), + purchase_id: nft_d_purchase_id.clone(), + price: 1, + token_size: 1, + trade_state_bump: 0, + created_at: NaiveDate::from_ymd(2020, 1, 2).and_hms(0, 0, 0), + canceled_at: None, + slot: 0, + write_version: Some(0), + }, + ]) + .on_conflict_do_nothing() + .execute(&conn) + .expect("failed to seed purchases"); + + insert_into(purchases::table) + .values(vec![models::Purchase { + id: nft_d_purchase_id.clone(), + buyer: buyer_address.clone(), + seller: seller_address.clone(), + auction_house: auction_house_address.clone(), + metadata: nft_d_metadata_address.clone(), + token_size: 1, + price: 1, + created_at: NaiveDate::from_ymd(2020, 1, 2).and_hms(0, 0, 0), + slot: 0, + write_version: None, + }]) + .on_conflict_do_nothing() + .execute(&conn) + .expect("failed to seed purchases"); + + insert_into(metadata_jsons::table) + .values(vec![ + models::MetadataJson { + metadata_address: nft_a_metadata_address, + fingerprint: Borrowed(&Vec::::new()), + updated_at: NaiveDate::from_ymd(2020, 1, 2).and_hms(0, 0, 0), + description: Some(Borrowed("nft A description")), + image: Some(Borrowed("http://example.com/nft-a-image")), + animation_url: Some(Borrowed("http://example.com/nft-a-animation")), + external_url: Some(Borrowed("http://example.com/nft-a-external")), + category: Some(Borrowed("nft A category")), + raw_content: Borrowed( + &serde_json::from_str("{}") + .expect("Failed to deserialize metadata content"), + ), + model: Some(Borrowed("model")), + fetch_uri: Borrowed("http://example.com/nft-a-fetch-uri"), + slot: 0, + write_version: 0, + }, + models::MetadataJson { + metadata_address: nft_b_metadata_address, + fingerprint: Borrowed(&Vec::::new()), + updated_at: NaiveDate::from_ymd(2020, 1, 2).and_hms(0, 0, 0), + description: Some(Borrowed("nft B description")), + image: Some(Borrowed("http://example.com/nft-b-image")), + animation_url: Some(Borrowed("http://example.com/nft-b-animation")), + external_url: Some(Borrowed("http://example.com/nft-b-external")), + category: Some(Borrowed("nft B category")), + raw_content: Borrowed( + &serde_json::from_str("{}") + .expect("Failed to deserialize metadata content"), + ), + model: Some(Borrowed("model")), + fetch_uri: Borrowed("http://example.com/nft-b-fetch-uri"), + slot: 0, + write_version: 0, + }, + models::MetadataJson { + metadata_address: nft_c_metadata_address, + fingerprint: Borrowed(&Vec::::new()), + updated_at: NaiveDate::from_ymd(2020, 1, 2).and_hms(0, 0, 0), + description: Some(Borrowed("nft C description")), + image: Some(Borrowed("http://example.com/nft-c-image")), + animation_url: Some(Borrowed("http://example.com/nft-c-animation")), + external_url: Some(Borrowed("http://example.com/nft-c-external")), + category: Some(Borrowed("nft C category")), + raw_content: Borrowed( + &serde_json::from_str("{}") + .expect("Failed to deserialize metadata content"), + ), + model: Some(Borrowed("model")), + fetch_uri: Borrowed("http://example.com/nft-c-fetch-uri"), + slot: 0, + write_version: 0, + }, + models::MetadataJson { + metadata_address: nft_d_metadata_address, + fingerprint: Borrowed(&Vec::::new()), + updated_at: NaiveDate::from_ymd(2020, 1, 2).and_hms(0, 0, 0), + description: Some(Borrowed("nft C description")), + image: Some(Borrowed("http://example.com/nft-c-image")), + animation_url: Some(Borrowed("http://example.com/nft-c-animation")), + external_url: Some(Borrowed("http://example.com/nft-c-external")), + category: Some(Borrowed("nft B category")), + raw_content: Borrowed( + &serde_json::from_str("{}") + .expect("Failed to deserialize metadata content"), + ), + model: Some(Borrowed("model")), + fetch_uri: Borrowed("http://example.com/nft-c-fetch-uri"), + slot: 0, + write_version: 0, + }, + models::MetadataJson { + metadata_address: collection_metadata_address, + fingerprint: Borrowed(&Vec::::new()), + updated_at: NaiveDate::from_ymd(2020, 1, 2).and_hms(0, 0, 0), + description: Some(Borrowed("collection description")), + image: Some(Borrowed("http://example.com/collection-image")), + animation_url: Some(Borrowed("http://example.com/collection-animation")), + external_url: Some(Borrowed("http://example.com/collection-external")), + category: Some(Borrowed("collection category")), + raw_content: Borrowed( + &serde_json::from_str("{}") + .expect("Failed to deserialize metadata content"), + ), + model: Some(Borrowed("model")), + fetch_uri: Borrowed("http://example.com/collection-fetch-uri"), + slot: 0, + write_version: 0, + }, + ]) + .on_conflict_do_nothing() + .execute(&conn) + .expect("failed to seed metadata_jsons"); + + pool + } + + lazy_static::lazy_static! { + pub static ref DATABASE: super::Pool = initialize(); + } +} diff --git a/crates/core/src/db/queries/collections.rs b/crates/core/src/db/queries/collections.rs index 73680818b..7483163f5 100644 --- a/crates/core/src/db/queries/collections.rs +++ b/crates/core/src/db/queries/collections.rs @@ -235,3 +235,51 @@ pub fn collection_activities( .load(conn) .context("Failed to load collection activities") } + +#[cfg(test)] +mod tests { + use chrono::{TimeZone, Utc}; + + use crate::db::test::DATABASE; + + #[test] + fn test_collections_featured_by_marketcap_returns_non_empty() { + let pool = &DATABASE; + + let result = super::by_market_cap( + &pool.get().expect("failed to aquire database connection"), + None::>, + crate::db::custom_types::OrderDirection::Desc, + Utc.ymd(1901, 1, 1).and_hms(0, 0, 0), + Utc.ymd(3000, 1, 1).and_hms(0, 0, 0), + 50, + 0, + ) + .expect("failed query"); + + assert!(!result.is_empty(), "expected at least one row"); + } + + #[test] + fn test_collections_featured_by_volume_returns_non_empty() { + let pool = &DATABASE; + + let result = super::by_volume( + &pool.get().expect("failed to aquire database connection"), + None::>, + crate::db::custom_types::OrderDirection::Desc, + Utc.ymd(1901, 1, 1).and_hms(0, 0, 0), + Utc.ymd(3000, 1, 1).and_hms(0, 0, 0), + 50, + 0, + ) + .expect("failed query"); + + assert!(!result.is_empty(), "expected at least one row"); + } + + #[test] + fn test_collection_activities() { + todo!("Test collection_activities()"); + } +} diff --git a/crates/core/src/db/queries/nft_count.rs b/crates/core/src/db/queries/nft_count.rs index e471adad6..3c9833b99 100644 --- a/crates/core/src/db/queries/nft_count.rs +++ b/crates/core/src/db/queries/nft_count.rs @@ -303,3 +303,19 @@ pub fn store_creators( .load(conn) .context("Failed to load store creators counts") } + +#[cfg(test)] +mod tests { + use crate::db::test::DATABASE; + + #[test] + fn test_store_creators_minimal_passes() { + let pool = &DATABASE; + + let _ = super::store_creators( + &pool.get().expect("failed to aquire database connection"), + Vec::::new(), + ) + .expect("failed query"); + } +} From 0c1d0c80a072a6040086a5c88932c85d5df44ccc Mon Sep 17 00:00:00 2001 From: raykast Date: Thu, 4 Aug 2022 15:52:30 -0700 Subject: [PATCH 4/5] Refactor test harness. --- crates/core/Cargo.toml | 3 +- crates/core/src/db/mod.rs | 449 +++--------------- crates/core/src/db/queries/collections.rs | 24 +- crates/core/src/db/queries/nft_count.rs | 10 +- .../2022-08-04-200854_seed_nfts/down.sql | 27 ++ .../2022-08-04-200854_seed_nfts/up.sql | 198 ++++++++ .../down.sql | 14 + .../up.sql | 96 ++++ diesel.sh | 5 +- test-migration.sh | 7 + 10 files changed, 428 insertions(+), 405 deletions(-) create mode 100644 crates/core/test_migrations/2022-08-04-200854_seed_nfts/down.sql create mode 100644 crates/core/test_migrations/2022-08-04-200854_seed_nfts/up.sql create mode 100644 crates/core/test_migrations/2022-08-04-205234_seed_auction_houses/down.sql create mode 100644 crates/core/test_migrations/2022-08-04-205234_seed_auction_houses/up.sql create mode 100755 test-migration.sh diff --git a/crates/core/Cargo.toml b/crates/core/Cargo.toml index 2370af57d..a91b3714d 100644 --- a/crates/core/Cargo.toml +++ b/crates/core/Cargo.toml @@ -72,6 +72,5 @@ cid = { version = "0.7.0", optional = true } url = "2.2.2" md5 = { version = "0.7.0", optional = true } - [dev-dependencies] -lazy_static = "1.4.0" \ No newline at end of file +lazy_static = "1.4.0" diff --git a/crates/core/src/db/mod.rs b/crates/core/src/db/mod.rs index 2a221e1b0..9544965da 100644 --- a/crates/core/src/db/mod.rs +++ b/crates/core/src/db/mod.rs @@ -118,6 +118,31 @@ impl From for ConnectionType { } } +fn migrate( + conn: &C, + desc: impl std::fmt::Display, + run: impl FnOnce(&C, &mut dyn std::io::Write) -> Result<(), diesel_migrations::RunMigrationsError>, +) -> Result<()> { + info!("Running {}...", desc); + + let mut out = vec![]; + + run(conn, &mut out).with_context(|| format!("Failed to run {}", desc))?; + + match std::str::from_utf8(&out) { + Ok(s) => { + let s = s.trim(); + + if !s.is_empty() { + info!("Output from {}:\n{}", desc, s); + } + }, + Err(e) => warn!("Failed to read output from {}: {}", desc, e), + } + + Ok(()) +} + /// Create a pooled connection to the Postgres database, using the given CLI /// arguments and a hint indicating if the database is writable. /// @@ -159,8 +184,6 @@ pub fn connect(args: ConnectArgs, mode: ConnectMode) -> Result { .build(man) .context("Failed to create database connection pool")?; - let mut out = vec![]; - if cfg!(not(debug_assertions)) && matches!(ty, ConnectionType::Default) { warn!("Cannot determine if database is writable; assuming yes"); } @@ -187,24 +210,13 @@ pub fn connect(args: ConnectArgs, mode: ConnectMode) -> Result { }; if migrated { - info!("Running database migrations..."); - - embedded_migrations::run_with_output( - &pool.get().context("Failed to connect to the database")?, - &mut out, - ) - .context("Failed to run database migrations")?; - } - - match std::str::from_utf8(&out) { - Ok(s) => { - let s = s.trim(); - - if !s.is_empty() { - info!("Output from migrations:\n{}", s); - } - }, - Err(e) => warn!("Failed to read migration output: {}", e), + migrate( + &*pool + .get() + .context("Failed to acquire database connection")?, + "database migrations", + embedded_migrations::run_with_output, + )?; } Ok(ConnectResult { pool, ty, migrated }) @@ -212,375 +224,50 @@ pub fn connect(args: ConnectArgs, mode: ConnectMode) -> Result { #[cfg(test)] pub mod test { - use diesel::{insert_into, prelude::*}; - use uuid::Uuid; - - use super::{ - connect, models, - schema::{ - auction_houses, listings, metadata_collection_keys, metadata_jsons, metadatas, - purchases, - }, - ConnectArgs, - }; - use crate::prelude::*; + embed_migrations!("test_migrations"); + + fn initialize() -> super::ConnectResult { + dotenv::from_filename(".env.dev").expect("Failed to load .env.dev"); + dotenv::from_filename(".env").expect("Failed to load .env"); - fn initialize() -> super::Pool { - let conn_args = ConnectArgs { + let conn_args = super::ConnectArgs { database_read_url: None, database_write_url: Some( - "postgres://postgres:holap1ex@localhost:5337/holaplex-indexer".into(), + std::env::var("DATABASE_URL") + .expect("Failed to load DATABASE_URL from environment"), ), database_url: None, }; - let (pool, _) = connect(conn_args, crate::db::ConnectMode::Write) - .expect("failed to connect to database"); - let conn = pool.get().expect("failed to get connection to database"); - - let nft_a_metadata_address = Borrowed("metadata_a"); - let nft_b_metadata_address = Borrowed("metadata_b"); - let nft_c_metadata_address = Borrowed("metadata_c"); - let nft_d_metadata_address = Borrowed("metadata_d"); - let nft_d_purchase_id = Some( - Uuid::parse_str("00000000-0000-0000-0000-000000000009").expect("failed to parse UUID"), - ); - let collection_metadata_address = Borrowed("collection_a"); - let auction_house_address = Borrowed("auction_house_a"); - let seller_address = Borrowed("seller_a"); - let buyer_address = Borrowed("buyer_a"); - - insert_into(metadata_collection_keys::table) - .values(vec![ - models::MetadataCollectionKey { - metadata_address: nft_a_metadata_address.clone(), - collection_address: collection_metadata_address.clone(), - verified: true, - }, - models::MetadataCollectionKey { - metadata_address: nft_b_metadata_address.clone(), - collection_address: collection_metadata_address.clone(), - verified: true, - }, - models::MetadataCollectionKey { - metadata_address: nft_c_metadata_address.clone(), - collection_address: collection_metadata_address.clone(), - verified: true, - }, - models::MetadataCollectionKey { - metadata_address: nft_d_metadata_address.clone(), - collection_address: collection_metadata_address.clone(), - verified: true, - }, - ]) - .on_conflict_do_nothing() - .execute(&conn) - .expect("failed to seed metadata_collection_keys"); - - insert_into(metadatas::table) - .values(vec![ - models::Metadata { - address: nft_a_metadata_address.clone(), - name: Borrowed("nft A"), - symbol: Borrowed("symbol"), - uri: Borrowed("http://example.com/nft-a-uri"), - seller_fee_basis_points: 100, - update_authority_address: Borrowed("update authority"), - mint_address: collection_metadata_address.clone(), - primary_sale_happened: true, - is_mutable: false, - edition_nonce: None, - edition_pda: Borrowed("nft edition pda"), - token_standard: None, - slot: Some(0), - burned: false, - }, - models::Metadata { - address: nft_b_metadata_address.clone(), - name: Borrowed("nft B"), - symbol: Borrowed("symbol"), - uri: Borrowed("http://example.com/nft-b-uri"), - seller_fee_basis_points: 100, - update_authority_address: Borrowed("update authority"), - mint_address: collection_metadata_address.clone(), - primary_sale_happened: true, - is_mutable: false, - edition_nonce: None, - edition_pda: Borrowed("nft edition pda"), - token_standard: None, - slot: Some(0), - burned: false, - }, - models::Metadata { - address: nft_c_metadata_address.clone(), - name: Borrowed("nft C"), - symbol: Borrowed("symbol"), - uri: Borrowed("http://example.com/nft-c-uri"), - seller_fee_basis_points: 100, - update_authority_address: Borrowed("update authority"), - mint_address: collection_metadata_address.clone(), - primary_sale_happened: true, - is_mutable: false, - edition_nonce: None, - edition_pda: Borrowed("nft edition pda"), - token_standard: None, - slot: Some(0), - burned: false, - }, - models::Metadata { - address: nft_d_metadata_address.clone(), - name: Borrowed("nft D"), - symbol: Borrowed("symbol"), - uri: Borrowed("http://example.com/nft-d-uri"), - seller_fee_basis_points: 100, - update_authority_address: Borrowed("update authority"), - mint_address: collection_metadata_address.clone(), - primary_sale_happened: true, - is_mutable: false, - edition_nonce: None, - edition_pda: Borrowed("nft edition pda"), - token_standard: None, - slot: Some(0), - burned: false, - }, - models::Metadata { - address: collection_metadata_address.clone(), - name: Borrowed("collection name"), - symbol: Borrowed("symbol"), - uri: Borrowed("http://example.com/collection-uri"), - seller_fee_basis_points: 100, - update_authority_address: Borrowed("update authority"), - mint_address: Borrowed("collection mint"), - primary_sale_happened: true, - is_mutable: false, - edition_nonce: None, - edition_pda: Borrowed("collection edition pda"), - token_standard: None, - slot: Some(0), - burned: false, - }, - ]) - .on_conflict_do_nothing() - .execute(&conn) - .expect("failed to seed metadatas"); - - insert_into(auction_houses::table) - .values(vec![models::AuctionHouse { - address: auction_house_address.clone(), - treasury_mint: Borrowed("So11111111111111111111111111111111111111112"), - auction_house_treasury: Borrowed("treasury"), - treasury_withdrawal_destination: Borrowed("treasury withdrawal"), - fee_withdrawal_destination: Borrowed("fee withdrawal"), - authority: Borrowed("auction house authority"), - creator: Borrowed("auction house creator"), - bump: 0, - treasury_bump: 0, - fee_payer_bump: 0, - seller_fee_basis_points: 100, - requires_sign_off: false, - can_change_sale_price: false, - auction_house_fee_account: Borrowed("auction house fee account"), - }]) - .on_conflict_do_nothing() - .execute(&conn) - .expect("failed to seed auction_houses"); - - insert_into(listings::table) - .values(vec![ - models::Listing { - id: Some( - Uuid::parse_str("00000000-0000-0000-0000-000000000001") - .expect("failed to parse UUID"), - ), - trade_state: Borrowed("nft_a trade state"), - auction_house: auction_house_address.clone(), - seller: seller_address.clone(), - metadata: nft_a_metadata_address.clone(), - purchase_id: None, - price: 1, - token_size: 1, - trade_state_bump: 0, - created_at: NaiveDate::from_ymd(2020, 1, 2).and_hms(0, 0, 0), - canceled_at: None, - slot: 0, - write_version: Some(0), - }, - models::Listing { - id: Some( - Uuid::parse_str("00000000-0000-0000-0000-000000000002") - .expect("failed to parse UUID"), - ), - trade_state: Borrowed("nft_b trade state"), - auction_house: auction_house_address.clone(), - seller: seller_address.clone(), - metadata: nft_b_metadata_address.clone(), - purchase_id: None, - price: 1, - token_size: 1, - trade_state_bump: 0, - created_at: NaiveDate::from_ymd(2020, 1, 2).and_hms(0, 0, 0), - canceled_at: None, - slot: 0, - write_version: Some(0), - }, - models::Listing { - id: Some( - Uuid::parse_str("00000000-0000-0000-0000-000000000003") - .expect("failed to parse UUID"), - ), - trade_state: Borrowed("nft_c trade state"), - auction_house: auction_house_address.clone(), - seller: seller_address.clone(), - metadata: nft_c_metadata_address.clone(), - purchase_id: None, - price: 1, - token_size: 1, - trade_state_bump: 0, - created_at: NaiveDate::from_ymd(2020, 1, 2).and_hms(0, 0, 0), - canceled_at: None, - slot: 0, - write_version: Some(0), - }, - models::Listing { - id: Some( - Uuid::parse_str("00000000-0000-0000-0000-000000000004") - .expect("failed to parse UUID"), - ), - trade_state: Borrowed("nft_d trade state"), - auction_house: auction_house_address.clone(), - seller: seller_address.clone(), - metadata: nft_d_metadata_address.clone(), - purchase_id: nft_d_purchase_id.clone(), - price: 1, - token_size: 1, - trade_state_bump: 0, - created_at: NaiveDate::from_ymd(2020, 1, 2).and_hms(0, 0, 0), - canceled_at: None, - slot: 0, - write_version: Some(0), - }, - ]) - .on_conflict_do_nothing() - .execute(&conn) - .expect("failed to seed purchases"); - - insert_into(purchases::table) - .values(vec![models::Purchase { - id: nft_d_purchase_id.clone(), - buyer: buyer_address.clone(), - seller: seller_address.clone(), - auction_house: auction_house_address.clone(), - metadata: nft_d_metadata_address.clone(), - token_size: 1, - price: 1, - created_at: NaiveDate::from_ymd(2020, 1, 2).and_hms(0, 0, 0), - slot: 0, - write_version: None, - }]) - .on_conflict_do_nothing() - .execute(&conn) - .expect("failed to seed purchases"); - - insert_into(metadata_jsons::table) - .values(vec![ - models::MetadataJson { - metadata_address: nft_a_metadata_address, - fingerprint: Borrowed(&Vec::::new()), - updated_at: NaiveDate::from_ymd(2020, 1, 2).and_hms(0, 0, 0), - description: Some(Borrowed("nft A description")), - image: Some(Borrowed("http://example.com/nft-a-image")), - animation_url: Some(Borrowed("http://example.com/nft-a-animation")), - external_url: Some(Borrowed("http://example.com/nft-a-external")), - category: Some(Borrowed("nft A category")), - raw_content: Borrowed( - &serde_json::from_str("{}") - .expect("Failed to deserialize metadata content"), - ), - model: Some(Borrowed("model")), - fetch_uri: Borrowed("http://example.com/nft-a-fetch-uri"), - slot: 0, - write_version: 0, - }, - models::MetadataJson { - metadata_address: nft_b_metadata_address, - fingerprint: Borrowed(&Vec::::new()), - updated_at: NaiveDate::from_ymd(2020, 1, 2).and_hms(0, 0, 0), - description: Some(Borrowed("nft B description")), - image: Some(Borrowed("http://example.com/nft-b-image")), - animation_url: Some(Borrowed("http://example.com/nft-b-animation")), - external_url: Some(Borrowed("http://example.com/nft-b-external")), - category: Some(Borrowed("nft B category")), - raw_content: Borrowed( - &serde_json::from_str("{}") - .expect("Failed to deserialize metadata content"), - ), - model: Some(Borrowed("model")), - fetch_uri: Borrowed("http://example.com/nft-b-fetch-uri"), - slot: 0, - write_version: 0, - }, - models::MetadataJson { - metadata_address: nft_c_metadata_address, - fingerprint: Borrowed(&Vec::::new()), - updated_at: NaiveDate::from_ymd(2020, 1, 2).and_hms(0, 0, 0), - description: Some(Borrowed("nft C description")), - image: Some(Borrowed("http://example.com/nft-c-image")), - animation_url: Some(Borrowed("http://example.com/nft-c-animation")), - external_url: Some(Borrowed("http://example.com/nft-c-external")), - category: Some(Borrowed("nft C category")), - raw_content: Borrowed( - &serde_json::from_str("{}") - .expect("Failed to deserialize metadata content"), - ), - model: Some(Borrowed("model")), - fetch_uri: Borrowed("http://example.com/nft-c-fetch-uri"), - slot: 0, - write_version: 0, - }, - models::MetadataJson { - metadata_address: nft_d_metadata_address, - fingerprint: Borrowed(&Vec::::new()), - updated_at: NaiveDate::from_ymd(2020, 1, 2).and_hms(0, 0, 0), - description: Some(Borrowed("nft C description")), - image: Some(Borrowed("http://example.com/nft-c-image")), - animation_url: Some(Borrowed("http://example.com/nft-c-animation")), - external_url: Some(Borrowed("http://example.com/nft-c-external")), - category: Some(Borrowed("nft B category")), - raw_content: Borrowed( - &serde_json::from_str("{}") - .expect("Failed to deserialize metadata content"), - ), - model: Some(Borrowed("model")), - fetch_uri: Borrowed("http://example.com/nft-c-fetch-uri"), - slot: 0, - write_version: 0, - }, - models::MetadataJson { - metadata_address: collection_metadata_address, - fingerprint: Borrowed(&Vec::::new()), - updated_at: NaiveDate::from_ymd(2020, 1, 2).and_hms(0, 0, 0), - description: Some(Borrowed("collection description")), - image: Some(Borrowed("http://example.com/collection-image")), - animation_url: Some(Borrowed("http://example.com/collection-animation")), - external_url: Some(Borrowed("http://example.com/collection-external")), - category: Some(Borrowed("collection category")), - raw_content: Borrowed( - &serde_json::from_str("{}") - .expect("Failed to deserialize metadata content"), - ), - model: Some(Borrowed("model")), - fetch_uri: Borrowed("http://example.com/collection-fetch-uri"), - slot: 0, - write_version: 0, - }, - ]) - .on_conflict_do_nothing() - .execute(&conn) - .expect("failed to seed metadata_jsons"); - - pool + let res = super::connect(conn_args, super::ConnectMode::Write { migrate: true }) + .expect("Failed to connect to database"); + + super::migrate( + &*res + .pool + .get() + .expect("Failed to acquire database connection"), + "test seed migrations", + embedded_migrations::run_with_output, + ) + .expect("Seed migrations failed"); + + res } lazy_static::lazy_static! { - pub static ref DATABASE: super::Pool = initialize(); + static ref DATABASE: super::ConnectResult = initialize(); + } + + #[must_use] + pub fn connect() -> super::PooledConnection { + DATABASE + .pool + .get() + .expect("Failed to acquire database connection") + } + + pub mod prelude { + pub use super::connect; + pub use crate::{db::custom_types::*, prelude::*}; } } diff --git a/crates/core/src/db/queries/collections.rs b/crates/core/src/db/queries/collections.rs index 7483163f5..feb403a2d 100644 --- a/crates/core/src/db/queries/collections.rs +++ b/crates/core/src/db/queries/collections.rs @@ -238,44 +238,42 @@ pub fn collection_activities( #[cfg(test)] mod tests { - use chrono::{TimeZone, Utc}; - - use crate::db::test::DATABASE; + use crate::db::test::prelude::*; #[test] fn test_collections_featured_by_marketcap_returns_non_empty() { - let pool = &DATABASE; + let conn = connect(); let result = super::by_market_cap( - &pool.get().expect("failed to aquire database connection"), + &conn, None::>, - crate::db::custom_types::OrderDirection::Desc, + OrderDirection::Desc, Utc.ymd(1901, 1, 1).and_hms(0, 0, 0), Utc.ymd(3000, 1, 1).and_hms(0, 0, 0), 50, 0, ) - .expect("failed query"); + .unwrap(); - assert!(!result.is_empty(), "expected at least one row"); + assert!(!result.is_empty(), "Expected at least one row"); } #[test] fn test_collections_featured_by_volume_returns_non_empty() { - let pool = &DATABASE; + let conn = connect(); let result = super::by_volume( - &pool.get().expect("failed to aquire database connection"), + &conn, None::>, - crate::db::custom_types::OrderDirection::Desc, + OrderDirection::Desc, Utc.ymd(1901, 1, 1).and_hms(0, 0, 0), Utc.ymd(3000, 1, 1).and_hms(0, 0, 0), 50, 0, ) - .expect("failed query"); + .unwrap(); - assert!(!result.is_empty(), "expected at least one row"); + assert!(!result.is_empty(), "Expected at least one row"); } #[test] diff --git a/crates/core/src/db/queries/nft_count.rs b/crates/core/src/db/queries/nft_count.rs index 3c9833b99..1ee7d580e 100644 --- a/crates/core/src/db/queries/nft_count.rs +++ b/crates/core/src/db/queries/nft_count.rs @@ -306,16 +306,12 @@ pub fn store_creators( #[cfg(test)] mod tests { - use crate::db::test::DATABASE; + use crate::db::test::prelude::*; #[test] fn test_store_creators_minimal_passes() { - let pool = &DATABASE; + let conn = connect(); - let _ = super::store_creators( - &pool.get().expect("failed to aquire database connection"), - Vec::::new(), - ) - .expect("failed query"); + std::mem::drop(super::store_creators(&conn, Vec::::new()).unwrap()); } } diff --git a/crates/core/test_migrations/2022-08-04-200854_seed_nfts/down.sql b/crates/core/test_migrations/2022-08-04-200854_seed_nfts/down.sql new file mode 100644 index 000000000..d6df2ac2f --- /dev/null +++ b/crates/core/test_migrations/2022-08-04-200854_seed_nfts/down.sql @@ -0,0 +1,27 @@ +delete from metadatas where address = any(array [ + 'meta_address_0', + 'meta_address_1', + 'meta_address_2', + 'meta_address_3', + 'collection_address' +]); + +delete from metadata_jsons where metadata_address = any(array [ + 'meta_address_0', + 'meta_address_1', + 'meta_address_2', + 'meta_address_3', + 'collection_address' +]); + +delete from metadata_collection_keys where collection_address = any(array [ + 'collection_mint' +]); + +delete from current_metadata_owners where mint_address = any(array [ + 'mint_0', + 'mint_1', + 'mint_2', + 'mint_3', + 'collection_mint' +]); diff --git a/crates/core/test_migrations/2022-08-04-200854_seed_nfts/up.sql b/crates/core/test_migrations/2022-08-04-200854_seed_nfts/up.sql new file mode 100644 index 000000000..262294505 --- /dev/null +++ b/crates/core/test_migrations/2022-08-04-200854_seed_nfts/up.sql @@ -0,0 +1,198 @@ +insert into metadatas values ( + 'meta_address_0', -- address + 'Metadata 0', -- name + 'NFT', -- symbol + 'https://example.com/0.json', -- uri + 1000, -- seller_fee_basis_points + 'updater', -- update_authority_address + 'mint_0', -- mint_address + false, -- primary_sale_happened + false, -- is_mutable + 1337, -- edition_nonce + 'edition', -- edition_pda + 'NonFungible', -- token_standard + 1, -- slot + false -- burned +), ( + 'meta_address_1', -- address + 'Metadata 1', -- name + 'NFT', -- symbol + 'https://example.com/1.json', -- uri + 1000, -- seller_fee_basis_points + 'updater', -- update_authority_address + 'mint_1', -- mint_address + false, -- primary_sale_happened + false, -- is_mutable + 1337, -- edition_nonce + 'edition', -- edition_pda + 'NonFungible', -- token_standard + 1, -- slot + false -- burned +), ( + 'meta_address_2', -- address + 'Metadata 2', -- name + 'NFT', -- symbol + 'https://example.com/2.json', -- uri + 1000, -- seller_fee_basis_points + 'updater', -- update_authority_address + 'mint_2', -- mint_address + false, -- primary_sale_happened + false, -- is_mutable + 1337, -- edition_nonce + 'edition', -- edition_pda + 'NonFungible', -- token_standard + 1, -- slot + false -- burned +), ( + 'meta_address_3', -- address + 'Metadata 3', -- name + 'NFT', -- symbol + 'https://example.com/3.json', -- uri + 1000, -- seller_fee_basis_points + 'updater', -- update_authority_address + 'mint_3', -- mint_address + false, -- primary_sale_happened + false, -- is_mutable + 1337, -- edition_nonce + 'edition', -- edition_pda + 'NonFungible', -- token_standard + 1, -- slot + false -- burned +), ( + 'collection_address', -- address + 'Collection', -- name + 'COLL', -- symbol + 'https://example.com/c.json', -- uri + 1000, -- seller_fee_basis_points + 'updater', -- update_authority_address + 'collection_mint', -- mint_address + false, -- primary_sale_happened + false, -- is_mutable + 1337, -- edition_nonce + 'Edition', -- edition_pda + 'NonFungible', -- token_standard + 1, -- slot + false -- burned +); + +insert into metadata_jsons values ( + 'meta_address_0', -- metadata_address + '00', -- fingerprint + '2020-01-01', -- updated_at + 'An NFT', -- description + 'https://example.com/0.jpg', -- image + 'https://example.com/0.mkv', -- animation_url + 'https://example.com/0', -- external_url + 'test', -- category + '{}', -- raw_content + 'seeded', -- model + 'https://example.com/0.json', -- fetch_uri + 1, -- slot + 0 -- write_version +), ( + 'meta_address_1', -- metadata_address + '01', -- fingerprint + '2020-01-01', -- updated_at + 'An NFT', -- description + 'https://example.com/1.jpg', -- image + 'https://example.com/1.mkv', -- animation_url + 'https://example.com/1', -- external_url + 'test', -- category + '{}', -- raw_content + 'seeded', -- model + 'https://example.com/1.json', -- fetch_uri + 1, -- slot + 0 -- write_version +), ( + 'meta_address_2', -- metadata_address + '02', -- fingerprint + '2020-01-01', -- updated_at + 'An NFT', -- description + 'https://example.com/2.jpg', -- image + 'https://example.com/2.mkv', -- animation_url + 'https://example.com/2', -- external_url + 'test', -- category + '{}', -- raw_content + 'seeded', -- model + 'https://example.com/2.json', -- fetch_uri + 1, -- slot + 0 -- write_version +), ( + 'meta_address_3', -- metadata_address + '03', -- fingerprint + '2020-01-01', -- updated_at + 'An NFT', -- description + 'https://example.com/3.jpg', -- image + 'https://example.com/3.mkv', -- animation_url + 'https://example.com/3', -- external_url + 'test', -- category + '{}', -- raw_content + 'seeded', -- model + 'https://example.com/3.json', -- fetch_uri + 1, -- slot + 0 -- write_version +), ( + 'collection_address', -- metadata_address + 'c0', -- fingerprint + '2020-01-01', -- updated_at + 'An NFT collection', -- description + 'https://example.com/c.jpg', -- image + 'https://example.com/c.mkv', -- animation_url + 'https://example.com/c', -- external_url + 'test', -- category + '{}', -- raw_content + 'seeded', -- model + 'https://example.com/c.json', -- fetch_uri + 1, -- slot + 0 -- write_version +); + +insert into metadata_collection_keys values ( + 'meta_address_0', -- metadata_address + 'collection_mint', -- collection_address + true -- verified +), ( + 'meta_address_1', -- metadata_address + 'collection_mint', -- collection_address + true -- verified +), ( + 'meta_address_2', -- metadata_address + 'collection_mint', -- collection_address + true -- verified +), ( + 'meta_address_3', -- metadata_address + 'collection_mint', -- collection_address + true -- verified +); + +insert into current_metadata_owners values ( + 'mint_0', -- mint_address + 'meta_owner', -- owner_address + 'ata_owner', -- token_account_address + '2020-01-01', -- updated_at + 1 -- slot +), ( + 'mint_1', -- mint_address + 'meta_owner', -- owner_address + 'ata_owner', -- token_account_address + '2020-01-01', -- updated_at + 1 -- slot +), ( + 'mint_2', -- mint_address + 'meta_owner', -- owner_address + 'ata_owner', -- token_account_address + '2020-01-01', -- updated_at + 1 -- slot +), ( + 'mint_3', -- mint_address + 'meta_owner', -- owner_address + 'ata_owner', -- token_account_address + '2020-01-01', -- updated_at + 1 -- slot +), ( + 'collection_mint', -- mint_address + 'meta_owner', -- owner_address + 'ata_owner', -- token_account_address + '2020-01-01', -- updated_at + 1 -- slot +); diff --git a/crates/core/test_migrations/2022-08-04-205234_seed_auction_houses/down.sql b/crates/core/test_migrations/2022-08-04-205234_seed_auction_houses/down.sql new file mode 100644 index 000000000..66539b761 --- /dev/null +++ b/crates/core/test_migrations/2022-08-04-205234_seed_auction_houses/down.sql @@ -0,0 +1,14 @@ +delete from auction_houses where address = any(array [ + 'ah_address' +]); + +delete from listings where id = any(array [ + '00000000-0000-0000-0001-000000000000'::uuid, + '00000000-0000-0000-0001-000000000001', + '00000000-0000-0000-0001-000000000002', + '00000000-0000-0000-0001-000000000003' +]); + +delete from purchases where id = any(array [ + '00000000-0000-0000-0002-000000000003'::uuid +]); diff --git a/crates/core/test_migrations/2022-08-04-205234_seed_auction_houses/up.sql b/crates/core/test_migrations/2022-08-04-205234_seed_auction_houses/up.sql new file mode 100644 index 000000000..ad2823764 --- /dev/null +++ b/crates/core/test_migrations/2022-08-04-205234_seed_auction_houses/up.sql @@ -0,0 +1,96 @@ +insert into auction_houses values ( + 'ah_address', -- address + 'So11111111111111111111111111111111111111112', -- treasury_mint + 'ah_treasury', -- auction_house_treasury + 'ah_withdrawal', -- treasury_withdrawal_destination + 'ah_fee_withdrawal', -- fee_withdrawal_destination + 'ah_authority', -- authority + 'ah_creator', -- creator + 0, -- bump + 0, -- treasury_bump + 0, -- fee_payer_bump + 1000, -- seller_fee_basis_points + true, -- requires_sign_off + false, -- can_change_sale_price + 'ah_fees' -- auction_house_fee_account +); + +insert into listings values ( + '00000000-0000-0000-0001-000000000000', -- id + 'meta_trade_state_0', -- trade_state + 'ah_address', -- auction_house + 'meta_owner', -- seller + 'meta_address_0', -- metadata + null, -- purchase_id + 1, -- price + 1, -- token_size + 0, -- trade_state_bump + '2020-01-01', -- created_at + null, -- canceled_at + 1, -- slot + 0, -- write_version + 'market_program', -- marketplace_program + null -- expiry +), ( + '00000000-0000-0000-0001-000000000001', -- id + 'meta_trade_state_1', -- trade_state + 'ah_address', -- auction_house + 'meta_owner', -- seller + 'meta_address_1', -- metadata + null, -- purchase_id + 1, -- price + 1, -- token_size + 0, -- trade_state_bump + '2020-01-01', -- created_at + null, -- canceled_at + 1, -- slot + 0, -- write_version + 'market_program', -- marketplace_program + null -- expiry +), ( + '00000000-0000-0000-0001-000000000002', -- id + 'meta_trade_state_2', -- trade_state + 'ah_address', -- auction_house + 'meta_owner', -- seller + 'meta_address_2', -- metadata + null, -- purchase_id + 1, -- price + 1, -- token_size + 0, -- trade_state_bump + '2020-01-01', -- created_at + null, -- canceled_at + 1, -- slot + 0, -- write_version + 'market_program', -- marketplace_program + null -- expiry +), ( + '00000000-0000-0000-0001-000000000003', -- id + 'meta_trade_state_3', -- trade_state + 'ah_address', -- auction_house + 'meta_owner', -- seller + 'meta_address_3', -- metadata + '00000000-0000-0000-0002-000000000003', -- purchase_id + 1, -- price + 1, -- token_size + 0, -- trade_state_bump + '2020-01-01', -- created_at + null, -- canceled_at + 1, -- slot + 0, -- write_version + 'market_program', -- marketplace_program + null -- expiry +); + +insert into purchases values ( + '00000000-0000-0000-0002-000000000003', -- id + 'meta_buyer', -- buyer + 'meta_owner', -- seller + 'ah_address', -- auction_house + 'meta_address_3', -- metadata + 1, -- token_size + 1, -- price + '2020-01-01', -- created_at + 1, -- slot + 0, -- write_version + 'market_program' -- marketplace_program +); diff --git a/diesel.sh b/diesel.sh index 95057c1e4..67299313d 100755 --- a/diesel.sh +++ b/diesel.sh @@ -1,6 +1,7 @@ #!/bin/bash set -e +cd "$(dirname "$0")" for f in '' .dev .local; do f="./.env$f" @@ -13,6 +14,6 @@ done export DATABASE_URL -cd "$(dirname "$0")"/crates/core +cd crates/core -diesel "$@" +exec diesel "$@" diff --git a/test-migration.sh b/test-migration.sh new file mode 100755 index 000000000..3b4f3888d --- /dev/null +++ b/test-migration.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +set -e + +cd "$(dirname "$0")" + +exec ./diesel.sh migration --migration-dir test_migrations "$@" From b1f2acde126d2b17f357b042b13d7d2692dfa913 Mon Sep 17 00:00:00 2001 From: raykast Date: Thu, 4 Aug 2022 17:39:47 -0700 Subject: [PATCH 5/5] Stubbed remaining tests. --- crates/core/src/db/queries/activities.rs | 8 ++++++++ crates/core/src/db/queries/bonding_changes.rs | 8 ++++++++ crates/core/src/db/queries/charts.rs | 16 ++++++++++++++++ crates/core/src/db/queries/featured_listings.rs | 8 ++++++++ crates/core/src/db/queries/feed_event.rs | 12 ++++++++++++ crates/core/src/db/queries/graph_connection.rs | 13 +++++++++++++ crates/core/src/db/queries/metadatas.rs | 12 ++++++++++++ crates/core/src/db/queries/nft_count.rs | 1 + crates/core/src/db/queries/stats.rs | 16 ++++++++++++++++ crates/core/src/db/queries/wallet.rs | 8 ++++++++ .../graphql/src/schema/dataloaders/collection.rs | 8 ++++++++ 11 files changed, 110 insertions(+) diff --git a/crates/core/src/db/queries/activities.rs b/crates/core/src/db/queries/activities.rs index bb4bc2c8d..6092241a7 100644 --- a/crates/core/src/db/queries/activities.rs +++ b/crates/core/src/db/queries/activities.rs @@ -57,3 +57,11 @@ pub fn list( .load(conn) .context("Failed to load activities") } + +#[cfg(test)] +mod tests { + #[test] + fn test_list() { + todo!("Test list()"); + } +} diff --git a/crates/core/src/db/queries/bonding_changes.rs b/crates/core/src/db/queries/bonding_changes.rs index 9cff4b0f6..2d9ed3e0c 100644 --- a/crates/core/src/db/queries/bonding_changes.rs +++ b/crates/core/src/db/queries/bonding_changes.rs @@ -54,3 +54,11 @@ pub fn list( .load(conn) .context("Failed to load enriched bonding changes") } + +#[cfg(test)] +mod tests { + #[test] + fn test_list() { + todo!("Test list()"); + } +} diff --git a/crates/core/src/db/queries/charts.rs b/crates/core/src/db/queries/charts.rs index fd20667de..93136f254 100644 --- a/crates/core/src/db/queries/charts.rs +++ b/crates/core/src/db/queries/charts.rs @@ -136,3 +136,19 @@ pub fn total_volume_prices( .load(conn) .context("Failed to load average prices") } + +#[cfg(test)] +mod tests { + #[test] + fn test_floor_prices() { + todo!("Test floor_prices()"); + } + #[test] + fn test_average_prices() { + todo!("Test average_prices()"); + } + #[test] + fn test_total_volume_prices() { + todo!("Test total_volume_prices()"); + } +} diff --git a/crates/core/src/db/queries/featured_listings.rs b/crates/core/src/db/queries/featured_listings.rs index f44974dea..56de54122 100644 --- a/crates/core/src/db/queries/featured_listings.rs +++ b/crates/core/src/db/queries/featured_listings.rs @@ -88,3 +88,11 @@ pub fn list( .load(conn) .context("Failed to load featured listings") } + +#[cfg(test)] +mod tests { + #[test] + fn test_list() { + todo!("Test list()"); + } +} diff --git a/crates/core/src/db/queries/feed_event.rs b/crates/core/src/db/queries/feed_event.rs index 517747269..e4b152856 100644 --- a/crates/core/src/db/queries/feed_event.rs +++ b/crates/core/src/db/queries/feed_event.rs @@ -370,3 +370,15 @@ pub fn list_relay( .load(conn) .context("Failed to load feed events") } + +#[cfg(test)] +mod tests { + #[test] + fn test_list() { + todo!("Test list()"); + } + #[test] + fn test_list_relay() { + todo!("Test list_relay()"); + } +} diff --git a/crates/core/src/db/queries/graph_connection.rs b/crates/core/src/db/queries/graph_connection.rs index ab7dba65d..db2d80f38 100644 --- a/crates/core/src/db/queries/graph_connection.rs +++ b/crates/core/src/db/queries/graph_connection.rs @@ -69,3 +69,16 @@ pub fn list( .load(conn) .context("failed to load twitter enriched graph connections by addresses") } + +#[cfg(test)] +mod tests { + #[test] + fn test_connections() { + todo!("Test connections()"); + } + + #[test] + fn test_list() { + todo!("Test list()"); + } +} diff --git a/crates/core/src/db/queries/metadatas.rs b/crates/core/src/db/queries/metadatas.rs index 7df5a5c24..739bbe2b0 100644 --- a/crates/core/src/db/queries/metadatas.rs +++ b/crates/core/src/db/queries/metadatas.rs @@ -468,3 +468,15 @@ pub fn activities( .load(conn) .context("Failed to load nft(s) activities") } + +#[cfg(test)] +mod tests { + #[test] + fn test_list() { + todo!("Test list()"); + } + #[test] + fn test_activities() { + todo!("Test activities()"); + } +} diff --git a/crates/core/src/db/queries/nft_count.rs b/crates/core/src/db/queries/nft_count.rs index 1ee7d580e..b82497084 100644 --- a/crates/core/src/db/queries/nft_count.rs +++ b/crates/core/src/db/queries/nft_count.rs @@ -313,5 +313,6 @@ mod tests { let conn = connect(); std::mem::drop(super::store_creators(&conn, Vec::::new()).unwrap()); + todo!("Check that the result is non-empty"); } } diff --git a/crates/core/src/db/queries/stats.rs b/crates/core/src/db/queries/stats.rs index da8bf2b5c..5903fa7d5 100644 --- a/crates/core/src/db/queries/stats.rs +++ b/crates/core/src/db/queries/stats.rs @@ -141,3 +141,19 @@ pub fn collection( .load(conn) .context("Failed to load collection mint stats") } + +#[cfg(test)] +mod tests { + #[test] + fn test_mint() { + todo!("Test mint()"); + } + #[test] + fn test_market() { + todo!("Test market()"); + } + #[test] + fn test_collection() { + todo!("Test collection()"); + } +} diff --git a/crates/core/src/db/queries/wallet.rs b/crates/core/src/db/queries/wallet.rs index ea8a83d89..3983c94e6 100644 --- a/crates/core/src/db/queries/wallet.rs +++ b/crates/core/src/db/queries/wallet.rs @@ -64,3 +64,11 @@ pub fn activities(conn: &Connection, address: impl ToSql) -> Result, Vec> for Batcher { async fn load(