Skip to content

Commit

Permalink
identities: updated delegation causes replication failure
Browse files Browse the repository at this point in the history
We have the following steps:
* Peer 1 creates a Person document
* Peer 2 replicates this Person
* Peer 1 updates Person document
* Peer 1 creates Project delegating to new Person document
* Peer 2 attempts to replicate the Project, but fails with error below

Error:
```
Revision 7bb4bbce268d89a62e1962f5dded7a9f68c9e665 of 4b84e8407d602317b01f22207908dbea1d9d4e17 not in ancestry path of eada5419806f643d402c92b790c9b471098f1e81
```

Signed-off-by: Fintan Halpenny <[email protected]>
  • Loading branch information
FintanH committed Jun 24, 2021
1 parent 723a08b commit 75cb749
Show file tree
Hide file tree
Showing 3 changed files with 159 additions and 0 deletions.
74 changes: 74 additions & 0 deletions test/src/rad/identities.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,60 @@ use librad::{
signer::Signer,
};

pub struct TestPerson {
pub owner: Person,
}

impl TestPerson {
pub fn create(storage: &Storage) -> anyhow::Result<Self> {
let peer_id = storage.peer_id();
let alice = identities::person::create(
storage,
payload::Person {
name: "alice".into(),
},
Some(*peer_id.as_public_key()).into_iter().collect(),
)?;

Ok(Self { owner: alice })
}

pub fn update(self, storage: &Storage) -> anyhow::Result<Self> {
let payload = payload::Person {
name: "alice-laptop".into(),
}
.into();
let owner =
identities::person::update(storage, &self.owner.urn(), None, Some(payload), None)?;
Ok(Self { owner })
}

/// Pull (fetch or clone) the project from known running peer `A` to peer
/// `B`.
pub async fn pull<A, B, S>(&self, from: &A, to: &B) -> anyhow::Result<ReplicateResult>
where
A: Deref<Target = Peer<S>> + LocalInfo<Addr = SocketAddr>,
B: Deref<Target = Peer<S>>,

S: Signer + Clone,
{
let remote_peer = from.local_peer_id();
let remote_addrs = from.listen_addrs();
let urn = self.owner.urn();
let cfg = to.protocol_config().replication;
let res = to
.using_storage(move |storage| {
let fetcher = fetcher::PeerToPeer::new(urn, remote_peer, remote_addrs)
.build(&storage)
.unwrap()
.unwrap();
replication::replicate(&storage, fetcher, cfg, None)
})
.await??;
Ok(res)
}
}

pub struct TestProject {
pub owner: Person,
pub project: Project,
Expand Down Expand Up @@ -50,6 +104,26 @@ impl TestProject {
})
}

pub fn from_test_person(storage: &Storage, person: TestPerson) -> anyhow::Result<Self> {
let local_id = identities::local::load(storage, person.owner.urn())?
.expect("local id must exist as we just created it");
let proj = identities::project::create(
storage,
local_id,
payload::Project {
name: "radicle-link".into(),
description: Some("pea two pea".into()),
default_branch: Some("next".into()),
},
delegation::Indirect::from(person.owner.clone()),
)?;

Ok(Self {
owner: person.owner,
project: proj,
})
}

pub fn from_project_payload(
storage: &Storage,
owner: Person,
Expand Down
1 change: 1 addition & 0 deletions test/src/test/integration/librad/scenario.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@

mod collaboration;
mod menage;
mod updated_delegate;
mod working_copy;
84 changes: 84 additions & 0 deletions test/src/test/integration/librad/scenario/updated_delegate.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// Copyright © 2019-2020 The Radicle Foundation <[email protected]>
//
// This file is part of radicle-link, distributed under the GPLv3 with Radicle
// Linking Exception. For full terms see the included LICENSE file.

use std::ops::Index as _;

use librad::git::storage::ReadOnlyStorage as _;

use crate::{
logging,
rad::{
identities::{TestPerson, TestProject},
testnet,
},
};

fn config() -> testnet::Config {
testnet::Config {
num_peers: nonzero!(2usize),
min_connected: 2,
bootstrap: testnet::Bootstrap::from_env(),
}
}

#[test]
fn can_replicate_with_updated_delegate() {
logging::init();

let net = testnet::run(config()).unwrap();
net.enter(async {
let peer1 = net.peers().index(0);
let peer2 = net.peers().index(1);

let person = {
let person = peer1
.using_storage(move |storage| TestPerson::create(&storage))
.await
.unwrap()
.unwrap();
person.pull(peer1, peer2).await.ok().unwrap();
person
};

let has = peer2
.using_storage({
let urn = person.owner.urn();
move |storage| storage.has_urn(&urn)
})
.await
.unwrap()
.unwrap();
assert!(has);

let person = {
let person = peer1
.using_storage(move |storage| person.update(&storage))
.await
.unwrap()
.unwrap();
person
};

let proj = {
let proj = peer1
.using_storage(move |storage| TestProject::from_test_person(storage, person))
.await
.unwrap()
.unwrap();
proj.pull(peer1, peer2).await.unwrap();
proj
};

let has = peer2
.using_storage({
let urn = proj.project.urn();
move |storage| storage.has_urn(&urn)
})
.await
.unwrap()
.unwrap();
assert!(has);
})
}

0 comments on commit 75cb749

Please sign in to comment.