Skip to content

Commit

Permalink
feat(Testsuit): 🎉 first test(admin_login)
Browse files Browse the repository at this point in the history
  • Loading branch information
Eason0729 committed Jan 1, 2024
1 parent 75044ee commit 9561529
Show file tree
Hide file tree
Showing 15 changed files with 119 additions and 100 deletions.
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"conventionalCommits.scopes": [
"Frontend",
"Backend",
"Judger"
"Judger",
"Testsuit"
]
}
3 changes: 2 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ members = [
prost = "0.12.3"
prost-types = "0.12.3"
tonic-build = "0.10.2"
tonic-web = "0.10.2"

[workspace.dependencies.tonic]
version = "0.10.2"
Expand Down
3 changes: 2 additions & 1 deletion backend/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ futures = "0.3.29"
bincode = "1.3.3"
base64 = "0.21.5"
uuid = "1.5.0"
tonic-web = "0.10.2"
tonic-web = { workspace = true }
quick_cache = "0.4.0"
leaky-bucket = "1.0.1"
hickory-resolver = "0.24.0"
Expand Down Expand Up @@ -90,3 +90,4 @@ tonic-build = { workspace = true }
default = ["single-instance"]
unsecured-log = []
single-instance = []
testsuit = []
1 change: 1 addition & 0 deletions backend/migration/src/m20231207_000001_create_table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -619,6 +619,7 @@ impl MigrationTrait for Migration {
index!(manager, User, Score);
index!(manager, User, Username);
index!(manager, Token, Rand);
index!(manager, Token, Expiry);
index!(manager, Chat, CreateAt);

manager
Expand Down
5 changes: 3 additions & 2 deletions backend/src/endpoint/token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use std::time::Duration;
use super::endpoints::*;
use super::tools::*;

use crate::controller::token::UserPermBytes;
use crate::grpc::backend::token_set_server::*;
use crate::grpc::backend::*;
use crate::grpc::into_chrono;
Expand Down Expand Up @@ -77,7 +78,7 @@ impl TokenSet for Arc<Server> {

Ok(Response::new(TokenInfo {
token: token.into(),
permission: model.permission as u64,
permission: UserPermBytes(model.permission).into(),
expiry: into_prost(expiry),
}))
} else {
Expand Down Expand Up @@ -115,7 +116,7 @@ impl TokenSet for Arc<Server> {
let (token, expiry) = self.token.add(&user, dur).await?;
return Ok(Response::new(TokenInfo {
token: token.into(),
permission: perm.0 as u64,
permission: perm.into(),
expiry: into_prost(expiry),
}));
}
Expand Down
18 changes: 18 additions & 0 deletions backend/src/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ impl Server {
_otel_guard: otel_guard,
})
}
#[cfg(not(feature="testsuit"))]
pub async fn start(self: Arc<Self>) {
transport::Server::builder()
.accept_http1(true)
Expand All @@ -75,4 +76,21 @@ impl Server {
.await
.unwrap();
}
#[cfg(feature="testsuit")]
pub async fn start(self: Arc<Self>) {
transport::Server::builder()
.accept_http1(true)
.max_frame_size(Some(MAX_FRAME_SIZE))
.add_service(ProblemSetServer::new(self.clone()))
.add_service(EducationSetServer::new(self.clone()))
.add_service(UserSetServer::new(self.clone()))
.add_service(TokenSetServer::new(self.clone()))
.add_service(ContestSetServer::new(self.clone()))
.add_service(TestcaseSetServer::new(self.clone()))
.add_service(SubmitSetServer::new(self.clone()))
.add_service(ChatSetServer::new(self.clone()))
.serve(self.config.bind_address.clone().parse().unwrap())
.await
.unwrap();
}
}
2 changes: 1 addition & 1 deletion proto/backend.proto
Original file line number Diff line number Diff line change
Expand Up @@ -608,7 +608,7 @@ service UserSet {

message TokenInfo {
required Token token = 1;
required uint64 permission = 2;
required Permission permission = 2;
required google.protobuf.Timestamp expiry = 3;
}

Expand Down
25 changes: 12 additions & 13 deletions testsuit/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,40 +14,39 @@ uuid = "1.5.0"
anyhow = "1.0.75"
tower = "0.4.13"
env_logger = "0.10.1"
prost = "0.12.3"
prost-types = "0.12.3"
tonic-web = "0.10.2"
prost = { workspace = true }
prost-types = { workspace = true }
tonic-web = { workspace = true }
futures-core = "0.3.29"
tokio-rustls = "0.24.1"
rustls-pki-types = "1.0.1"

[dependencies.rustls]
version ="0.21.9"
features = ["dangerous_configuration"]
rustls = "0.21.9"
http-body = "0.4.6"

[dependencies.tokio-stream]
version = "0.1.14"
features =["sync"]
features = ["sync"]

[dependencies.tracing-subscriber]
version = "0.3.17"
features =["json"]
features = ["json"]

[dependencies.tokio]
version = "1.28.0"
features =["macros", "rt-multi-thread", "full","time"]
features = ["macros", "rt-multi-thread", "full", "time"]

[dependencies.serde]
version = "1.0.163"
features = ["derive"]

[dependencies.tonic]
version = "0.10.2"
workspace = true
features = ["transport", "channel", "codegen", "tls", "prost"]

[dependencies.hyper]
version ="0.14.27"
features=["client","http1","http2"]
version = "0.14.27"
features = ["client", "http1", "http2"]

[build-dependencies]
tonic-build = "0.9.2"
tonic-build = { workspace = true }
23 changes: 12 additions & 11 deletions testsuit/src/case.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use tonic::async_trait;
#[async_trait]
pub trait Case<S: Send + Sync> {
const NAME: &'static str;

async fn run(&self, state: &mut S) -> Result<(), String>;
}

Expand All @@ -23,27 +24,27 @@ impl<S: Send + Sync, Rhs: Case<S> + Send + Sync + 'static> Runable<S> for Rhs {
}
}

pub struct CaseRunner<S: Send + Sync> {
#[derive(Default)]
pub struct CaseRunner<S: Send + Sync + Default> {
case: Vec<Box<dyn Runable<S> + Send + Sync + 'static>>,
state: S,
}

impl<S: Send + Sync> CaseRunner<S> {
pub async fn new(state: S) -> Self {
Self {
case: Vec::new(),
state,
}
}
impl<S: Send + Sync + Default> CaseRunner<S> {
pub fn add_case<Rhs: Case<S> + Send + Sync + 'static>(&mut self, case: Rhs) {
self.case.push(Box::new(case));
}
pub async fn run(mut self) {
log::info!("Start testsuit");
pub async fn run(mut self, title: &'static str) -> S {
log::info!("Start testsuit {}", title);
for (i, case) in self.case.into_iter().enumerate() {
log::info!("Running case {} {}", i, case.name());
case.run(&mut self.state).await.unwrap();
if let Err(err) = case.run(&mut self.state).await {
log::error!("test fail: {}", err);
break;
}
}
log::info!("End");

self.state
}
}
72 changes: 12 additions & 60 deletions testsuit/src/client.rs
Original file line number Diff line number Diff line change
@@ -1,63 +1,15 @@
// use std::sync::Arc;
use http_body::combinators::UnsyncBoxBody;
use hyper::client::HttpConnector;
use tonic_web::{GrpcWebCall, GrpcWebClientLayer, GrpcWebClientService};

// use crate::grpc::backend::token_set_client::TokenSetClient;
// use hyper::{client::HttpConnector, Uri};
// use rustls::client::{DangerousClientConfig, ServerCertVerifier, ServerCertVerified};
// use rustls_pki_types::*;
// use tokio_rustls::rustls::*;
pub type Intercepter = GrpcWebClientService<
hyper::Client<HttpConnector, GrpcWebCall<UnsyncBoxBody<hyper::body::Bytes, tonic::Status>>>,
>;

// #[derive(Debug)]
// pub struct AllowAllVerifier;
pub fn connection() -> Intercepter {
let client = hyper::Client::builder().build_http();

// impl ServerCertVerifier for AllowAllVerifier {
// fn supported_verify_schemes(&self) -> Vec<tokio_rustls::rustls::SignatureScheme> {
// vec![tokio_rustls::rustls::SignatureScheme::RSA_PSS_SHA256]
// }

// fn verify_server_cert(
// &self,
// end_entity: &Certificate,
// intermediates: &[Certificate],
// server_name: &rustls::ServerName,
// scts: &mut dyn Iterator<Item = &[u8]>,
// ocsp_response: &[u8],
// now: std::time::SystemTime,
// ) -> Result<ServerCertVerified, Error> {
// todo!()
// }
// }

// fn tls_config() -> ClientConfig {
// let verifier = Arc::new(AllowAllVerifier) as Arc<(dyn ServerCertVerifier + 'static)>;
// let mut tls_config = ClientConfig::builder().with_safe_defaults().with_no_client_auth()
// ;
// // .with_custom_certificate_verifier(verifier)
// // .with_no_client_auth();
// tls_config
// }

// pub struct Clients {}

// async fn token_client() {
// // let tls = tls_config();

// // let mut http = HttpConnector::new();
// // http.enforce_http(false);

// // // We have to do some wrapping here to map the request type from
// // // `https://example.com` -> `https://[::1]:50051` because `rustls`
// // // doesn't accept ip's as `ServerName`.
// // let connector = tower::ServiceBuilder::new()
// // .layer_fn(move |s| {
// // let tls = tls.clone();

// // hyper_rustls::HttpsConnectorBuilder::new()
// // .with_tls_config(tls)
// // .https_or_http()
// // })
// // // Since our cert is signed with `example.com` but we actually want to connect
// // // to a local server we will override the Uri passed from the `HttpsConnector`
// // // and map it to the correct `Uri` that will connect us directly to the local server.
// // .map_request(|_| Uri::from_static("https://[::1]:50051"))
// // .service(http);
// }
tower::ServiceBuilder::new()
.layer(GrpcWebClientLayer::new())
.service(client)
}
3 changes: 3 additions & 0 deletions testsuit/src/constant.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pub static SERVER: &str = "http://localhost:8081";
pub static ADMIN: &str = "admin";
pub static ADMIN_PWD: &str = "admin";
4 changes: 3 additions & 1 deletion testsuit/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
pub mod case;
pub mod client;
pub mod constant;
pub mod grpc;
pub mod user;

Expand All @@ -8,5 +9,6 @@ async fn main() {
env_logger::builder()
.filter_module("testsuit", log::LevelFilter::Trace)
.init();
// user::run().await;

user::run().await;
}
36 changes: 34 additions & 2 deletions testsuit/src/user/login.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
use crate::case::Case;
use crate::{
case::Case,
client::connection,
constant,
grpc::backend::{token_set_client::TokenSetClient, LoginRequest},
};

use super::State;

Expand All @@ -9,6 +14,33 @@ impl Case<State> for AdminLogin {
const NAME: &'static str = "login as admin@admin";

async fn run(&self, state: &mut State) -> Result<(), String> {
todo!()
let mut client =
TokenSetClient::with_origin(connection(), constant::SERVER.try_into().unwrap());

let res = client
.create(LoginRequest {
username: constant::ADMIN.to_string(),
password: constant::ADMIN_PWD.to_string(),
expiry: None,
})
.await
.unwrap();

let res = res.into_inner();

assert!(res.permission.can_root);
assert!(!res.permission.can_link);
assert!(!res.permission.can_manage_announcement);
assert!(!res.permission.can_manage_chat);
assert!(!res.permission.can_manage_contest);
assert!(!res.permission.can_manage_education);
assert!(!res.permission.can_manage_problem);
assert!(!res.permission.can_manage_submit);
assert!(!res.permission.can_manage_user);
assert!(!res.permission.can_publish);
assert!(!res.permission.can_imgur);

state.token = Some(res.token.signature);
Ok(())
}
}
20 changes: 13 additions & 7 deletions testsuit/src/user/mod.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
// mod login;
// use crate::{client::Clients, grpc::*};
mod login;
use crate::{case::CaseRunner, user::login::AdminLogin};

// struct State {
// token: Option<String>,
// clients: Clients,
// }
#[derive(Default)]
pub struct State {
token: Option<String>,
}

// pub async fn run() {}
pub async fn run() -> State {
let mut user_runner = CaseRunner::<State>::default();

user_runner.add_case(AdminLogin);

user_runner.run("user").await
}

0 comments on commit 9561529

Please sign in to comment.