Skip to content

Commit 3c58ee1

Browse files
authored
Merge pull request #41 from MicroClub-USTHB/ci/test-pipeline
GitHub Actions CI pipeline for Android, IOS, Linux
2 parents ae2c6c6 + 1bb072f commit 3c58ee1

9 files changed

Lines changed: 176 additions & 77 deletions

File tree

.github/workflows/ci.yml

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [main, ci/test-pipeline]
6+
pull_request:
7+
branches: [main]
8+
9+
concurrency:
10+
group: ${{ github.workflow }}-${{ github.ref }}
11+
cancel-in-progress: true
12+
13+
jobs:
14+
rust:
15+
name: Rust (lint + test)
16+
runs-on: ubuntu-latest
17+
defaults:
18+
run:
19+
working-directory: rust
20+
steps:
21+
- uses: actions/checkout@v4
22+
- uses: dtolnay/rust-toolchain@stable
23+
with:
24+
components: clippy
25+
- uses: Swatinem/rust-cache@v2
26+
with:
27+
workspaces: rust
28+
- run: cargo clippy --all-targets -- -D warnings
29+
- run: cargo test
30+
31+
dart:
32+
name: Dart (codegen + analyze)
33+
runs-on: ubuntu-latest
34+
steps:
35+
- uses: actions/checkout@v4
36+
- uses: subosito/flutter-action@v2
37+
with:
38+
channel: stable
39+
- uses: dtolnay/rust-toolchain@stable
40+
- run: cargo install flutter_rust_bridge_codegen
41+
- run: flutter pub get
42+
- run: flutter_rust_bridge_codegen generate
43+
- run: dart run build_runner build --delete-conflicting-outputs
44+
- run: dart analyze lib/ integration_test/
45+
46+
build-android:
47+
name: Android build
48+
needs: [rust, dart]
49+
runs-on: ubuntu-latest
50+
steps:
51+
- uses: actions/checkout@v4
52+
- uses: subosito/flutter-action@v2
53+
with:
54+
channel: stable
55+
- uses: dtolnay/rust-toolchain@stable
56+
with:
57+
targets: aarch64-linux-android,armv7-linux-androideabi
58+
- uses: nttld/setup-ndk@v1
59+
with:
60+
ndk-version: r27c
61+
- run: cargo install flutter_rust_bridge_codegen
62+
- run: flutter pub get
63+
- run: flutter_rust_bridge_codegen generate
64+
- run: dart run build_runner build --delete-conflicting-outputs
65+
- run: cd example && flutter build apk --release
66+
67+
build-ios:
68+
name: iOS build
69+
needs: [rust, dart]
70+
runs-on: macos-latest
71+
steps:
72+
- uses: actions/checkout@v4
73+
- uses: subosito/flutter-action@v2
74+
with:
75+
channel: stable
76+
- uses: dtolnay/rust-toolchain@stable
77+
with:
78+
targets: aarch64-apple-ios,aarch64-apple-ios-sim
79+
- run: cargo install flutter_rust_bridge_codegen
80+
- run: flutter pub get
81+
- run: flutter_rust_bridge_codegen generate
82+
- run: dart run build_runner build --delete-conflicting-outputs
83+
- run: cd example && flutter build ios --simulator --debug
84+
85+
build-linux:
86+
name: Linux build
87+
needs: [rust, dart]
88+
runs-on: ubuntu-latest
89+
steps:
90+
- uses: actions/checkout@v4
91+
- uses: subosito/flutter-action@v2
92+
with:
93+
channel: stable
94+
- uses: dtolnay/rust-toolchain@stable
95+
- run: sudo apt-get update && sudo apt-get install -y clang cmake ninja-build pkg-config libgtk-3-dev
96+
- run: cargo install flutter_rust_bridge_codegen
97+
- run: flutter pub get
98+
- run: flutter_rust_bridge_codegen generate
99+
- run: dart run build_runner build --delete-conflicting-outputs
100+
- run: cd example && flutter build linux --release

rust/src/api/encryption/aes_gcm.rs

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -220,19 +220,15 @@ mod tests {
220220
fn nist_test_vector_decrypt() {
221221
let key = hex("feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308");
222222
let nonce = hex("cafebabefacedbaddecaf888");
223-
let expected_pt = hex(
224-
"d9313225f88406e5a55909c5aff5269a\
223+
let expected_pt = hex("d9313225f88406e5a55909c5aff5269a\
225224
86a7a9531534f7da2e4c303d8a318a72\
226225
1c3c0c95956809532fcf0e2449a6b525\
227-
b16aedf5aa0de657ba637b39",
228-
);
226+
b16aedf5aa0de657ba637b39");
229227
let aad = hex("feedfacedeadbeeffeedfacedeadbeefabaddad2");
230-
let ct = hex(
231-
"522dc1f099567d07f47f37a32a84427d\
228+
let ct = hex("522dc1f099567d07f47f37a32a84427d\
232229
643a8cdcbfe5c0c97598a2bd2555d1aa\
233230
8cb08e48590dbb3da7b08b1056828838\
234-
c5f61e6393ba7a0abcc9f662",
235-
);
231+
c5f61e6393ba7a0abcc9f662");
236232
let tag = hex("76fc6ece0f4e1768cddf8853bb2d551b");
237233

238234
// Build wire format: nonce || ciphertext || tag

rust/src/api/hashing/argon2.rs

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,8 @@ mod tests {
9595

9696
#[test]
9797
fn test_hash_contains_preset_params() {
98-
let hash = argon2id_hash("test".into(), Argon2Preset::Mobile)
99-
.expect("hashing should succeed");
98+
let hash =
99+
argon2id_hash("test".into(), Argon2Preset::Mobile).expect("hashing should succeed");
100100

101101
// Mobile: m=65536 (64*1024), t=3, p=4
102102
assert!(hash.contains("m=65536"), "Missing memory param: {}", hash);
@@ -106,8 +106,8 @@ mod tests {
106106

107107
#[test]
108108
fn test_hash_desktop_preset_params() {
109-
let hash = argon2id_hash("test".into(), Argon2Preset::Desktop)
110-
.expect("hashing should succeed");
109+
let hash =
110+
argon2id_hash("test".into(), Argon2Preset::Desktop).expect("hashing should succeed");
111111

112112
// Desktop: m=262144 (256*1024), t=4, p=8
113113
assert!(hash.contains("m=262144"), "Missing memory param: {}", hash);
@@ -147,7 +147,10 @@ mod tests {
147147
let hash2 = argon2id_hash_with_salt("password".into(), salt.into(), Argon2Preset::Mobile)
148148
.expect("hashing should succeed");
149149

150-
assert_eq!(hash1, hash2, "Same password + salt should produce same hash");
150+
assert_eq!(
151+
hash1, hash2,
152+
"Same password + salt should produce same hash"
153+
);
151154
}
152155

153156
#[test]
@@ -159,7 +162,10 @@ mod tests {
159162
let hash2 = argon2id_hash_with_salt("password2".into(), salt.into(), Argon2Preset::Mobile)
160163
.expect("hashing should succeed");
161164

162-
assert_ne!(hash1, hash2, "Different passwords should produce different hashes");
165+
assert_ne!(
166+
hash1, hash2,
167+
"Different passwords should produce different hashes"
168+
);
163169
}
164170

165171
#[test]
@@ -196,7 +202,11 @@ mod tests {
196202

197203
#[test]
198204
fn test_invalid_salt() {
199-
let result = argon2id_hash_with_salt("password".into(), "!!!invalid!!!".into(), Argon2Preset::Mobile);
205+
let result = argon2id_hash_with_salt(
206+
"password".into(),
207+
"!!!invalid!!!".into(),
208+
Argon2Preset::Mobile,
209+
);
200210
assert!(result.is_err());
201211
match result {
202212
Err(CryptoError::InvalidParameter(_)) => {} // expected
@@ -207,8 +217,8 @@ mod tests {
207217
#[test]
208218
fn test_empty_password_hashes() {
209219
// Empty password is valid — Argon2id should handle it
210-
let hash = argon2id_hash(String::new(), Argon2Preset::Mobile)
211-
.expect("empty password should hash");
220+
let hash =
221+
argon2id_hash(String::new(), Argon2Preset::Mobile).expect("empty password should hash");
212222
assert!(hash.starts_with("$argon2id$"));
213223
assert!(argon2id_verify(hash, String::new()).is_ok());
214224
}

rust/src/api/hashing/blake3.rs

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -56,23 +56,25 @@ mod tests {
5656
let digest = hasher.finalize().expect("finalize should succeed");
5757

5858
// BLAKE3 empty string hash (official test vector)
59-
let expected = hex::decode(
60-
"af1349b9f5f9a1a6a0404dea36dcc9499bcb25c9adc112b7cc9a93cae41f3262"
61-
).expect("valid hex");
59+
let expected =
60+
hex::decode("af1349b9f5f9a1a6a0404dea36dcc9499bcb25c9adc112b7cc9a93cae41f3262")
61+
.expect("valid hex");
6262

6363
assert_eq!(digest, expected);
6464
}
6565

6666
#[test]
6767
fn test_hello_world() {
6868
let mut hasher = Blake3Hasher::new();
69-
hasher.update(b"hello world").expect("update should succeed");
69+
hasher
70+
.update(b"hello world")
71+
.expect("update should succeed");
7072
let digest = hasher.finalize().expect("finalize should succeed");
7173

7274
// BLAKE3("hello world") - verified against reference implementation
73-
let expected = hex::decode(
74-
"d74981efa70a0c880b8d8c1985d075dbcbf679b99a5f9914e5aaf96b831a9e24"
75-
).expect("valid hex");
75+
let expected =
76+
hex::decode("d74981efa70a0c880b8d8c1985d075dbcbf679b99a5f9914e5aaf96b831a9e24")
77+
.expect("valid hex");
7678

7779
assert_eq!(digest, expected);
7880
}
@@ -101,7 +103,9 @@ mod tests {
101103

102104
// After reset, should produce empty hash
103105
let digest = hasher.finalize().expect("finalize should succeed");
104-
let empty_hash = Blake3Hasher::new().finalize().expect("finalize should succeed");
106+
let empty_hash = Blake3Hasher::new()
107+
.finalize()
108+
.expect("finalize should succeed");
105109

106110
assert_eq!(digest, empty_hash);
107111
}

rust/src/api/hashing/mod.rs

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
//! Hashing API module.
22
3+
pub mod argon2;
34
mod blake3;
45
mod sha3;
5-
pub mod argon2;
66

77
use crate::core::error::CryptoError;
88
use crate::core::traits::Hasher;
@@ -37,33 +37,37 @@ pub fn create_sha3() -> HasherHandle {
3737

3838
/// Feed data into the hasher.
3939
pub fn hasher_update(handle: &HasherHandle, data: Vec<u8>) -> Result<(), CryptoError> {
40-
let mut guard = handle.inner.lock().map_err(|_| {
41-
CryptoError::HashingFailed("Hasher lock poisoned".into())
42-
})?;
40+
let mut guard = handle
41+
.inner
42+
.lock()
43+
.map_err(|_| CryptoError::HashingFailed("Hasher lock poisoned".into()))?;
4344
guard.update(&data)
4445
}
4546

4647
/// Reset the hasher to its initial state.
4748
pub fn hasher_reset(handle: &HasherHandle) -> Result<(), CryptoError> {
48-
let mut guard = handle.inner.lock().map_err(|_| {
49-
CryptoError::HashingFailed("Hasher lock poisoned".into())
50-
})?;
49+
let mut guard = handle
50+
.inner
51+
.lock()
52+
.map_err(|_| CryptoError::HashingFailed("Hasher lock poisoned".into()))?;
5153
guard.reset()
5254
}
5355

5456
/// Finalize and return the digest.
5557
pub fn hasher_finalize(handle: &HasherHandle) -> Result<Vec<u8>, CryptoError> {
56-
let guard = handle.inner.lock().map_err(|_| {
57-
CryptoError::HashingFailed("Hasher lock poisoned".into())
58-
})?;
58+
let guard = handle
59+
.inner
60+
.lock()
61+
.map_err(|_| CryptoError::HashingFailed("Hasher lock poisoned".into()))?;
5962
guard.finalize()
6063
}
6164

6265
/// Get the algorithm identifier for the hasher.
6366
pub fn hasher_algorithm_id(handle: &HasherHandle) -> Result<String, CryptoError> {
64-
let guard = handle.inner.lock().map_err(|_| {
65-
CryptoError::HashingFailed("Hasher lock poisoned".into())
66-
})?;
67+
let guard = handle
68+
.inner
69+
.lock()
70+
.map_err(|_| CryptoError::HashingFailed("Hasher lock poisoned".into()))?;
6771
Ok(guard.algorithm_id().to_string())
6872
}
6973

rust/src/api/hashing/sha3.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,9 @@ mod tests {
5757
let digest = hasher.finalize().expect("finalize should succeed");
5858

5959
// NIST SHA-3 empty string test vector
60-
let expected = hex::decode(
61-
"a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a",
62-
)
63-
.expect("valid hex");
60+
let expected =
61+
hex::decode("a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a")
62+
.expect("valid hex");
6463

6564
assert_eq!(digest, expected);
6665
}
@@ -72,10 +71,9 @@ mod tests {
7271
let digest = hasher.finalize().expect("finalize should succeed");
7372

7473
// NIST SHA-3("abc") test vector
75-
let expected = hex::decode(
76-
"3a985da74fe225b2045c172d6bd390bd855f086e3e9d525b46bfe24511431532",
77-
)
78-
.expect("valid hex");
74+
let expected =
75+
hex::decode("3a985da74fe225b2045c172d6bd390bd855f086e3e9d525b46bfe24511431532")
76+
.expect("valid hex");
7977

8078
assert_eq!(digest, expected);
8179
}
@@ -104,7 +102,9 @@ mod tests {
104102

105103
// After reset, should produce empty hash
106104
let digest = hasher.finalize().expect("finalize should succeed");
107-
let empty_hash = Sha3Hasher::new().finalize().expect("finalize should succeed");
105+
let empty_hash = Sha3Hasher::new()
106+
.finalize()
107+
.expect("finalize should succeed");
108108

109109
assert_eq!(digest, empty_hash);
110110
}

0 commit comments

Comments
 (0)