Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add tests for manually manipulated DB #410

Open
djmitche opened this issue Jul 3, 2024 · 5 comments
Open

Add tests for manually manipulated DB #410

djmitche opened this issue Jul 3, 2024 · 5 comments
Assignees
Labels
good first issue Good for newcomers
Milestone

Comments

@djmitche
Copy link
Collaborator

djmitche commented Jul 3, 2024

In GothenburgBitFactory/taskwarrior#3530 @snaka224 mentioned they edited the DB. They probably aren't the first or only person to do so!

The result is a "corrupted" DB in the sense that an invariant is invalidated: the cumulative effects of the ops in the operations table are not the same as the tasks table.

Let's add some tests for that circumstance to ensure that at least the "blast radius" of this corruption is limited.

  • TC does not panic or crash
  • Sync continues to run successfully
  • Only the modified task is affected locally
  • After sync, only the modified task is different between replicas

This would be a good first task since it just requires writing some tests. If bugs are found, we can file and fix those separately. The resulting tests are probably a mix of unit-style tests (such as for apply when an Update operation is applied to a task that has been deleted) and integration tests (for things that involve running sync). There are already some example integration tests in taskchampion/tests.

@koleesch
Copy link
Contributor

koleesch commented Jul 8, 2024

I will try to write the tests.

@koleesch
Copy link
Contributor

koleesch commented Jul 8, 2024

Currently I have no idea, where i can start.

@djmitche
Copy link
Collaborator Author

djmitche commented Jul 9, 2024

It may be good to familiarize yourself with the data model, if you haven't already: https://gothenburgbitfactory.org/taskchampion/

The key is the "Replica Invariant". TaskChampion itself maintains that invariant, but users mucking about manually in taskchampion.sqlite3 might invalidate it. The idea of this issue is to test those conditions and make sure TaskChampion is behaving appropriately (and we can think about what that means).

The taskdb layer is defined in taskchampion/src/taskdb and apply is defined in apply.rs. That file actually has two functions in it (and a bunch of tests, which you may want to add to) -- apply_and_record and apply_op. If I recall, the first is used when a change is made locally, so it modifies the state and adds the operation to the list of operations. The second is used during sync, to apply an operation received from the sync server. That operation is only applied to the current state, and not recorded in the list of operations.

I see that both of those functions have some interesting error handling. For example:

SyncOp::Delete { ref uuid } => {
if !txn.delete_task(*uuid)? {
return Err(Error::Database(format!("Task {} does not exist", uuid)));
}
}

If a user has used task delete on another replica, but locally gotten frustrated and gone into the DB to run DELETE from tasks where uuid = ..., what will happen when that user sync's the task deletion into this repo? apply_op will return an error. How is that handled? (hint: sync.rs)

There are integration-style tests such as update-and-delete-sync.rs. These take a bit longer to run, but are a good way to test end-to-end functionality (everything from the storage layer through the taskdb to the Replica type).

So, I'd say the overall to-do list for this issue is:

  • Write down all of the ways the user might violate the Replica Invariant by modifying the DB
  • Simulate those situations in tests
  • Verify that the results we check for in the tests match what we want (I can help reason through this part)

A good place to start is to identify one way the user might violate the invariant, and write a test for that. Let's start with an integration test (maybe in a new taskchampion/tests/replica-invariant-violations.rs largely copied from one of the other tests?), unless the case you come up with is a good fit for a unit test.

@djmitche
Copy link
Collaborator Author

djmitche commented Aug 3, 2024

@koleesch how is this going?

@djmitche djmitche modified the milestones: v0.7.0, v0.8.0 Aug 5, 2024
@djmitche
Copy link
Collaborator Author

djmitche commented Aug 5, 2024

BTW the invariant mentioned in the first comment is here

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
good first issue Good for newcomers
Projects
Status: In progress
Development

No branches or pull requests

2 participants