POC for Integration Testing#62
Conversation
|
@rudyfraser Is an approach like this something on the table? |
Yeah, definitely. As long as tests can still run concurrently and the DBs are torn down after the tests complete I'm good with this approach. |
|
Having to address some tech debt related to establish_connection() to properly implement |
|
Will clean up and make a new pull request. Only thing last to check is how it behaves on the Github pipeline |
# Conflicts: # rsky-pds/src/main.rs
|
Came across integration-test issue as service is dependent on environment variables to startup. @rudyfraser is it possible for us to pass environment variables necessary to start an rsky-pds in the github action? The specific erroring for this one is on "PDS_ADMIN_PASS" |
Should resolve issues in #62
|
I added a bunch of environment vars to the GitHub workflow that should fix this but let me know if it isn't squared away. |
Updated pipeline
Thanks! It looks like build is failing testing when it uses the secrets field specifically? Unsure why that is. I passed it some hard values for the time being to validate that. Other than that, can confirm that test containers is working. Going to cleanup the PR a bit and then move it into "Ready for Review" |
|
Any feedback on this one? |
|
If this is ready to go before OAuth, we can have integration testing for oauth ideally |
|
Missed this, sorry. Thanks for the ping. Will review tonight. |
There was a problem hiding this comment.
The tests look good. However, I’m not a fan of the foo_v2 pattern (I stopped commenting on it midway).
Instead, I think AccountManager should be updated from:
#[derive(Clone)]
pub struct AccountManager {}to:
#[derive(Clone)]
pub struct AccountManager {
pub db: Arc<DbConn>
}Then, update the functions to be instance methods (&self) instead of static functions.
This aligns with the TypeScript implementation and helps keep things DRY.
There was a problem hiding this comment.
What's the reasoning behind the foo_v2 pattern? Any reason to not refactor the code to use DbConn entirely? That's where I'd like things to go in any case and get rid of "establish_connection" where possible. It's a bit of technical debt.
There was a problem hiding this comment.
I was using v2 to avoid having to do a total rewrite of the connection pattern yet. Plan was to move all to v2, then remove the old method, and then just remove v2
| pub async fn store_refresh_token_v2( | ||
| payload: RefreshToken, | ||
| app_password_name: Option<String>, | ||
| db: &DbConn, | ||
| ) -> Result<()> { | ||
| use crate::schema::pds::refresh_token::dsl as RefreshTokenSchema; | ||
|
|
||
| let exp = from_micros_to_utc((payload.exp.as_millis() / 1000) as i64); | ||
|
|
||
| db.run(move |conn| { | ||
| insert_into(RefreshTokenSchema::refresh_token) | ||
| .values(( | ||
| RefreshTokenSchema::id.eq(payload.jti), | ||
| RefreshTokenSchema::did.eq(payload.sub), | ||
| RefreshTokenSchema::appPasswordName.eq(app_password_name), | ||
| RefreshTokenSchema::expiresAt.eq(format!("{}", exp.format(RFC3339_VARIANT))), | ||
| )) | ||
| .on_conflict_do_nothing() // E.g. when re-granting during a refresh grace period | ||
| .execute(conn) | ||
| }) | ||
| .await?; | ||
|
|
There was a problem hiding this comment.
Similar question here on need for v2
There was a problem hiding this comment.
I was using v2 to avoid having to do a total rewrite of the connection pattern yet. Plan was to move all to v2, then remove the old method, and then just remove v2
There was a problem hiding this comment.
I'd rather not have the transition period. Let me know if you'd like me to take on the migration to the v2 pattern.
There was a problem hiding this comment.
I can take this up
There was a problem hiding this comment.
Can have it updated by end of the weekend
| pub async fn update_root_v2(did: String, cid: Cid, rev: String, db: &DbConn) -> Result<()> { | ||
| // @TODO balance risk of a race in the case of a long retry | ||
| use crate::schema::pds::repo_root::dsl as RepoRootSchema; | ||
|
|
||
| let now = rsky_common::now(); | ||
|
|
||
| db.run(move |conn| { | ||
| insert_into(RepoRootSchema::repo_root) | ||
| .values(( | ||
| RepoRootSchema::did.eq(did), | ||
| RepoRootSchema::cid.eq(cid.to_string()), | ||
| RepoRootSchema::rev.eq(rev.clone()), | ||
| RepoRootSchema::indexedAt.eq(now), | ||
| )) | ||
| .on_conflict(RepoRootSchema::did) | ||
| .do_update() | ||
| .set(( | ||
| RepoRootSchema::cid.eq(cid.to_string()), | ||
| RepoRootSchema::rev.eq(rev), | ||
| )) | ||
| .execute(conn) | ||
| }) | ||
| .await?; | ||
|
|
||
| Ok(()) | ||
| } |
| client | ||
| .post("/xrpc/com.atproto.server.createAccount") | ||
| .header(ContentType::JSON) | ||
| .header(Header::new("Authorization", get_admin_token())) | ||
| .body(account_input.to_string()) | ||
| .dispatch() | ||
| .await; | ||
|
|
||
| ("dummyemail@rsky.com".to_string(), "password".to_string()) |
There was a problem hiding this comment.
What happens if there's an error here in creating the account (for example, generating a DID)?
There was a problem hiding this comment.
I can add an assert. Currently it will cause the tests utilizing the function to fail as the account won't exist.
There was a problem hiding this comment.
From what I can see it's only used in test_create_session. And if it isn't creating an account then what is it actually doing?
There was a problem hiding this comment.
It does create an account, if it was to fail currently the account wouldn't exist at all tests would fail
There was a problem hiding this comment.
Testing specific function to make tests easier to write
|
@rudyfraser Left some comments |
Will have an update for this later today |
I need to check how this plays with the Rocket Fairing specifically |
|
Realized changing AccountManager to a state like that has some knock on effects as currently it is used in LocalViewer, which will mean LocalViewer will need updates and changes as well |
Does this mean you'd like to hold off on making the changes or that you're in the middle of changes but will take some more time? |
I was in the middle of making the changes, but realized that there are some key differences in the typescript reference. One of them is that because it uses SQLite, it doesn't use a connection pool to establish the connection. Because LocalViewer is a Read/Write Lock, but the db connection pool is managed by Rocket, I'd like to move the function logic into the SharedLocalViewer instead and have the SharedLocalViewer be a request guard that utilizes the local viewer state. My main concern is it bloats the pull request into even more changes. If that's acceptable, I can do it, but it will have affects |
|
Instead of naming the new functions "foo_v2", please rename the old function "bar_legacy" and add the #[deprecated] attribute to them. |
Can do, will update later today for review |
|
@rudyfraser Renamed v2 and marked old functions as legacy |
# Conflicts: # .gitignore
Summary
Implementation of Integration Testing for the RSky-PDS APIs. As of now, there are only unit tests for small pieces of logic and nothing that would cover an endpoint in itself. This adds several integration tests, and supplies the starting framework to be used for writing API integration tests going forward.
Rocket method will be moved into the library rsky-pds package in order to properly test, where the main would simply call it once.
Strategy is
Components that may need either mocking, or creative solutions (Not yet implemented)
Other Updates
Related Issues
#49
#24
Changes
Checklist