Skip to content

Commit 9031f52

Browse files
authored
Merge pull request #30 from swayam-agrahari/master
Updating the deploy.yml action
2 parents 2ad8866 + 3673c4c commit 9031f52

File tree

3 files changed

+132
-58
lines changed

3 files changed

+132
-58
lines changed

.github/workflows/deploy.yml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,15 @@ jobs:
1010
deploy:
1111
runs-on: ubuntu-latest
1212
steps:
13+
- name: Checkout Repository
14+
uses: actions/checkout@v4
15+
- name: Start PostgreSQL
16+
run: |
17+
docker run --name postgres-test -e POSTGRES_USER=postgres -e POSTGRES_PASSWORD=postgres -e POSTGRES_DB=test_db -p 5432:5432 -d postgres:15
18+
19+
- name: Set TEST_DATABASE_URL
20+
run: echo "TEST_DATABASE_URL=postgres://postgres:postgres@localhost:5432/test_db" >> $GITHUB_ENV
21+
1322
- uses: shuttle-hq/deploy-action@main
1423
with:
1524
name: "root"

src/db/member.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
use sqlx::FromRow;
21
use async_graphql::SimpleObject;
3-
2+
use sqlx::FromRow;
43

54
//Struct for the Member table
65
#[derive(FromRow, SimpleObject)]
@@ -15,12 +14,12 @@ pub struct Member {
1514
pub year: i32,
1615
pub macaddress: String,
1716
pub discord_id: Option<String>,
18-
pub group_id: Option<i32>,
17+
pub group_id: i32,
1918
}
2019

2120
#[derive(FromRow, SimpleObject)]
2221
pub struct StreakUpdate {
2322
pub id: i32,
2423
pub streak: Option<i32>,
2524
pub max_streak: Option<i32>,
26-
}
25+
}

tests/integration_tests.rs

Lines changed: 120 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,61 +1,142 @@
1-
use config::{Config, File, FileFormat};
21
use root::db::leaderboard::Leaderboard;
32
use root::db::member::Member;
43
use root::leaderboard::fetch_stats::{fetch_codeforces_stats, fetch_leetcode_stats};
54
use root::leaderboard::update_leaderboard::update_leaderboard;
65
use sqlx::{postgres::PgPoolOptions, PgPool};
6+
use std::env;
77
use std::sync::Arc;
88

99
pub fn get_database_url() -> String {
10-
// Create a configuration instance to read Secrets.toml
11-
let settings = Config::builder()
12-
.add_source(File::new("Secrets", FileFormat::Toml))
13-
.build()
14-
.expect("Failed to load Secrets.toml");
15-
16-
// Retrieve the `DATABASE_URL` from the file
17-
settings
18-
.get_string("DATABASE_URL")
19-
.expect("Missing 'DATABASE_URL' in Secrets.toml")
10+
match env::var("TEST_DATABASE_URL") {
11+
Ok(db_url) => db_url,
12+
Err(_) => "postgres://localhost:5432/default_db".to_string(),
13+
}
2014
}
2115

2216
// Helper function to create a test database connection
2317
async fn setup_test_db() -> PgPool {
2418
let database_url = get_database_url();
25-
PgPoolOptions::new()
19+
let pool = PgPoolOptions::new()
2620
.max_connections(5)
2721
.connect(&database_url)
2822
.await
29-
.expect("Failed to create test database pool")
23+
.expect("Failed to create test database pool");
24+
25+
// Create tables if they do not already exist
26+
let queries = vec![
27+
r#"
28+
CREATE TABLE IF NOT EXISTS member (
29+
id SERIAL PRIMARY KEY,
30+
rollno VARCHAR(255) NOT NULL,
31+
name VARCHAR(255) NOT NULL,
32+
hostel VARCHAR(255) NOT NULL,
33+
email VARCHAR(255) NOT NULL UNIQUE,
34+
sex VARCHAR(10) NOT NULL,
35+
year INT NOT NULL,
36+
macaddress VARCHAR(17) NOT NULL,
37+
discord_id VARCHAR(255),
38+
group_id INT NOT NULL
39+
)"#,
40+
r#"
41+
CREATE TABLE IF NOT EXISTS leaderboard (
42+
id SERIAL PRIMARY KEY,
43+
member_id INT UNIQUE NOT NULL,
44+
leetcode_score INT,
45+
codeforces_score INT,
46+
unified_score INT NOT NULL,
47+
last_updated TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
48+
FOREIGN KEY (member_id) REFERENCES member(id)
49+
)"#,
50+
r#"
51+
CREATE TABLE IF NOT EXISTS leetcode_stats (
52+
id SERIAL PRIMARY KEY,
53+
member_id INT UNIQUE NOT NULL,
54+
leetcode_username VARCHAR(255) NOT NULL,
55+
problems_solved INT NOT NULL,
56+
easy_solved INT NOT NULL,
57+
medium_solved INT NOT NULL,
58+
hard_solved INT NOT NULL,
59+
contests_participated INT NOT NULL,
60+
best_rank INT NOT NULL,
61+
total_contests INT NOT NULL,
62+
FOREIGN KEY (member_id) REFERENCES member(id)
63+
)"#,
64+
r#"
65+
CREATE TABLE IF NOT EXISTS codeforces_stats (
66+
id SERIAL PRIMARY KEY,
67+
member_id INT UNIQUE NOT NULL,
68+
codeforces_handle VARCHAR(255) NOT NULL,
69+
codeforces_rating INT NOT NULL,
70+
max_rating INT NOT NULL,
71+
contests_participated INT NOT NULL,
72+
FOREIGN KEY (member_id) REFERENCES member(id)
73+
)"#,
74+
];
75+
76+
for query in queries {
77+
sqlx::query(query)
78+
.execute(&pool)
79+
.await
80+
.expect("Failed to execute query");
81+
}
82+
pool
3083
}
3184

3285
// Helper function to clean up test data
86+
3387
async fn cleanup_test_data(pool: &PgPool) {
34-
// sqlx::query("DELETE FROM leaderboard")
35-
// .execute(pool)
36-
// .await
37-
// .unwrap();
38-
// sqlx::query("DELETE FROM leetcode_stats")
39-
// .execute(pool)
40-
// .await
41-
// .unwrap();
42-
// sqlx::query("DELETE FROM codeforces_stats")
43-
// .execute(pool)
44-
// .await
45-
// .unwrap();
46-
// sqlx::query("DELETE FROM Member")
47-
// .execute(pool)
48-
// .await
49-
// .unwrap();
88+
print!("called");
89+
let cleanup_query = r#"
90+
DO $$
91+
DECLARE
92+
seq RECORD;
93+
BEGIN
94+
-- Droppign all the tables for cleanup purpose
95+
BEGIN
96+
TRUNCATE TABLE leaderboard, leetcode_stats, codeforces_stats, member RESTART IDENTITY CASCADE;
97+
EXCEPTION
98+
WHEN undefined_table THEN
99+
-- Ignore errors if tables don't exist
100+
RAISE NOTICE 'Tables do not exist, skipping TRUNCATE.';
101+
END;
102+
103+
-- Postgres stores the sequences of unique id outside of respective tables, so need to delete those too.
104+
FOR seq IN
105+
SELECT c.relname
106+
FROM pg_class c
107+
JOIN pg_namespace n ON n.oid = c.relnamespace
108+
WHERE c.relkind = 'S' AND n.nspname = 'public'
109+
LOOP
110+
BEGIN
111+
EXECUTE 'ALTER SEQUENCE ' || seq.relname || ' RESTART WITH 1';
112+
EXCEPTION
113+
WHEN undefined_object THEN
114+
-- Ignore errors if sequences don't exist
115+
RAISE NOTICE 'Sequence % does not exist, skipping.', seq.relname;
116+
END;
117+
END LOOP;
118+
END $$;
119+
"#;
120+
121+
sqlx::query(cleanup_query)
122+
.execute(pool)
123+
.await
124+
.expect("Failed to clean up and reset database state");
125+
}
126+
127+
#[tokio::test]
128+
// Additional helper test to verify database connections and basic operations
129+
async fn test_database_connection() {
130+
let database_url = get_database_url();
131+
println!("Database URL: {}", database_url);
132+
assert!(!database_url.is_empty(), "Database URL should not be empty");
50133
}
51134

52135
//test
53136
#[tokio::test]
54137
async fn test_insert_members_and_update_stats() {
55138
let pool = setup_test_db().await;
56139

57-
cleanup_test_data(&pool).await;
58-
59140
// Define test members
60141
let members = vec![
61142
(
@@ -67,6 +148,7 @@ async fn test_insert_members_and_update_stats() {
67148
2021,
68149
"00:11:22:33:44:55",
69150
Some("john_discord"),
151+
1,
70152
"swayam-agrahari",
71153
"tourist",
72154
),
@@ -79,6 +161,7 @@ async fn test_insert_members_and_update_stats() {
79161
2021,
80162
"66:77:88:99:AA:BB",
81163
Some("jane_discord"),
164+
2,
82165
"rihaan1810",
83166
"tourist",
84167
),
@@ -90,8 +173,8 @@ async fn test_insert_members_and_update_stats() {
90173
for member in &members {
91174
// Insert Member
92175
let member_result = sqlx::query_as::<_, Member>(
93-
"INSERT INTO Member (rollno, name, hostel, email, sex, year, macaddress, discord_id)
94-
VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
176+
"INSERT INTO member (rollno, name, hostel, email, sex, year, macaddress, discord_id, group_id)
177+
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)
95178
RETURNING *",
96179
)
97180
.bind(&member.0)
@@ -102,6 +185,7 @@ async fn test_insert_members_and_update_stats() {
102185
.bind(member.5)
103186
.bind(&member.6)
104187
.bind(&member.7)
188+
.bind(&member.8)
105189
.fetch_one(&pool)
106190
.await
107191
.expect("Failed to insert member");
@@ -112,7 +196,7 @@ async fn test_insert_members_and_update_stats() {
112196
VALUES ($1, $2, 0,0,0,0,0,0,0)",
113197
)
114198
.bind(member_result.id)
115-
.bind(&member.8)
199+
.bind(&member.9)
116200
.execute(&pool)
117201
.await
118202
.expect("Failed to insert LeetCode stats");
@@ -123,7 +207,7 @@ async fn test_insert_members_and_update_stats() {
123207
VALUES ($1, $2, 0,0,0)",
124208
)
125209
.bind(member_result.id)
126-
.bind(&member.9)
210+
.bind(&member.10)
127211
.execute(&pool)
128212
.await
129213
.expect("Failed to insert Codeforces stats");
@@ -132,7 +216,7 @@ async fn test_insert_members_and_update_stats() {
132216
}
133217

134218
// Test LeetCode stats fetching
135-
for (member_id, leetcode_username) in inserted_members.iter().zip(members.iter().map(|m| m.8)) {
219+
for (member_id, leetcode_username) in inserted_members.iter().zip(members.iter().map(|m| m.9)) {
136220
match fetch_leetcode_stats(Arc::new(pool.clone()), *member_id, leetcode_username).await {
137221
Ok(_) => println!(
138222
"Successfully fetched LeetCode stats for member ID: {}",
@@ -155,8 +239,6 @@ async fn test_insert_members_and_update_stats() {
155239
),
156240
Err(e) => {
157241
println!("Error fetching Codeforces stats: {:?}", e);
158-
// Uncomment to fail test on fetch error
159-
// panic!("Failed to fetch Codeforces stats")
160242
}
161243
}
162244
}
@@ -192,21 +274,5 @@ async fn test_insert_members_and_update_stats() {
192274
);
193275
}
194276

195-
// Clean up
196277
cleanup_test_data(&pool).await;
197278
}
198-
199-
// Additional helper test to verify database connections and basic operations
200-
#[tokio::test]
201-
async fn test_database_connection() {
202-
let pool = setup_test_db().await;
203-
let database_url = get_database_url();
204-
205-
// Print the URL to verify (optional, for debugging purposes)
206-
println!("Database URL: {}", database_url);
207-
208-
// Basic database connectivity test
209-
let result = sqlx::query("SELECT 1").fetch_one(&pool).await;
210-
211-
assert!(result.is_ok(), "Database connection and query should work");
212-
}

0 commit comments

Comments
 (0)