• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

geo-engine / geoengine / 12907583488

22 Jan 2025 11:50AM UTC coverage: 90.062% (-0.6%) from 90.64%
12907583488

Pull #1008

github

web-flow
Merge 921681cfb into de81b44f7
Pull Request #1008: user ctx in ge_test

4564 of 4830 new or added lines in 65 files covered. (94.49%)

786 existing lines in 19 files now uncovered.

127252 of 141294 relevant lines covered (90.06%)

56970.82 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

69.6
/operators/src/engine/execution_context.rs
1
use super::query::QueryAbortRegistration;
2
use super::{
3
    CreateSpan, InitializedPlotOperator, InitializedRasterOperator, InitializedVectorOperator,
4
    MockQueryContext,
5
};
6
use crate::engine::{
7
    ChunkByteSize, RasterResultDescriptor, ResultDescriptor, VectorResultDescriptor,
8
};
9
use crate::error::Error;
10
use crate::meta::wrapper::InitializedOperatorWrapper;
11
use crate::mock::MockDatasetDataSourceLoadingInfo;
12
use crate::source::{GdalLoadingInfo, OgrSourceDataset};
13
use crate::util::{create_rayon_thread_pool, Result};
14
use async_trait::async_trait;
15
use geoengine_datatypes::dataset::{DataId, NamedData};
16
use geoengine_datatypes::machine_learning::{MlModelMetadata, MlModelName};
17
use geoengine_datatypes::primitives::{RasterQueryRectangle, VectorQueryRectangle};
18
use geoengine_datatypes::raster::TilingSpecification;
19
use geoengine_datatypes::util::test::TestDefault;
20
use rayon::ThreadPool;
21
use serde::{Deserialize, Serialize};
22
use std::any::Any;
23
use std::collections::HashMap;
24
use std::fmt::Debug;
25
use std::marker::PhantomData;
26
use std::sync::Arc;
27

28
/// A context that provides certain utility access during operator initialization
29
#[async_trait::async_trait]
30
pub trait ExecutionContext: Send
31
    + Sync
32
    + MetaDataProvider<MockDatasetDataSourceLoadingInfo, VectorResultDescriptor, VectorQueryRectangle>
33
    + MetaDataProvider<OgrSourceDataset, VectorResultDescriptor, VectorQueryRectangle>
34
    + MetaDataProvider<GdalLoadingInfo, RasterResultDescriptor, RasterQueryRectangle>
35
{
36
    fn thread_pool(&self) -> &Arc<ThreadPool>;
37
    fn tiling_specification(&self) -> TilingSpecification;
38

39
    fn wrap_initialized_raster_operator(
40
        &self,
41
        op: Box<dyn InitializedRasterOperator>,
42
        span: CreateSpan,
43
    ) -> Box<dyn InitializedRasterOperator>;
44

45
    fn wrap_initialized_vector_operator(
46
        &self,
47
        op: Box<dyn InitializedVectorOperator>,
48
        span: CreateSpan,
49
    ) -> Box<dyn InitializedVectorOperator>;
50

51
    fn wrap_initialized_plot_operator(
52
        &self,
53
        op: Box<dyn InitializedPlotOperator>,
54
        span: CreateSpan,
55
    ) -> Box<dyn InitializedPlotOperator>;
56

57
    async fn resolve_named_data(&self, data: &NamedData) -> Result<DataId>;
58

59
    async fn ml_model_metadata(&self, name: &MlModelName) -> Result<MlModelMetadata>;
60
}
61

62
#[async_trait]
63
pub trait MetaDataProvider<L, R, Q>
64
where
65
    R: ResultDescriptor,
66
{
67
    async fn meta_data(&self, id: &DataId) -> Result<Box<dyn MetaData<L, R, Q>>>;
68
}
69

70
#[async_trait]
71
pub trait MetaData<L, R, Q>: Debug + Send + Sync
72
where
73
    R: ResultDescriptor,
74
{
75
    async fn loading_info(&self, query: Q) -> Result<L>;
76
    async fn result_descriptor(&self) -> Result<R>;
77

78
    fn box_clone(&self) -> Box<dyn MetaData<L, R, Q>>;
79
}
80

81
impl<L, R, Q> Clone for Box<dyn MetaData<L, R, Q>>
82
where
83
    R: ResultDescriptor,
84
{
85
    fn clone(&self) -> Box<dyn MetaData<L, R, Q>> {
130✔
86
        self.box_clone()
130✔
87
    }
130✔
88
}
89

90
pub struct MockExecutionContext {
91
    pub thread_pool: Arc<ThreadPool>,
92
    pub meta_data: HashMap<DataId, Box<dyn Any + Send + Sync>>,
93
    pub named_data: HashMap<NamedData, DataId>,
94
    pub ml_models: HashMap<MlModelName, MlModelMetadata>,
95
    pub tiling_specification: TilingSpecification,
96
}
97

98
impl TestDefault for MockExecutionContext {
99
    fn test_default() -> Self {
144✔
100
        Self {
144✔
101
            thread_pool: create_rayon_thread_pool(0),
144✔
102
            meta_data: HashMap::default(),
144✔
103
            named_data: HashMap::default(),
144✔
104
            ml_models: HashMap::default(),
144✔
105
            tiling_specification: TilingSpecification::test_default(),
144✔
106
        }
144✔
107
    }
144✔
108
}
109

110
impl MockExecutionContext {
111
    pub fn new_with_tiling_spec(tiling_specification: TilingSpecification) -> Self {
130✔
112
        Self {
130✔
113
            thread_pool: create_rayon_thread_pool(0),
130✔
114
            meta_data: HashMap::default(),
130✔
115
            named_data: HashMap::default(),
130✔
116
            ml_models: HashMap::default(),
130✔
117
            tiling_specification,
130✔
118
        }
130✔
119
    }
130✔
120

121
    pub fn new_with_tiling_spec_and_thread_count(
×
122
        tiling_specification: TilingSpecification,
×
123
        num_threads: usize,
×
124
    ) -> Self {
×
125
        Self {
×
126
            thread_pool: create_rayon_thread_pool(num_threads),
×
127
            meta_data: HashMap::default(),
×
128
            named_data: HashMap::default(),
×
129
            ml_models: HashMap::default(),
×
130
            tiling_specification,
×
131
        }
×
132
    }
×
133

134
    pub fn add_meta_data<L, R, Q>(
49✔
135
        &mut self,
49✔
136
        data: DataId,
49✔
137
        named_data: NamedData,
49✔
138
        meta_data: Box<dyn MetaData<L, R, Q>>,
49✔
139
    ) where
49✔
140
        L: Send + Sync + 'static,
49✔
141
        R: Send + Sync + 'static + ResultDescriptor,
49✔
142
        Q: Send + Sync + 'static,
49✔
143
    {
49✔
144
        self.meta_data.insert(
49✔
145
            data.clone(),
49✔
146
            Box::new(meta_data) as Box<dyn Any + Send + Sync>,
49✔
147
        );
49✔
148

49✔
149
        self.named_data.insert(named_data, data);
49✔
150
    }
49✔
151

152
    pub fn delete_meta_data(&mut self, named_data: &NamedData) {
2✔
153
        let data = self.named_data.remove(named_data);
2✔
154
        if let Some(data) = data {
2✔
155
            self.meta_data.remove(&data);
2✔
156
        }
2✔
157
    }
2✔
158

159
    pub fn mock_query_context(&self, chunk_byte_size: ChunkByteSize) -> MockQueryContext {
3✔
160
        let (abort_registration, abort_trigger) = QueryAbortRegistration::new();
3✔
161
        MockQueryContext {
3✔
162
            chunk_byte_size,
3✔
163
            thread_pool: self.thread_pool.clone(),
3✔
164
            cache: None,
3✔
165
            quota_checker: None,
3✔
166
            quota_tracking: None,
3✔
167
            abort_registration,
3✔
168
            abort_trigger: Some(abort_trigger),
3✔
169
        }
3✔
170
    }
3✔
171
}
172

173
#[async_trait::async_trait]
174
impl ExecutionContext for MockExecutionContext {
175
    fn thread_pool(&self) -> &Arc<ThreadPool> {
×
176
        &self.thread_pool
×
177
    }
×
178

179
    fn tiling_specification(&self) -> TilingSpecification {
244✔
180
        self.tiling_specification
244✔
181
    }
244✔
182

183
    fn wrap_initialized_raster_operator(
316✔
184
        &self,
316✔
185
        op: Box<dyn InitializedRasterOperator>,
316✔
186
        _span: CreateSpan,
316✔
187
    ) -> Box<dyn InitializedRasterOperator> {
316✔
188
        op
316✔
189
    }
316✔
190

191
    fn wrap_initialized_vector_operator(
168✔
192
        &self,
168✔
193
        op: Box<dyn InitializedVectorOperator>,
168✔
194
        _span: CreateSpan,
168✔
195
    ) -> Box<dyn InitializedVectorOperator> {
168✔
196
        op
168✔
197
    }
168✔
198

199
    fn wrap_initialized_plot_operator(
53✔
200
        &self,
53✔
201
        op: Box<dyn InitializedPlotOperator>,
53✔
202
        _span: CreateSpan,
53✔
203
    ) -> Box<dyn InitializedPlotOperator> {
53✔
204
        op
53✔
205
    }
53✔
206

207
    async fn resolve_named_data(&self, data: &NamedData) -> Result<DataId> {
53✔
208
        self.named_data
53✔
209
            .get(data)
53✔
210
            .cloned()
53✔
211
            .ok_or_else(|| Error::UnknownDatasetName { name: data.clone() })
53✔
212
    }
106✔
213

214
    async fn ml_model_metadata(&self, name: &MlModelName) -> Result<MlModelMetadata> {
2✔
215
        self.ml_models
2✔
216
            .get(name)
2✔
217
            .cloned()
2✔
218
            .ok_or_else(|| Error::UnknownMlModelName { name: name.clone() })
2✔
219
    }
4✔
220
}
221

222
#[async_trait]
223
impl<L, R, Q> MetaDataProvider<L, R, Q> for MockExecutionContext
224
where
225
    L: 'static,
226
    R: 'static + ResultDescriptor,
227
    Q: 'static,
228
{
229
    async fn meta_data(&self, id: &DataId) -> Result<Box<dyn MetaData<L, R, Q>>> {
53✔
230
        let meta_data = self
53✔
231
            .meta_data
53✔
232
            .get(id)
53✔
233
            .ok_or(Error::UnknownDataId)?
53✔
234
            .downcast_ref::<Box<dyn MetaData<L, R, Q>>>()
53✔
235
            .ok_or(Error::InvalidMetaDataType)?;
53✔
236

237
        Ok(meta_data.clone())
53✔
238
    }
106✔
239
}
240

241
#[derive(PartialEq, Eq, Debug, Clone, Serialize, Deserialize)]
242
#[serde(rename_all = "camelCase")]
243
pub struct StaticMetaData<L, R, Q>
244
where
245
    L: Debug + Clone + Send + Sync + 'static,
246
    R: Debug + Send + Sync + 'static + ResultDescriptor,
247
    Q: Debug + Clone + Send + Sync + 'static,
248
{
249
    pub loading_info: L,
250
    pub result_descriptor: R,
251
    #[serde(skip)]
252
    pub phantom: PhantomData<Q>,
253
}
254

255
#[async_trait]
256
impl<L, R, Q> MetaData<L, R, Q> for StaticMetaData<L, R, Q>
257
where
258
    L: Debug + Clone + Send + Sync + 'static,
259
    R: Debug + Send + Sync + 'static + ResultDescriptor,
260
    Q: Debug + Clone + Send + Sync + 'static,
261
{
262
    async fn loading_info(&self, _query: Q) -> Result<L> {
59✔
263
        Ok(self.loading_info.clone())
59✔
264
    }
118✔
265

266
    async fn result_descriptor(&self) -> Result<R> {
35✔
267
        Ok(self.result_descriptor.clone())
35✔
268
    }
70✔
269

270
    fn box_clone(&self) -> Box<dyn MetaData<L, R, Q>> {
48✔
271
        Box::new(self.clone())
48✔
272
    }
48✔
273
}
274

275
mod db_types {
276
    use geoengine_datatypes::delegate_from_to_sql;
277
    use postgres_types::{FromSql, ToSql};
278

279
    use super::*;
280

281
    pub type MockMetaData = StaticMetaData<
282
        MockDatasetDataSourceLoadingInfo,
283
        VectorResultDescriptor,
284
        VectorQueryRectangle,
285
    >;
286

287
    #[derive(Debug, ToSql, FromSql)]
435✔
288
    #[postgres(name = "MockMetaData")]
289
    pub struct MockMetaDataDbType {
290
        pub loading_info: MockDatasetDataSourceLoadingInfo,
291
        pub result_descriptor: VectorResultDescriptor,
292
    }
293

294
    impl From<&MockMetaData> for MockMetaDataDbType {
UNCOV
295
        fn from(other: &MockMetaData) -> Self {
×
UNCOV
296
            Self {
×
UNCOV
297
                loading_info: other.loading_info.clone(),
×
UNCOV
298
                result_descriptor: other.result_descriptor.clone(),
×
UNCOV
299
            }
×
UNCOV
300
        }
×
301
    }
302

303
    impl TryFrom<MockMetaDataDbType> for MockMetaData {
304
        type Error = Error;
305

UNCOV
306
        fn try_from(other: MockMetaDataDbType) -> Result<Self, Self::Error> {
×
UNCOV
307
            Ok(Self {
×
UNCOV
308
                loading_info: other.loading_info,
×
UNCOV
309
                result_descriptor: other.result_descriptor,
×
UNCOV
310
                phantom: PhantomData,
×
UNCOV
311
            })
×
UNCOV
312
        }
×
313
    }
314

315
    pub type OgrMetaData =
316
        StaticMetaData<OgrSourceDataset, VectorResultDescriptor, VectorQueryRectangle>;
317

318
    #[derive(Debug, ToSql, FromSql)]
446✔
319
    #[postgres(name = "OgrMetaData")]
320
    pub struct OgrMetaDataDbType {
321
        pub loading_info: OgrSourceDataset,
322
        pub result_descriptor: VectorResultDescriptor,
323
    }
324

325
    impl From<&StaticMetaData<OgrSourceDataset, VectorResultDescriptor, VectorQueryRectangle>>
326
        for OgrMetaDataDbType
327
    {
328
        fn from(other: &OgrMetaData) -> Self {
25✔
329
            Self {
25✔
330
                loading_info: other.loading_info.clone(),
25✔
331
                result_descriptor: other.result_descriptor.clone(),
25✔
332
            }
25✔
333
        }
25✔
334
    }
335

336
    impl TryFrom<OgrMetaDataDbType> for OgrMetaData {
337
        type Error = Error;
338

339
        fn try_from(other: OgrMetaDataDbType) -> Result<Self, Self::Error> {
11✔
340
            Ok(Self {
11✔
341
                loading_info: other.loading_info,
11✔
342
                result_descriptor: other.result_descriptor,
11✔
343
                phantom: PhantomData,
11✔
344
            })
11✔
345
        }
11✔
346
    }
347

348
    delegate_from_to_sql!(MockMetaData, MockMetaDataDbType);
349
    delegate_from_to_sql!(OgrMetaData, OgrMetaDataDbType);
350
}
351

352
/// A mock execution context that wraps all operators with a statistics operator.
353
pub struct StatisticsWrappingMockExecutionContext {
354
    pub inner: MockExecutionContext,
355
}
356

357
impl TestDefault for StatisticsWrappingMockExecutionContext {
358
    fn test_default() -> Self {
×
359
        Self {
×
360
            inner: MockExecutionContext::test_default(),
×
361
        }
×
362
    }
×
363
}
364

365
#[async_trait::async_trait]
366
impl ExecutionContext for StatisticsWrappingMockExecutionContext {
367
    fn thread_pool(&self) -> &Arc<ThreadPool> {
×
368
        &self.inner.thread_pool
×
369
    }
×
370

371
    fn tiling_specification(&self) -> TilingSpecification {
×
372
        self.inner.tiling_specification
×
373
    }
×
374

375
    fn wrap_initialized_raster_operator(
×
376
        &self,
×
377
        op: Box<dyn InitializedRasterOperator>,
×
378
        span: CreateSpan,
×
379
    ) -> Box<dyn InitializedRasterOperator> {
×
380
        InitializedOperatorWrapper::new(op, span).boxed()
×
381
    }
×
382

383
    fn wrap_initialized_vector_operator(
×
384
        &self,
×
385
        op: Box<dyn InitializedVectorOperator>,
×
386
        span: CreateSpan,
×
387
    ) -> Box<dyn InitializedVectorOperator> {
×
388
        InitializedOperatorWrapper::new(op, span).boxed()
×
389
    }
×
390

391
    fn wrap_initialized_plot_operator(
×
392
        &self,
×
393
        op: Box<dyn InitializedPlotOperator>,
×
394
        _span: CreateSpan,
×
395
    ) -> Box<dyn InitializedPlotOperator> {
×
396
        op
×
397
    }
×
398

399
    async fn resolve_named_data(&self, data: &NamedData) -> Result<DataId> {
×
400
        self.inner.resolve_named_data(data).await
×
401
    }
×
402

403
    async fn ml_model_metadata(&self, name: &MlModelName) -> Result<MlModelMetadata> {
×
404
        self.inner.ml_model_metadata(name).await
×
405
    }
×
406
}
407

408
#[async_trait]
409
impl<L, R, Q> MetaDataProvider<L, R, Q> for StatisticsWrappingMockExecutionContext
410
where
411
    L: 'static,
412
    R: 'static + ResultDescriptor,
413
    Q: 'static,
414
{
415
    async fn meta_data(&self, id: &DataId) -> Result<Box<dyn MetaData<L, R, Q>>> {
×
416
        self.inner.meta_data(id).await
×
417
    }
×
418
}
419

420
#[cfg(test)]
421
mod tests {
422
    use super::*;
423
    use geoengine_datatypes::collections::VectorDataType;
424
    use geoengine_datatypes::spatial_reference::SpatialReferenceOption;
425

426
    #[tokio::test]
427
    async fn test() {
1✔
428
        let info = StaticMetaData {
1✔
429
            loading_info: 1_i32,
1✔
430
            result_descriptor: VectorResultDescriptor {
1✔
431
                data_type: VectorDataType::Data,
1✔
432
                spatial_reference: SpatialReferenceOption::Unreferenced,
1✔
433
                columns: Default::default(),
1✔
434
                time: None,
1✔
435
                bbox: None,
1✔
436
            },
1✔
437
            phantom: Default::default(),
1✔
438
        };
1✔
439

1✔
440
        let info: Box<dyn MetaData<i32, VectorResultDescriptor, VectorQueryRectangle>> =
1✔
441
            Box::new(info);
1✔
442

1✔
443
        let info2: Box<dyn Any + Send + Sync> = Box::new(info);
1✔
444

1✔
445
        let info3 = info2
1✔
446
            .downcast_ref::<Box<dyn MetaData<i32, VectorResultDescriptor, VectorQueryRectangle>>>()
1✔
447
            .unwrap();
1✔
448

1✔
449
        assert_eq!(
1✔
450
            info3.result_descriptor().await.unwrap(),
1✔
451
            VectorResultDescriptor {
1✔
452
                data_type: VectorDataType::Data,
1✔
453
                spatial_reference: SpatialReferenceOption::Unreferenced,
1✔
454
                columns: Default::default(),
1✔
455
                time: None,
1✔
456
                bbox: None,
1✔
457
            }
1✔
458
        );
1✔
459
    }
1✔
460
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc