Coverage Report

Created: 2026-11-13 23:29

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/build/source/nativelink-scheduler/src/mock_scheduler.rs
Line
Count
Source
1
// Copyright 2024 Trace Machina, Inc. All rights reserved.
2
//
3
// Licensed under the Functional Source License, Version 1.1, Apache 2.0 Future License (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//    See LICENSE file for details
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
15
use std::sync::Arc;
16
17
use async_trait::async_trait;
18
use nativelink_error::Error;
19
use nativelink_metric::{MetricsComponent, RootMetricsComponent};
20
use nativelink_util::action_messages::{ActionInfo, OperationId};
21
use nativelink_util::operation_state_manager::{
22
    ActionStateResult, ActionStateResultStream, ClientStateManager, OperationFilter,
23
};
24
use tokio::sync::{Mutex, mpsc};
25
use tonic::Code;
26
27
use crate::known_platform_property_provider::KnownPlatformPropertyProvider;
28
29
#[allow(
30
    clippy::large_enum_variant,
31
    reason = "Testing, so this doesn't really matter. Doesn't trigger on nightly"
32
)]
33
#[allow(dead_code, reason = "https://github.com/rust-lang/rust/issues/46379")]
34
enum ActionSchedulerCalls {
35
    GetGetKnownProperties(String),
36
    AddAction((OperationId, ActionInfo)),
37
    FilterOperations(OperationFilter),
38
}
39
40
#[allow(dead_code, reason = "https://github.com/rust-lang/rust/issues/46379")]
41
enum ActionSchedulerReturns {
42
    GetGetKnownProperties(Result<Vec<String>, Error>),
43
    AddAction(Result<Box<dyn ActionStateResult>, Error>),
44
    FilterOperations(Result<ActionStateResultStream<'static>, Error>),
45
}
46
47
#[derive(MetricsComponent, Debug)]
48
pub struct MockActionScheduler {
49
    rx_call: Mutex<mpsc::UnboundedReceiver<ActionSchedulerCalls>>,
50
    tx_call: mpsc::UnboundedSender<ActionSchedulerCalls>,
51
52
    rx_resp: Mutex<mpsc::UnboundedReceiver<ActionSchedulerReturns>>,
53
    tx_resp: mpsc::UnboundedSender<ActionSchedulerReturns>,
54
}
55
56
impl Default for MockActionScheduler {
57
0
    fn default() -> Self {
58
0
        Self::new()
59
0
    }
60
}
61
62
impl MockActionScheduler {
63
59
    pub fn new() -> Self {
64
59
        let (tx_call, rx_call) = mpsc::unbounded_channel();
65
59
        let (tx_resp, rx_resp) = mpsc::unbounded_channel();
66
59
        Self {
67
59
            rx_call: Mutex::new(rx_call),
68
59
            tx_call,
69
59
            rx_resp: Mutex::new(rx_resp),
70
59
            tx_resp,
71
59
        }
72
59
    }
73
74
    #[allow(dead_code, reason = "https://github.com/rust-lang/rust/issues/46379")]
75
4
    pub async fn expect_get_known_properties(&self, result: Result<Vec<String>, Error>) -> String {
76
4
        let mut rx_call_lock = self.rx_call.lock().await;
77
4
        let ActionSchedulerCalls::GetGetKnownProperties(req) = rx_call_lock
78
4
            .recv()
79
4
            .await
80
4
            .expect("Could not receive msg in mpsc")
81
        else {
82
0
            panic!("Got incorrect call waiting for get_known_properties")
83
        };
84
4
        self.tx_resp
85
4
            .send(ActionSchedulerReturns::GetGetKnownProperties(result))
86
4
            .map_err(|err| 
{0
87
0
                Error::from_std_err(Code::InvalidArgument, &err)
88
0
                    .append("Could not send request to mpsc")
89
0
            })
90
4
            .unwrap();
91
4
        req
92
4
    }
93
94
    #[allow(dead_code, reason = "https://github.com/rust-lang/rust/issues/46379")]
95
0
    pub async fn expect_add_action(
96
0
        &self,
97
0
        result: Result<Box<dyn ActionStateResult>, Error>,
98
93
    ) -> (OperationId, ActionInfo) {
99
93
        let mut rx_call_lock = self.rx_call.lock().await;
100
93
        let ActionSchedulerCalls::AddAction(req) = rx_call_lock
101
93
            .recv()
102
93
            .await
103
93
            .expect("Could not receive msg in mpsc")
104
        else {
105
0
            panic!("Got incorrect call waiting for get_known_properties")
106
        };
107
93
        self.tx_resp
108
93
            .send(ActionSchedulerReturns::AddAction(result))
109
93
            .map_err(|err| 
{0
110
0
                Error::from_std_err(Code::InvalidArgument, &err)
111
0
                    .append("Could not send request to mpsc")
112
0
            })
113
93
            .unwrap();
114
93
        req
115
93
    }
116
117
    #[allow(dead_code, reason = "https://github.com/rust-lang/rust/issues/46379")]
118
8
    pub async fn expect_filter_operations(
119
8
        &self,
120
8
        result: Result<ActionStateResultStream<'static>, Error>,
121
8
    ) -> OperationFilter {
122
8
        let mut rx_call_lock = self.rx_call.lock().await;
123
8
        let ActionSchedulerCalls::FilterOperations(req) = rx_call_lock
124
8
            .recv()
125
8
            .await
126
8
            .expect("Could not receive msg in mpsc")
127
        else {
128
0
            panic!("Got incorrect call waiting for find_by_client_operation_id")
129
        };
130
8
        self.tx_resp
131
8
            .send(ActionSchedulerReturns::FilterOperations(result))
132
8
            .map_err(|err| 
{0
133
0
                Error::from_std_err(Code::InvalidArgument, &err)
134
0
                    .append("Could not send request to mpsc")
135
0
            })
136
8
            .unwrap();
137
8
        req
138
8
    }
139
}
140
141
#[async_trait]
142
impl KnownPlatformPropertyProvider for MockActionScheduler {
143
4
    async fn get_known_properties(&self, instance_name: &str) -> Result<Vec<String>, Error> {
144
        self.tx_call
145
            .send(ActionSchedulerCalls::GetGetKnownProperties(
146
                instance_name.to_string(),
147
            ))
148
            .expect("Could not send request to mpsc");
149
        let mut rx_resp_lock = self.rx_resp.lock().await;
150
        match rx_resp_lock
151
            .recv()
152
            .await
153
            .expect("Could not receive msg in mpsc")
154
        {
155
            ActionSchedulerReturns::GetGetKnownProperties(result) => result,
156
            _ => panic!("Expected get_known_properties return value"),
157
        }
158
4
    }
159
}
160
161
#[async_trait]
162
impl ClientStateManager for MockActionScheduler {
163
    async fn add_action(
164
        &self,
165
        client_operation_id: OperationId,
166
        action_info: Arc<ActionInfo>,
167
93
    ) -> Result<Box<dyn ActionStateResult>, Error> {
168
        self.tx_call
169
            .send(ActionSchedulerCalls::AddAction((
170
                client_operation_id,
171
                action_info.as_ref().clone(),
172
            )))
173
            .expect("Could not send request to mpsc");
174
        let mut rx_resp_lock = self.rx_resp.lock().await;
175
        match rx_resp_lock
176
            .recv()
177
            .await
178
            .expect("Could not receive msg in mpsc")
179
        {
180
            ActionSchedulerReturns::AddAction(result) => result,
181
            _ => panic!("Expected add_action return value"),
182
        }
183
93
    }
184
185
    async fn filter_operations<'a>(
186
        &'a self,
187
        filter: OperationFilter,
188
8
    ) -> Result<ActionStateResultStream<'a>, Error> {
189
        self.tx_call
190
            .send(ActionSchedulerCalls::FilterOperations(filter))
191
            .expect("Could not send request to mpsc");
192
        let mut rx_resp_lock = self.rx_resp.lock().await;
193
        match rx_resp_lock
194
            .recv()
195
            .await
196
            .expect("Could not receive msg in mpsc")
197
        {
198
            ActionSchedulerReturns::FilterOperations(result) => result,
199
            _ => panic!("Expected find_by_client_operation_id return value"),
200
        }
201
8
    }
202
}
203
204
impl RootMetricsComponent for MockActionScheduler {}