Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,13 @@ Anchor aims for high test coverage with different types of tests:
- Use trait mocking when needed
- Consider dependency injection for easier testing

6. **Testing Production Code Paths**:
- **NEVER add production logic directly in test code** - tests should call actual production functions and verify their behavior
- It's acceptable to mock external dependencies (databases, network calls, etc.) to isolate the code under test
- However, avoid duplicating or simulating the actual business logic being tested within the test itself
- If production code has a behavior (like disconnecting peers on handshake failure), the test should call the production code that performs this behavior, not implement the disconnection logic in the test
- When tests bypass certain system layers, consider restructuring the test to go through the actual production code paths rather than adding the bypassed logic to the test

## Contribution Workflow

When contributing to Anchor, follow these steps to ensure high-quality code that meets project standards:
Expand Down
26 changes: 13 additions & 13 deletions anchor/network/src/network.rs
Original file line number Diff line number Diff line change
Expand Up @@ -231,10 +231,7 @@ impl<R: MessageReceiver> Network<R> {
.peers_to_disconnect_due_to_subnets();

for peer_id in to_disconnect {
match self.swarm.disconnect_peer_id(peer_id) {
Ok(_) => debug!(%peer_id, "Disconnected peer due to no subnets"),
Err(_) => trace!(%peer_id, "Peer was already disconnected"),
}
self.disconnect_peer(&peer_id, "No longer subscribed to any needed subnets");
}
}
_ => {
Expand Down Expand Up @@ -519,6 +516,9 @@ impl<R: MessageReceiver> Network<R> {
}
Err(handshake::Failed { peer_id, error }) => {
debug!(%peer_id, ?error, "Handshake failed");

// Disconnect the peer on handshake failure
self.disconnect_peer(&peer_id, "Handshake failed");
}
}
}
Expand Down Expand Up @@ -555,7 +555,7 @@ impl<R: MessageReceiver> Network<R> {

for peer_id in &peers_to_block_and_disconnect {
self.swarm.behaviour_mut().peer_manager.block_peer(*peer_id);
self.disconnect_peer(peer_id);
self.disconnect_peer(peer_id, "Blocking peer due to low score");
}

if excess > 0 {
Expand All @@ -567,23 +567,23 @@ impl<R: MessageReceiver> Network<R> {
.map(|(p, _)| *p);

for peer_id in to_disconnect {
self.disconnect_peer(&peer_id);
self.disconnect_peer(&peer_id, "Pruning excess peers by score");
}
}
}

fn disconnect_peer(&mut self, peer_id: &PeerId) {
match self.swarm.disconnect_peer_id(*peer_id) {
Ok(_) => debug!(%peer_id, "Disconnected peer due to low score"),
Err(_) => trace!(%peer_id, "Peer was already disconnected"),
}
}

fn dial(&mut self, opts: DialOpts) {
if let Err(err) = self.swarm.dial(opts) {
debug!(%err, "Failed to dial peer");
}
}

fn disconnect_peer(&mut self, peer_id: &PeerId, reason: &str) {
match self.swarm.disconnect_peer_id(*peer_id) {
Ok(_) => debug!(%peer_id, reason = %reason, "Disconnected peer"),
Err(_) => trace!(%peer_id, "Peer was already disconnected"),
}
}
}

fn build_swarm(
Expand Down