Skip to content

Commit db2bca0

Browse files
test(plugins/cgroups/oar): Updates to add 80% test code coverage for CGroups/oar plugin
1 parent 47f3d25 commit db2bca0

5 files changed

Lines changed: 225 additions & 102 deletions

File tree

plugins/cgroups/oar/src/config.rs

Lines changed: 0 additions & 36 deletions
This file was deleted.

plugins/cgroups/oar/src/job_tracker.rs

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
use std::sync::{Arc, Mutex};
2-
3-
use anyhow::Context;
1+
use anyhow::{Context, Result};
42
use rustc_hash::FxHashSet;
3+
use std::sync::{Arc, Mutex};
4+
use util_cgroups::Cgroup;
55

66
use crate::{
7+
OarVersion,
78
attr::{JOB_REGEX_OAR2, JOB_REGEX_OAR3, find_jobid_in_attrs},
8-
config::OarVersion,
99
};
1010
use util_cgroups_plugins::{cgroup_events::CgroupRemovalCallback, regex::RegexAttributesExtrator};
1111

@@ -62,7 +62,7 @@ impl JobTracker {
6262
}
6363

6464
impl JobCleaner {
65-
pub fn with_version(tracker: &JobTracker, version: OarVersion) -> anyhow::Result<Self> {
65+
pub fn with_version(tracker: &JobTracker, version: OarVersion) -> Result<Self> {
6666
let attr_extractor = match version {
6767
OarVersion::Oar2 => RegexAttributesExtrator::new(JOB_REGEX_OAR2),
6868
OarVersion::Oar3 => RegexAttributesExtrator::new(JOB_REGEX_OAR3),
@@ -75,7 +75,7 @@ impl JobCleaner {
7575
}
7676

7777
impl CgroupRemovalCallback for JobCleaner {
78-
fn on_cgroups_removed(&mut self, cgroups: Vec<util_cgroups::Cgroup>) -> anyhow::Result<()> {
78+
fn on_cgroups_removed(&mut self, cgroups: Vec<Cgroup>) -> Result<()> {
7979
let mut job_ids = Vec::new();
8080
for cgroup in cgroups {
8181
// If the regex matches, the cgroup corresponds to a job, and it should have a job id.
@@ -103,4 +103,23 @@ mod tests {
103103
// this compiles only if JobTracker is Send and Sync
104104
f::<JobTracker>();
105105
}
106+
107+
#[test]
108+
fn test_job_single_handle() {
109+
let mut tracker = JobTracker::new();
110+
tracker.add(10);
111+
tracker.remove(10);
112+
}
113+
114+
#[test]
115+
fn test_job_multiple_handle() {
116+
let mut tracker = JobTracker::new();
117+
tracker.add_multiple(vec![10, 20, 30].into_iter());
118+
// Remove nothing
119+
tracker.remove_multiple(vec![].into_iter());
120+
assert_eq!(tracker.known_jobs_sorted(), vec![10, 20, 30]);
121+
// Remove everything
122+
tracker.remove_multiple(vec![10, 20, 30].into_iter());
123+
assert!(tracker.known_jobs_sorted().is_empty());
124+
}
106125
}

plugins/cgroups/oar/src/lib.rs

Lines changed: 61 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ use alumet::plugin::{
33
rust::{AlumetPlugin, deserialize_config, serialize_config},
44
};
55
use anyhow::Context;
6+
use serde::{Deserialize, Serialize};
7+
use std::time::Duration;
68

79
use crate::{
810
attr::OarJobTagger,
@@ -26,15 +28,15 @@ mod transform;
2628
///
2729
/// Supports OAR2 and OAR3, on cgroup v1 or cgroup v2.
2830
pub struct OarPlugin {
29-
config: Option<config::Config>,
31+
config: Option<Config>,
3032
/// Intermediary state for startup.
3133
starting_state: Option<StartingState>,
3234
/// The reactor that is running in the background. Dropping it will stop it.
3335
reactor: Option<CgroupReactor>,
3436
}
3537

3638
impl OarPlugin {
37-
pub fn new(config: config::Config) -> Self {
39+
pub fn new(config: Config) -> Self {
3840
Self {
3941
config: Some(config),
4042
reactor: None,
@@ -53,12 +55,12 @@ impl AlumetPlugin for OarPlugin {
5355
}
5456

5557
fn init(config: ConfigTable) -> anyhow::Result<Box<Self>> {
56-
let config: config::Config = deserialize_config(config)?;
58+
let config: Config = deserialize_config(config)?;
5759
Ok(Box::new(Self::new(config)))
5860
}
5961

6062
fn default_config() -> anyhow::Result<Option<ConfigTable>> {
61-
let config = serialize_config(config::Config::default())?;
63+
let config = serialize_config(Config::default())?;
6264
Ok(Some(config))
6365
}
6466

@@ -119,11 +121,65 @@ impl AlumetPlugin for OarPlugin {
119121
}
120122
}
121123

122-
mod config;
124+
#[derive(Debug, Serialize, Deserialize)]
125+
pub struct Config {
126+
pub(crate) oar_version: OarVersion,
127+
#[serde(with = "humantime_serde")]
128+
pub(crate) poll_interval: Duration,
129+
pub(crate) jobs_only: bool,
130+
/// If `true`, adds attributes like `job_id` to the measurements produced by other plugins.
131+
/// The default value is `false`.
132+
///
133+
/// The measurements must have the `cgroup` resource consumer, and **cgroup v2** must be used on the node.
134+
#[serde(default)]
135+
pub annotate_foreign_measurements: bool,
136+
}
137+
138+
impl Default for Config {
139+
#[cfg_attr(tarpaulin, ignore)]
140+
fn default() -> Self {
141+
Self {
142+
oar_version: OarVersion::Oar3,
143+
poll_interval: Duration::from_secs(1),
144+
jobs_only: true,
145+
annotate_foreign_measurements: false,
146+
}
147+
}
148+
}
149+
150+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
151+
#[serde(rename_all = "lowercase")]
152+
pub enum OarVersion {
153+
Oar2,
154+
Oar3,
155+
}
123156

124157
struct StartingState {
125158
metrics: Metrics,
126159
reactor_config: ReactorConfig,
127160
source_setup: source::JobSourceSetup,
128161
job_cleaner: JobCleaner,
129162
}
163+
164+
#[cfg(test)]
165+
mod tests {
166+
use super::*;
167+
168+
#[test]
169+
fn test_default_config() {
170+
let config_table = OarPlugin::default_config()
171+
.expect("default_config() should not fail")
172+
.expect("default_config() should return Some");
173+
174+
let config: Config = deserialize_config(config_table).expect("should deserialize config");
175+
let default = Config::default();
176+
177+
assert_eq!(config.oar_version, default.oar_version);
178+
assert_eq!(config.poll_interval, default.poll_interval);
179+
assert_eq!(config.jobs_only, default.jobs_only);
180+
assert_eq!(
181+
config.annotate_foreign_measurements,
182+
default.annotate_foreign_measurements
183+
);
184+
}
185+
}

0 commit comments

Comments
 (0)