Skip to content

Commit bd899c6

Browse files
authored
test(api-db): Move DB-only API tests from api-core into api-db (#2652)
- Moves DB-only tests out of api-core and into the owning api-db modules. - Covers domain creation, rack/switch/power shelf metadata, machine interface IP allocation, machine interface address lookup, and duplicate MAC handling. - Adds api-db::test_support::network_segment::admin_segment for shared DB test fixture setup. - Removes TestEnv/API harness usage from these tests where direct DB setup is enough. ## Related issues #2001 ## Type of Change - [ ] **Add** - New feature or capability - [ ] **Change** - Changes in existing functionality - [ ] **Fix** - Bug fixes - [ ] **Remove** - Removed features or deprecated functionality - [x] **Internal** - Internal changes (refactoring, tests, docs, etc.) ## Breaking Changes - [ ] **This PR contains breaking changes** ## Testing - [ ] Unit tests added/updated - [ ] Integration tests added/updated - [ ] Manual testing performed - [x] No testing required (docs, internal refactor, etc.) ## Additional Notes --------- Signed-off-by: Dmitry Porokh <dporokh@nvidia.com>
1 parent 18578dd commit bd899c6

17 files changed

Lines changed: 149 additions & 85 deletions

File tree

crates/api-core/src/tests/mod.rs

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ mod client_resolution;
2020
pub mod common;
2121
mod compute_allocation;
2222
mod connected_device;
23-
mod create_domain;
2423
mod credential;
2524
mod dhcp_lease_expiration;
2625
mod dns;
@@ -57,7 +56,6 @@ mod instance_find;
5756
mod instance_ipxe_behaviors;
5857
mod instance_os;
5958
mod instance_type;
60-
mod ip_allocator;
6159
mod ipxe;
6260
mod level_filter;
6361
mod lldp;
@@ -70,7 +68,6 @@ mod machine_discovery;
7068
mod machine_find;
7169
mod machine_health;
7270
mod machine_history;
73-
mod machine_interface_addresses;
7471
mod machine_interfaces;
7572
mod machine_metadata;
7673
mod machine_network;
@@ -96,13 +93,10 @@ mod operating_system;
9693
mod power_shelf;
9794
mod power_shelf_find;
9895
mod power_shelf_health;
99-
mod power_shelf_metadata;
10096
mod power_shelf_state_controller;
10197
mod preingestion_dpu_nic_mode;
102-
mod prevent_duplicate_mac_addresses;
10398
mod rack_find;
10499
mod rack_health;
105-
mod rack_metadata;
106100
mod rack_state_controller;
107101
mod redfish_actions;
108102
mod resource_pool;
@@ -118,7 +112,6 @@ mod storage;
118112
mod switch;
119113
mod switch_find;
120114
mod switch_health;
121-
mod switch_metadata;
122115
mod switch_state_controller;
123116
mod tenant_keyset_find;
124117
mod tenants;

crates/api-db/src/dns/domain.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ use super::super::{ColumnInfo, FilterableQueryBuilder, ObjectColumnFilter};
2727
use crate::db_read::DbReader;
2828
use crate::{DatabaseError, DatabaseResult};
2929

30+
#[cfg(test)]
31+
mod test_create_domain;
32+
3033
/// Validates a domain name according to DNS standards
3134
fn validate_domain_name(name: &str) -> Result<(), DatabaseError> {
3235
if name != name.to_lowercase() {

crates/api-core/src/tests/create_domain.rs renamed to crates/api-db/src/dns/domain/test_create_domain.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,11 @@
1414
* See the License for the specific language governing permissions and
1515
* limitations under the License.
1616
*/
17+
1718
use db::ObjectColumnFilter;
1819
use model::dns::NewDomain;
1920

21+
use crate as db;
2022
use crate::DatabaseError;
2123

2224
#[crate::sqlx_test]

crates/api-db/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,9 @@ pub mod vpc_peering;
9696
pub mod vpc_prefix;
9797
pub mod work_lock_manager;
9898

99+
#[cfg(test)]
100+
mod test_support;
101+
99102
use std::backtrace::{Backtrace, BacktraceStatus};
100103
use std::error::Error;
101104
use std::fmt::{Display, Formatter};

crates/api-db/src/machine_interface.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,10 @@ impl ColumnInfo<'_> for IdColumn {
9595
}
9696
}
9797

98+
#[cfg(test)]
99+
mod ip_allocator;
100+
#[cfg(test)]
101+
mod test_duplicate_mac;
98102
#[cfg(test)]
99103
mod tests;
100104

crates/api-core/src/tests/ip_allocator.rs renamed to crates/api-db/src/machine_interface/ip_allocator.rs

Lines changed: 23 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -19,29 +19,33 @@ use std::str::FromStr;
1919

2020
use mac_address::MacAddress;
2121
use model::address_selection_strategy::AddressSelectionStrategy;
22+
use model::dns::{Domain, NewDomain};
2223
use model::network_prefix::NewNetworkPrefix;
2324
use model::network_segment::{
2425
AllocationStrategy, NetworkSegmentControllerState, NetworkSegmentType, NewNetworkSegment,
2526
};
2627

27-
use crate::tests::common::api_fixtures::{
28-
TestEnvOverrides, create_test_env, create_test_env_with_overrides,
29-
};
28+
use crate as db;
29+
use crate::test_support::network_segment::admin_segment;
30+
31+
async fn init_dwrt1_domain(txn: &mut sqlx::PgTransaction<'_>) -> db::DatabaseResult<Domain> {
32+
db::dns::domain::persist(NewDomain::new("dwrt1.com"), txn.as_mut()).await
33+
}
3034

3135
/// Test that machine_interface::create allocates the correct IPv4 address
3236
/// from the admin segment (192.0.2.0/24 with num_reserved=3, gateway=.1).
3337
#[crate::sqlx_test]
3438
async fn test_machine_interface_create_with_ipv4_prefix(
3539
pool: sqlx::PgPool,
3640
) -> Result<(), Box<dyn std::error::Error>> {
37-
let env = create_test_env(pool).await;
38-
let mut txn = env.pool.begin().await?;
39-
40-
let network_segment = db::network_segment::admin(&mut txn)
41-
.await?
42-
.into_iter()
43-
.next()
44-
.unwrap();
41+
let mut txn = pool.begin().await?;
42+
43+
let network_segment = db::network_segment::persist(
44+
admin_segment("ADMIN_TEST", "192.0.2.0/24", "192.0.2.1", 3),
45+
&mut txn,
46+
NetworkSegmentControllerState::Ready,
47+
)
48+
.await?;
4549
let network_prefix = network_segment
4650
.prefixes
4751
.first()
@@ -111,36 +115,17 @@ async fn test_machine_interface_create_with_ipv4_prefix(
111115
async fn test_machine_interface_create_falls_through_admin_segments(
112116
pool: sqlx::PgPool,
113117
) -> Result<(), Box<dyn std::error::Error>> {
114-
let env = create_test_env_with_overrides(pool, TestEnvOverrides::no_network_segments()).await;
115-
let mut txn = env.pool.begin().await?;
116-
117-
let admin_segment = |name: &str, prefix: &str, gateway: &str| NewNetworkSegment {
118-
name: name.to_string(),
119-
subdomain_id: None,
120-
vpc_id: None,
121-
mtu: 1500,
122-
prefixes: vec![NewNetworkPrefix {
123-
prefix: prefix.parse().unwrap(),
124-
gateway: Some(gateway.parse().unwrap()),
125-
num_reserved: 2,
126-
}],
127-
vlan_id: None,
128-
vni: None,
129-
segment_type: NetworkSegmentType::Admin,
130-
id: uuid::Uuid::new_v4().into(),
131-
can_stretch: None,
132-
allocation_strategy: AllocationStrategy::Dynamic,
133-
};
118+
let mut txn = pool.begin().await?;
134119

135120
// Create two tiny admin segments with one allocatable address each.
136121
let first_segment = db::network_segment::persist(
137-
admin_segment("ADMIN_TINY_1", "192.0.20.0/30", "192.0.20.1"),
122+
admin_segment("ADMIN_TINY_1", "192.0.20.0/30", "192.0.20.1", 2),
138123
&mut txn,
139124
NetworkSegmentControllerState::Ready,
140125
)
141126
.await?;
142127
let second_segment = db::network_segment::persist(
143-
admin_segment("ADMIN_TINY_2", "192.0.21.0/30", "192.0.21.1"),
128+
admin_segment("ADMIN_TINY_2", "192.0.21.0/30", "192.0.21.1", 2),
144129
&mut txn,
145130
NetworkSegmentControllerState::Ready,
146131
)
@@ -178,7 +163,7 @@ async fn test_machine_interface_create_falls_through_admin_segments(
178163
txn.commit().await?;
179164

180165
// Re-read the second interface to verify the persisted segment and address.
181-
let mut txn = env.pool.begin().await?;
166+
let mut txn = pool.begin().await?;
182167
let persisted_interface =
183168
db::machine_interface::find_one(txn.as_mut(), second_interface_id).await?;
184169
assert_eq!(persisted_interface.segment_id, second_segment.id);
@@ -195,14 +180,8 @@ async fn test_machine_interface_create_falls_through_admin_segments(
195180
async fn test_machine_interface_create_with_ipv6_prefix(
196181
pool: sqlx::PgPool,
197182
) -> Result<(), Box<dyn std::error::Error>> {
198-
let env = create_test_env(pool).await;
199-
let mut txn = env.pool.begin().await?;
200-
201-
let domain = db::dns::domain::find_by_name(txn.as_mut(), "dwrt1.com")
202-
.await?
203-
.into_iter()
204-
.next()
205-
.unwrap();
183+
let mut txn = pool.begin().await?;
184+
let domain = init_dwrt1_domain(&mut txn).await?;
206185

207186
// Create an underlay segment with only an IPv6 prefix
208187
let new_ns = NewNetworkSegment {
@@ -278,14 +257,8 @@ async fn test_machine_interface_create_with_ipv6_prefix(
278257
async fn test_machine_interface_create_dual_stack(
279258
pool: sqlx::PgPool,
280259
) -> Result<(), Box<dyn std::error::Error>> {
281-
let env = create_test_env(pool).await;
282-
let mut txn = env.pool.begin().await?;
283-
284-
let domain = db::dns::domain::find_by_name(txn.as_mut(), "dwrt1.com")
285-
.await?
286-
.into_iter()
287-
.next()
288-
.unwrap();
260+
let mut txn = pool.begin().await?;
261+
let domain = init_dwrt1_domain(&mut txn).await?;
289262

290263
let new_ns = NewNetworkSegment {
291264
name: "DUAL-STACK-TEST".to_string(),

crates/api-core/src/tests/prevent_duplicate_mac_addresses.rs renamed to crates/api-db/src/machine_interface/test_duplicate_mac.rs

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -14,49 +14,56 @@
1414
* See the License for the specific language governing permissions and
1515
* limitations under the License.
1616
*/
17-
use db::{self, ObjectColumnFilter, network_segment};
17+
18+
use std::str::FromStr;
19+
20+
use carbide_uuid::machine::{MachineId, MachineIdSource, MachineType};
21+
use mac_address::MacAddress;
1822
use model::address_selection_strategy::AddressSelectionStrategy;
19-
use model::machine::machine_id::from_hardware_info;
23+
use model::network_segment::NetworkSegmentControllerState;
2024

25+
use crate as db;
2126
use crate::DatabaseError;
22-
use crate::tests::common::api_fixtures::create_test_env;
27+
use crate::test_support::network_segment::admin_segment;
28+
29+
fn test_machine_id() -> MachineId {
30+
MachineId::new(
31+
MachineIdSource::ProductBoardChassisSerial,
32+
[0x42; 32],
33+
MachineType::Dpu,
34+
)
35+
}
2336

2437
#[crate::sqlx_test]
2538
async fn prevent_duplicate_mac_addresses(
2639
pool: sqlx::PgPool,
2740
) -> Result<(), Box<dyn std::error::Error>> {
28-
let env = create_test_env(pool).await;
29-
let host_config = env.managed_host_config();
30-
let dpu = host_config.get_and_assert_single_dpu();
31-
32-
let mut txn = env.pool.begin().await?;
33-
34-
let network_segment = db::network_segment::find_by(
35-
txn.as_mut(),
36-
ObjectColumnFilter::One(network_segment::IdColumn, env.admin_segment_ref()),
37-
model::network_segment::NetworkSegmentSearchConfig::default(),
41+
let mut txn = pool.begin().await?;
42+
let network_segment = db::network_segment::persist(
43+
admin_segment("ADMIN_TEST", "192.0.2.0/24", "192.0.2.1", 3),
44+
&mut txn,
45+
NetworkSegmentControllerState::Ready,
3846
)
39-
.await?
40-
.pop()
41-
.unwrap();
47+
.await?;
48+
let mac_address = MacAddress::from_str("52:54:00:12:34:56").unwrap();
4249

4350
let new_interface = db::machine_interface::create(
4451
&mut txn,
4552
std::slice::from_ref(&network_segment),
46-
&dpu.oob_mac_address,
53+
&mac_address,
4754
true,
4855
AddressSelectionStrategy::NextAvailableIp,
4956
None,
5057
)
5158
.await?;
5259

53-
let machine_id = from_hardware_info(&dpu.into()).unwrap();
60+
let machine_id = test_machine_id();
5461
db::machine::get_or_create(&mut txn, None, &machine_id, &new_interface).await?;
5562

5663
let duplicate_interface = db::machine_interface::create(
5764
&mut txn,
5865
std::slice::from_ref(&network_segment),
59-
&dpu.oob_mac_address,
66+
&mac_address,
6067
true,
6168
AddressSelectionStrategy::NextAvailableIp,
6269
None,

crates/api-db/src/machine_interface_address.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ use sqlx::{FromRow, PgConnection};
2727
use super::DatabaseError;
2828
use crate::db_read::DbReader;
2929

30+
#[cfg(test)]
31+
mod test_find_by_address;
32+
3033
/// Returned by allocation paths with `AddressSelectionStrategy::StaticAddress`
3134
/// when the target IP is already held by some other interface.
3235
#[derive(thiserror::Error, Debug)]

crates/api-core/src/tests/machine_interface_addresses.rs renamed to crates/api-db/src/machine_interface_address/test_find_by_address.rs

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,26 +21,25 @@ use std::str::FromStr;
2121
use ipnetwork::IpNetwork;
2222
use mac_address::MacAddress;
2323
use model::address_selection_strategy::AddressSelectionStrategy;
24+
use model::dns::{Domain, NewDomain};
2425
use model::network_prefix::NewNetworkPrefix;
2526
use model::network_segment::{
2627
NetworkSegmentControllerState, NetworkSegmentType, NewNetworkSegment,
2728
};
2829

29-
use crate::tests::common::api_fixtures::create_test_env;
30+
use crate as db;
31+
32+
async fn init_dwrt1_domain(txn: &mut sqlx::PgTransaction<'_>) -> db::DatabaseResult<Domain> {
33+
db::dns::domain::persist(NewDomain::new("dwrt1.com"), txn.as_mut()).await
34+
}
3035

3136
#[crate::sqlx_test]
3237
async fn find_by_address_bmc(pool: sqlx::PgPool) -> Result<(), Box<dyn std::error::Error>> {
33-
let env = create_test_env(pool).await;
34-
let mut txn = env.pool.begin().await?;
35-
let domain = db::dns::domain::find_by_name(txn.as_mut(), "dwrt1.com")
36-
.await?
37-
.into_iter()
38-
.next()
39-
.unwrap();
38+
let mut txn = pool.begin().await?;
39+
let domain = init_dwrt1_domain(&mut txn).await?;
4040

4141
let new_ns = NewNetworkSegment {
4242
name: "PDX01-M01-H14-IPMITOR-01".to_string(),
43-
// domain id from tests/fixtures/create_domain.sql
4443
subdomain_id: Some(domain.id),
4544
vpc_id: None,
4645
mtu: 1490,

crates/api-db/src/power_shelf.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ use crate::{
3333
ColumnInfo, DatabaseError, DatabaseResult, FilterableQueryBuilder, ObjectColumnFilter,
3434
};
3535

36+
#[cfg(test)]
37+
mod test_metadata;
38+
3639
#[derive(Debug, Clone, Default)]
3740
pub struct PowerShelfSearchConfig {
3841
// pub include_history: bool, // unused

0 commit comments

Comments
 (0)