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

geo-engine / geoengine / 13027340444

29 Jan 2025 08:29AM UTC coverage: 90.025% (-0.07%) from 90.094%
13027340444

Pull #1011

github

web-flow
Merge f5a017fde into b4abb5d41
Pull Request #1011: update to rust 1.84

46 of 54 new or added lines in 14 files covered. (85.19%)

104 existing lines in 43 files now uncovered.

125594 of 139510 relevant lines covered (90.03%)

57696.78 hits per line

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

98.51
/operators/src/adapters/raster_stacker.rs
1
use crate::util::Result;
2
use futures::future::JoinAll;
3
use futures::stream::{Fuse, FusedStream, Stream};
4
use futures::{ready, Future, StreamExt};
5
use geoengine_datatypes::primitives::{
6
    BandSelection, RasterQueryRectangle, SpatialPartition2D, SpatialResolution, TimeInterval,
7
};
8
use geoengine_datatypes::raster::{
9
    GridIdx2D, GridSize, Pixel, RasterTile2D, TileInformation, TilingStrategy,
10
};
11
use pin_project::pin_project;
12
use std::pin::Pin;
13
use std::task::{Context, Poll};
14

15
use super::Queryable;
16

UNCOV
17
#[pin_project(project = ArrayStateProjection)]
×
18
enum State<T, F>
19
where
20
    T: Pixel,
21
    F: Queryable<T>,
22
    F::Stream: Stream<Item = Result<RasterTile2D<T>>>,
23
    F::Output: Future<Output = Result<F::Stream>>,
24
{
25
    Initial,
26
    AwaitingQuery {
27
        #[pin]
28
        query_futures: JoinAll<F::Output>,
29
    },
30
    ConsumingStreams {
31
        #[pin]
32
        streams: Vec<Fuse<F::Stream>>,
33
        stream_state: StreamState<T>,
34
    },
35

36
    Finished,
37
}
38

39
enum StreamState<T> {
40
    CollectingFirstTiles {
41
        first_tiles: Vec<Option<Result<RasterTile2D<T>>>>,
42
    },
43
    ProducingTimeSlice {
44
        first_tiles: Vec<RasterTile2D<T>>,
45
        time_slice: TimeInterval,
46
        current_stream: usize,
47
        current_band: usize,
48
        current_spatial_tile: usize,
49
    },
50
}
51

52
pub struct RasterStackerSource<Q> {
53
    pub queryable: Q,
54
    pub band_idxs: Vec<u32>,
55
}
56

57
impl<Q> From<(Q, Vec<u32>)> for RasterStackerSource<Q> {
58
    fn from(value: (Q, Vec<u32>)) -> Self {
10✔
59
        debug_assert!(!value.1.is_empty(), "At least one band required");
10✔
60
        Self {
10✔
61
            queryable: value.0,
10✔
62
            band_idxs: value.1,
10✔
63
        }
10✔
64
    }
10✔
65
}
66

67
#[derive(Debug)]
68
pub struct PartialQueryRect {
69
    pub spatial_bounds: SpatialPartition2D,
70
    pub time_interval: TimeInterval,
71
    pub spatial_resolution: SpatialResolution,
72
}
73

74
impl PartialQueryRect {
75
    fn raster_query_rectangle(&self, attributes: BandSelection) -> RasterQueryRectangle {
146✔
76
        RasterQueryRectangle {
146✔
77
            spatial_bounds: self.spatial_bounds,
146✔
78
            time_interval: self.time_interval,
146✔
79
            spatial_resolution: self.spatial_resolution,
146✔
80
            attributes,
146✔
81
        }
146✔
82
    }
146✔
83
}
84

85
impl From<RasterQueryRectangle> for PartialQueryRect {
86
    fn from(value: RasterQueryRectangle) -> Self {
72✔
87
        Self {
72✔
88
            spatial_bounds: value.spatial_bounds,
72✔
89
            time_interval: value.time_interval,
72✔
90
            spatial_resolution: value.spatial_resolution,
72✔
91
        }
72✔
92
    }
72✔
93
}
94

95
/// Stacks the bands of the input raster streams to create a single raster stream with all the combined bands.
96
/// The input streams are automatically temporally aligned.
97
#[pin_project(project = RasterArrayTimeAdapterProjection)]
671✔
98
pub struct RasterStackerAdapter<T, F>
99
where
100
    T: Pixel,
101
    F: Queryable<T>,
102
    F::Stream: Stream<Item = Result<RasterTile2D<T>>>,
103
    F::Output: Future<Output = Result<F::Stream>>,
104
{
105
    // the sources (wrapped `QueryProcessor`s)
106
    sources: Vec<RasterStackerSource<F>>,
107
    #[pin]
108
    state: State<T, F>,
109
    // the current query rectangle, which is advanced over time by increasing the start time
110
    query_rect: PartialQueryRect,
111
    num_spatial_tiles: Option<usize>,
112
}
113

114
impl<T, F> RasterStackerAdapter<T, F>
115
where
116
    T: Pixel,
117
    F: Queryable<T>,
118
    F::Stream: Stream<Item = Result<RasterTile2D<T>>>,
119
    F::Output: Future<Output = Result<F::Stream>>,
120
{
121
    pub fn new(queryables: Vec<RasterStackerSource<F>>, query_rect: PartialQueryRect) -> Self {
77✔
122
        Self {
77✔
123
            sources: queryables,
77✔
124
            query_rect,
77✔
125
            state: State::Initial,
77✔
126
            num_spatial_tiles: None,
77✔
127
        }
77✔
128
    }
77✔
129

130
    fn number_of_tiles_in_partition(
100✔
131
        tile_info: &TileInformation,
100✔
132
        partition: SpatialPartition2D,
100✔
133
    ) -> usize {
100✔
134
        // TODO: get tiling strategy from stream or execution context instead of creating it here
100✔
135
        let strat = TilingStrategy {
100✔
136
            tile_size_in_pixels: tile_info.tile_size_in_pixels,
100✔
137
            geo_transform: tile_info.global_geo_transform,
100✔
138
        };
100✔
139

100✔
140
        strat.tile_grid_box(partition).number_of_elements()
100✔
141
    }
100✔
142

143
    fn grid_idx_for_nth_tile(
421✔
144
        tile_info: &TileInformation,
421✔
145
        partition: SpatialPartition2D,
421✔
146
        n: usize,
421✔
147
    ) -> Option<GridIdx2D> {
421✔
148
        let strat = TilingStrategy {
421✔
149
            tile_size_in_pixels: tile_info.tile_size_in_pixels,
421✔
150
            geo_transform: tile_info.global_geo_transform,
421✔
151
        };
421✔
152

421✔
153
        strat.tile_idx_iterator(partition).nth(n)
421✔
154
    }
421✔
155
}
156

157
impl<T, F> Stream for RasterStackerAdapter<T, F>
158
where
159
    T: Pixel,
160
    F: Queryable<T>,
161
    F::Stream: Stream<Item = Result<RasterTile2D<T>>> + Unpin,
162
    F::Output: Future<Output = Result<F::Stream>>,
163
{
164
    type Item = Result<RasterTile2D<T>>;
165

166
    #[allow(clippy::too_many_lines)] // TODO: refactor
167
    fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
671✔
168
        let RasterArrayTimeAdapterProjection {
671✔
169
            sources,
671✔
170
            mut state,
671✔
171
            query_rect,
671✔
172
            num_spatial_tiles,
671✔
173
        } = self.project();
671✔
174

175
        loop {
176
            match state.as_mut().project() {
971✔
177
                ArrayStateProjection::Initial => {
100✔
178
                    let array_of_futures = sources
100✔
179
                        .iter()
100✔
180
                        .map(|source| {
146✔
181
                            let query_rect = query_rect.raster_query_rectangle(
146✔
182
                                BandSelection::new_unchecked(source.band_idxs.clone()),
146✔
183
                            );
146✔
184
                            source.queryable.query(query_rect)
146✔
185
                        })
146✔
186
                        .collect::<Vec<_>>();
100✔
187

100✔
188
                    let query_futures = futures::future::join_all(array_of_futures);
100✔
189

100✔
190
                    state.set(State::AwaitingQuery { query_futures });
100✔
191
                }
100✔
192
                ArrayStateProjection::AwaitingQuery { query_futures } => {
155✔
193
                    let queries = ready!(query_futures.poll(cx));
155✔
194

195
                    let mut ok_queries = Vec::with_capacity(sources.len());
100✔
196
                    for query in queries {
246✔
197
                        match query {
146✔
198
                            Ok(query) => ok_queries.push(query),
146✔
199
                            Err(e) => {
×
200
                                // at least one source failed, output error and end the stream
×
201
                                state.set(State::Finished);
×
202
                                return Poll::Ready(Some(Err(e)));
×
203
                            }
204
                        }
205
                    }
206

207
                    // all sources produced an output, set the stream to be consumed
208
                    state.set(State::ConsumingStreams {
100✔
209
                        streams: ok_queries.into_iter().map(StreamExt::fuse).collect(),
100✔
210
                        stream_state: StreamState::CollectingFirstTiles {
100✔
211
                            first_tiles: (0..sources.len()).map(|_| None).collect(),
146✔
212
                        },
100✔
213
                    });
100✔
214
                }
100✔
215
                ArrayStateProjection::ConsumingStreams {
216
                    mut streams,
639✔
217
                    stream_state,
639✔
218
                } => match stream_state {
639✔
219
                    StreamState::CollectingFirstTiles { first_tiles } => {
177✔
220
                        for (stream, value) in streams.iter_mut().zip(first_tiles.iter_mut()) {
290✔
221
                            if value.is_none() {
290✔
222
                                match Pin::new(stream).poll_next(cx) {
257✔
223
                                    Poll::Ready(Some(item)) => *value = Some(item),
146✔
224
                                    Poll::Ready(None) | Poll::Pending => {}
111✔
225
                                }
226
                            }
33✔
227
                        }
228

229
                        let first_tiles = if first_tiles.iter().all(Option::is_some) {
177✔
230
                            let mut values = Vec::new();
100✔
231

232
                            for option in &mut *first_tiles {
246✔
233
                                if let Some(value) = option.take() {
146✔
234
                                    values.push(value);
146✔
235
                                }
146✔
236
                            }
237

238
                            values
100✔
239
                        } else if streams.iter().any(FusedStream::is_terminated) {
77✔
240
                            state.set(State::Finished);
×
241
                            return Poll::Ready(None);
×
242
                        } else {
243
                            return Poll::Pending;
77✔
244
                        };
245

246
                        let mut ok_tiles = Vec::with_capacity(sources.len());
100✔
247
                        for tile in first_tiles {
246✔
248
                            match tile {
146✔
249
                                Ok(tile) => ok_tiles.push(tile),
146✔
250
                                Err(e) => {
×
251
                                    // at least one stream failed, output error and end the stream
×
252
                                    state.set(State::Finished);
×
253
                                    return Poll::Ready(Some(Err(e)));
×
254
                                }
255
                            }
256
                        }
257

258
                        let mut iter = ok_tiles.iter();
100✔
259
                        let mut time = iter
100✔
260
                            .next()
100✔
261
                            .expect("RasterArrayTimeAdapter must have at least one input")
100✔
262
                            .time;
100✔
263

264
                        for tile in iter {
146✔
265
                            time = time.intersect(&tile.time).unwrap_or_else(|| {
46✔
266
                                    panic!(
×
267
                                        "intervals must overlap: ({}/{}) <-> ({}/{})\nThis is a bug and most likely means an operator or adapter has a faulty implementation.",
×
268
                                        time.start().as_datetime_string(),
×
269
                                        time.end().as_datetime_string(),
×
270
                                        tile.time.start().as_datetime_string(),
×
271
                                        tile.time.end().as_datetime_string()
×
272
                                    )
×
273
                                });
46✔
274
                        }
46✔
275

276
                        *num_spatial_tiles = Some(Self::number_of_tiles_in_partition(
100✔
277
                            &ok_tiles[0].tile_information(),
100✔
278
                            query_rect.spatial_bounds,
100✔
279
                        ));
100✔
280

100✔
281
                        *stream_state = StreamState::ProducingTimeSlice {
100✔
282
                            first_tiles: ok_tiles,
100✔
283
                            time_slice: time,
100✔
284
                            current_stream: 0,
100✔
285
                            current_band: 0,
100✔
286
                            current_spatial_tile: 0,
100✔
287
                        }
100✔
288
                    }
289
                    StreamState::ProducingTimeSlice {
290
                        first_tiles,
462✔
291
                        time_slice,
462✔
292
                        current_stream,
462✔
293
                        current_band,
462✔
294
                        current_spatial_tile,
462✔
295
                    } => {
296
                        let tile = if *current_spatial_tile == 0 && *current_band == 0 {
462✔
297
                            // consume tiles that were already computed first
298
                            Some(Ok(first_tiles[*current_stream].clone())) // TODO: avoid clone and instead consume the tile
146✔
299
                        } else {
300
                            ready!(Pin::new(&mut streams[*current_stream]).poll_next(cx))
316✔
301
                        };
302

303
                        let mut tile = match tile {
421✔
304
                            Some(Ok(tile)) => tile,
421✔
305
                            Some(Err(e)) => {
×
306
                                state.set(State::Finished);
×
307
                                return Poll::Ready(Some(Err(e)));
×
308
                            }
309
                            None => {
310
                                state.set(State::Finished);
×
311
                                return Poll::Ready(None);
×
312
                            }
313
                        };
314

315
                        debug_assert_eq!(
421✔
316
                                tile.band, *current_band as u32,
421✔
317
                                "RasterStacker got tile with unexpected band index: expected {}, got {} for source {}",
×
318
                                current_band,
319
                                tile.band,
320
                                current_stream
321
                            );
322

323
                        debug_assert!(
421✔
324
                                tile.time.contains(time_slice),
421✔
325
                                "RasterStacker got tile with unexpected time: time slice [{}, {}) not contained in tile time [{}, {}) for source {}",
×
326
                                time_slice.start().as_datetime_string(),
×
327
                                time_slice.end().as_datetime_string(),
×
328
                                tile.time.start().as_datetime_string(),
×
329
                                tile.time.end().as_datetime_string(),
×
330
                                current_stream
331
                            );
332

333
                        debug_assert_eq!(
421✔
334
                                Some(tile.tile_position), Self::grid_idx_for_nth_tile(&tile.tile_information(), query_rect.spatial_bounds, *current_spatial_tile),
421✔
335
                                "RasteStacker got tile with unexpected tile_position: expected {:?}, got {:?} for source {}",
×
336
                                Self::grid_idx_for_nth_tile(&tile.tile_information(), query_rect.spatial_bounds, *current_spatial_tile), tile.tile_position, current_stream
×
337
                            );
338

339
                        tile.band = sources
421✔
340
                            .iter()
421✔
341
                            .take(*current_stream)
421✔
342
                            .map(|b| b.band_idxs.len() as u32)
421✔
343
                            .sum::<u32>()
421✔
344
                            + *current_band as u32;
421✔
345
                        tile.time = *time_slice;
421✔
346

421✔
347
                        // make progress
421✔
348
                        *current_band += 1;
421✔
349
                        if *current_band >= sources[*current_stream].band_idxs.len() {
421✔
350
                            *current_band = 0;
375✔
351
                            *current_stream += 1;
375✔
352
                        }
375✔
353

354
                        if *current_stream >= streams.len() {
421✔
355
                            *current_stream = 0;
273✔
356
                            *current_band = 0;
273✔
357
                            *current_spatial_tile += 1;
273✔
358
                        }
273✔
359

360
                        if *current_spatial_tile >= num_spatial_tiles.unwrap_or_default() {
421✔
361
                            *current_spatial_tile = 0;
100✔
362
                            *current_band = 0;
100✔
363
                            *current_stream = 0;
100✔
364

100✔
365
                            let mut new_start = time_slice.end();
100✔
366

100✔
367
                            if new_start == query_rect.time_interval.start() {
100✔
368
                                // in the case that the time interval has no length, i.e. start=end,
2✔
369
                                // we have to advance `new_start` to prevent infinite loops.
2✔
370
                                // Otherwise, the new query rectangle would be equal to the previous one.
2✔
371
                                new_start += 1;
2✔
372
                            }
98✔
373

374
                            if new_start >= query_rect.time_interval.end() {
100✔
375
                                // the query window is exhausted, end the stream
77✔
376
                                state.set(State::Finished);
77✔
377
                            } else {
77✔
378
                                // advance the query rectangle and reset the state so that the sources are queried again for the next time step
23✔
379
                                query_rect.time_interval = TimeInterval::new_unchecked(
23✔
380
                                    new_start,
23✔
381
                                    query_rect.time_interval.end(),
23✔
382
                                );
23✔
383

23✔
384
                                state.set(State::Initial);
23✔
385
                            }
23✔
386
                        }
321✔
387

388
                        return Poll::Ready(Some(Ok(tile)));
421✔
389
                    }
390
                },
391

392
                ArrayStateProjection::Finished => return Poll::Ready(None),
77✔
393
            }
394
        }
395
    }
671✔
396
}
397

398
#[cfg(test)]
399
mod tests {
400
    use futures::StreamExt;
401
    use geoengine_datatypes::{
402
        primitives::{CacheHint, Measurement, SpatialResolution, TimeInterval},
403
        raster::{Grid, GridShape, RasterDataType, TilesEqualIgnoringCacheHint},
404
        spatial_reference::SpatialReference,
405
        util::test::TestDefault,
406
    };
407

408
    use crate::{
409
        adapters::QueryWrapper,
410
        engine::{
411
            MockExecutionContext, MockQueryContext, RasterBandDescriptor, RasterBandDescriptors,
412
            RasterOperator, RasterResultDescriptor, WorkflowOperatorPath,
413
        },
414
        mock::{MockRasterSource, MockRasterSourceParams},
415
    };
416

417
    use super::*;
418

419
    #[tokio::test]
420
    #[allow(clippy::too_many_lines)]
421
    async fn it_stacks() {
1✔
422
        let data: Vec<RasterTile2D<u8>> = vec![
1✔
423
            RasterTile2D {
1✔
424
                time: TimeInterval::new_unchecked(0, 5),
1✔
425
                tile_position: [-1, 0].into(),
1✔
426
                band: 0,
1✔
427
                global_geo_transform: TestDefault::test_default(),
1✔
428
                grid_array: Grid::new([2, 2].into(), vec![0, 1, 2, 3]).unwrap().into(),
1✔
429
                properties: Default::default(),
1✔
430
                cache_hint: CacheHint::default(),
1✔
431
            },
1✔
432
            RasterTile2D {
1✔
433
                time: TimeInterval::new_unchecked(0, 5),
1✔
434
                tile_position: [-1, 1].into(),
1✔
435
                band: 0,
1✔
436
                global_geo_transform: TestDefault::test_default(),
1✔
437
                grid_array: Grid::new([2, 2].into(), vec![4, 5, 6, 7]).unwrap().into(),
1✔
438
                properties: Default::default(),
1✔
439
                cache_hint: CacheHint::default(),
1✔
440
            },
1✔
441
            RasterTile2D {
1✔
442
                time: TimeInterval::new_unchecked(5, 10),
1✔
443
                tile_position: [-1, 0].into(),
1✔
444
                band: 0,
1✔
445
                global_geo_transform: TestDefault::test_default(),
1✔
446
                grid_array: Grid::new([2, 2].into(), vec![8, 9, 10, 11]).unwrap().into(),
1✔
447
                properties: Default::default(),
1✔
448
                cache_hint: CacheHint::default(),
1✔
449
            },
1✔
450
            RasterTile2D {
1✔
451
                time: TimeInterval::new_unchecked(5, 10),
1✔
452
                tile_position: [-1, 1].into(),
1✔
453
                band: 0,
1✔
454
                global_geo_transform: TestDefault::test_default(),
1✔
455
                grid_array: Grid::new([2, 2].into(), vec![12, 13, 14, 15])
1✔
456
                    .unwrap()
1✔
457
                    .into(),
1✔
458
                properties: Default::default(),
1✔
459
                cache_hint: CacheHint::default(),
1✔
460
            },
1✔
461
        ];
1✔
462

1✔
463
        let data2: Vec<RasterTile2D<u8>> = vec![
1✔
464
            RasterTile2D {
1✔
465
                time: TimeInterval::new_unchecked(0, 5),
1✔
466
                tile_position: [-1, 0].into(),
1✔
467
                band: 0,
1✔
468
                global_geo_transform: TestDefault::test_default(),
1✔
469
                grid_array: Grid::new([2, 2].into(), vec![16, 17, 18, 19])
1✔
470
                    .unwrap()
1✔
471
                    .into(),
1✔
472
                properties: Default::default(),
1✔
473
                cache_hint: CacheHint::default(),
1✔
474
            },
1✔
475
            RasterTile2D {
1✔
476
                time: TimeInterval::new_unchecked(0, 5),
1✔
477
                tile_position: [-1, 1].into(),
1✔
478
                band: 0,
1✔
479
                global_geo_transform: TestDefault::test_default(),
1✔
480
                grid_array: Grid::new([2, 2].into(), vec![20, 21, 22, 23])
1✔
481
                    .unwrap()
1✔
482
                    .into(),
1✔
483
                properties: Default::default(),
1✔
484
                cache_hint: CacheHint::default(),
1✔
485
            },
1✔
486
            RasterTile2D {
1✔
487
                time: TimeInterval::new_unchecked(5, 10),
1✔
488
                tile_position: [-1, 0].into(),
1✔
489
                band: 0,
1✔
490
                global_geo_transform: TestDefault::test_default(),
1✔
491
                grid_array: Grid::new([2, 2].into(), vec![24, 25, 26, 27])
1✔
492
                    .unwrap()
1✔
493
                    .into(),
1✔
494
                properties: Default::default(),
1✔
495
                cache_hint: CacheHint::default(),
1✔
496
            },
1✔
497
            RasterTile2D {
1✔
498
                time: TimeInterval::new_unchecked(5, 10),
1✔
499
                tile_position: [-1, 1].into(),
1✔
500
                band: 0,
1✔
501
                global_geo_transform: TestDefault::test_default(),
1✔
502
                grid_array: Grid::new([2, 2].into(), vec![28, 29, 30, 31])
1✔
503
                    .unwrap()
1✔
504
                    .into(),
1✔
505
                properties: Default::default(),
1✔
506
                cache_hint: CacheHint::default(),
1✔
507
            },
1✔
508
        ];
1✔
509

1✔
510
        let mrs1 = MockRasterSource {
1✔
511
            params: MockRasterSourceParams {
1✔
512
                data: data.clone(),
1✔
513
                result_descriptor: RasterResultDescriptor {
1✔
514
                    data_type: RasterDataType::U8,
1✔
515
                    spatial_reference: SpatialReference::epsg_4326().into(),
1✔
516
                    time: None,
1✔
517
                    bbox: None,
1✔
518
                    resolution: None,
1✔
519
                    bands: RasterBandDescriptors::new_single_band(),
1✔
520
                },
1✔
521
            },
1✔
522
        }
1✔
523
        .boxed();
1✔
524

1✔
525
        let mrs2 = MockRasterSource {
1✔
526
            params: MockRasterSourceParams {
1✔
527
                data: data2.clone(),
1✔
528
                result_descriptor: RasterResultDescriptor {
1✔
529
                    data_type: RasterDataType::U8,
1✔
530
                    spatial_reference: SpatialReference::epsg_4326().into(),
1✔
531
                    time: None,
1✔
532
                    bbox: None,
1✔
533
                    resolution: None,
1✔
534
                    bands: RasterBandDescriptors::new_single_band(),
1✔
535
                },
1✔
536
            },
1✔
537
        }
1✔
538
        .boxed();
1✔
539

1✔
540
        let mut exe_ctx = MockExecutionContext::test_default();
1✔
541
        exe_ctx.tiling_specification.tile_size_in_pixels = GridShape {
1✔
542
            shape_array: [2, 2],
1✔
543
        };
1✔
544

1✔
545
        let qp1 = mrs1
1✔
546
            .initialize(WorkflowOperatorPath::initialize_root(), &exe_ctx)
1✔
547
            .await
1✔
548
            .unwrap()
1✔
549
            .query_processor()
1✔
550
            .unwrap()
1✔
551
            .get_u8()
1✔
552
            .unwrap();
1✔
553

1✔
554
        let qp2 = mrs2
1✔
555
            .initialize(WorkflowOperatorPath::initialize_root(), &exe_ctx)
1✔
556
            .await
1✔
557
            .unwrap()
1✔
558
            .query_processor()
1✔
559
            .unwrap()
1✔
560
            .get_u8()
1✔
561
            .unwrap();
1✔
562

1✔
563
        let query_ctx = MockQueryContext::test_default();
1✔
564

1✔
565
        let stacker = RasterStackerAdapter::new(
1✔
566
            vec![
1✔
567
                (
1✔
568
                    QueryWrapper {
1✔
569
                        p: &qp1,
1✔
570
                        ctx: &query_ctx,
1✔
571
                    },
1✔
572
                    vec![0],
1✔
573
                )
1✔
574
                    .into(),
1✔
575
                (
1✔
576
                    QueryWrapper {
1✔
577
                        p: &qp2,
1✔
578
                        ctx: &query_ctx,
1✔
579
                    },
1✔
580
                    vec![0],
1✔
581
                )
1✔
582
                    .into(),
1✔
583
            ],
1✔
584
            PartialQueryRect {
1✔
585
                spatial_bounds: SpatialPartition2D::new_unchecked([0., 1.].into(), [3., 0.].into()),
1✔
586
                time_interval: TimeInterval::new_unchecked(0, 10),
1✔
587
                spatial_resolution: SpatialResolution::one(),
1✔
588
            },
1✔
589
        );
1✔
590

1✔
591
        let result = stacker.collect::<Vec<_>>().await;
1✔
592
        let result = result.into_iter().collect::<Result<Vec<_>>>().unwrap();
1✔
593

1✔
594
        let expected: Vec<_> = data
1✔
595
            .into_iter()
1✔
596
            .zip(data2.into_iter().map(|mut tile| {
4✔
597
                tile.band = 1;
4✔
598
                tile
4✔
599
            }))
4✔
600
            .flat_map(|(a, b)| vec![a.clone(), b.clone()])
4✔
601
            .collect();
1✔
602

1✔
603
        assert!(expected.tiles_equal_ignoring_cache_hint(&result));
1✔
604
    }
1✔
605

606
    #[tokio::test]
607
    #[allow(clippy::too_many_lines)]
608
    async fn it_keeps_single_band_input() {
1✔
609
        let data: Vec<RasterTile2D<u8>> = vec![
1✔
610
            RasterTile2D {
1✔
611
                time: TimeInterval::new_unchecked(0, 5),
1✔
612
                tile_position: [-1, 0].into(),
1✔
613
                band: 0,
1✔
614
                global_geo_transform: TestDefault::test_default(),
1✔
615
                grid_array: Grid::new([2, 2].into(), vec![0, 1, 2, 3]).unwrap().into(),
1✔
616
                properties: Default::default(),
1✔
617
                cache_hint: CacheHint::default(),
1✔
618
            },
1✔
619
            RasterTile2D {
1✔
620
                time: TimeInterval::new_unchecked(0, 5),
1✔
621
                tile_position: [-1, 1].into(),
1✔
622
                band: 0,
1✔
623
                global_geo_transform: TestDefault::test_default(),
1✔
624
                grid_array: Grid::new([2, 2].into(), vec![4, 5, 6, 7]).unwrap().into(),
1✔
625
                properties: Default::default(),
1✔
626
                cache_hint: CacheHint::default(),
1✔
627
            },
1✔
628
            RasterTile2D {
1✔
629
                time: TimeInterval::new_unchecked(5, 10),
1✔
630
                tile_position: [-1, 0].into(),
1✔
631
                band: 0,
1✔
632
                global_geo_transform: TestDefault::test_default(),
1✔
633
                grid_array: Grid::new([2, 2].into(), vec![8, 9, 10, 11]).unwrap().into(),
1✔
634
                properties: Default::default(),
1✔
635
                cache_hint: CacheHint::default(),
1✔
636
            },
1✔
637
            RasterTile2D {
1✔
638
                time: TimeInterval::new_unchecked(5, 10),
1✔
639
                tile_position: [-1, 1].into(),
1✔
640
                band: 0,
1✔
641
                global_geo_transform: TestDefault::test_default(),
1✔
642
                grid_array: Grid::new([2, 2].into(), vec![12, 13, 14, 15])
1✔
643
                    .unwrap()
1✔
644
                    .into(),
1✔
645
                properties: Default::default(),
1✔
646
                cache_hint: CacheHint::default(),
1✔
647
            },
1✔
648
        ];
1✔
649

1✔
650
        let mrs1 = MockRasterSource {
1✔
651
            params: MockRasterSourceParams {
1✔
652
                data: data.clone(),
1✔
653
                result_descriptor: RasterResultDescriptor {
1✔
654
                    data_type: RasterDataType::U8,
1✔
655
                    spatial_reference: SpatialReference::epsg_4326().into(),
1✔
656
                    time: None,
1✔
657
                    bbox: None,
1✔
658
                    resolution: None,
1✔
659
                    bands: RasterBandDescriptors::new_single_band(),
1✔
660
                },
1✔
661
            },
1✔
662
        }
1✔
663
        .boxed();
1✔
664

1✔
665
        let mut exe_ctx = MockExecutionContext::test_default();
1✔
666
        exe_ctx.tiling_specification.tile_size_in_pixels = GridShape {
1✔
667
            shape_array: [2, 2],
1✔
668
        };
1✔
669

1✔
670
        let qp1 = mrs1
1✔
671
            .initialize(WorkflowOperatorPath::initialize_root(), &exe_ctx)
1✔
672
            .await
1✔
673
            .unwrap()
1✔
674
            .query_processor()
1✔
675
            .unwrap()
1✔
676
            .get_u8()
1✔
677
            .unwrap();
1✔
678

1✔
679
        let query_ctx = MockQueryContext::test_default();
1✔
680

1✔
681
        let stacker = RasterStackerAdapter::new(
1✔
682
            vec![(
1✔
683
                QueryWrapper {
1✔
684
                    p: &qp1,
1✔
685
                    ctx: &query_ctx,
1✔
686
                },
1✔
687
                vec![0],
1✔
688
            )
1✔
689
                .into()],
1✔
690
            PartialQueryRect {
1✔
691
                spatial_bounds: SpatialPartition2D::new_unchecked([0., 1.].into(), [3., 0.].into()),
1✔
692
                time_interval: TimeInterval::new_unchecked(0, 10),
1✔
693
                spatial_resolution: SpatialResolution::one(),
1✔
694
            },
1✔
695
        );
1✔
696

1✔
697
        let result = stacker.collect::<Vec<_>>().await;
1✔
698
        let result = result.into_iter().collect::<Result<Vec<_>>>().unwrap();
1✔
699

1✔
700
        assert!(data.tiles_equal_ignoring_cache_hint(&result));
1✔
701
    }
1✔
702

703
    #[tokio::test]
704
    #[allow(clippy::too_many_lines)]
705
    async fn it_stacks_stacks() {
1✔
706
        let data: Vec<RasterTile2D<u8>> = vec![
1✔
707
            RasterTile2D {
1✔
708
                time: TimeInterval::new_unchecked(0, 5),
1✔
709
                tile_position: [-1, 0].into(),
1✔
710
                band: 0,
1✔
711
                global_geo_transform: TestDefault::test_default(),
1✔
712
                grid_array: Grid::new([2, 2].into(), vec![0, 1, 2, 3]).unwrap().into(),
1✔
713
                properties: Default::default(),
1✔
714
                cache_hint: CacheHint::default(),
1✔
715
            },
1✔
716
            RasterTile2D {
1✔
717
                time: TimeInterval::new_unchecked(0, 5),
1✔
718
                tile_position: [-1, 0].into(),
1✔
719
                band: 1,
1✔
720
                global_geo_transform: TestDefault::test_default(),
1✔
721
                grid_array: Grid::new([2, 2].into(), vec![3, 2, 1, 0]).unwrap().into(),
1✔
722
                properties: Default::default(),
1✔
723
                cache_hint: CacheHint::default(),
1✔
724
            },
1✔
725
            RasterTile2D {
1✔
726
                time: TimeInterval::new_unchecked(0, 5),
1✔
727
                tile_position: [-1, 1].into(),
1✔
728
                band: 0,
1✔
729
                global_geo_transform: TestDefault::test_default(),
1✔
730
                grid_array: Grid::new([2, 2].into(), vec![4, 5, 6, 7]).unwrap().into(),
1✔
731
                properties: Default::default(),
1✔
732
                cache_hint: CacheHint::default(),
1✔
733
            },
1✔
734
            RasterTile2D {
1✔
735
                time: TimeInterval::new_unchecked(0, 5),
1✔
736
                tile_position: [-1, 1].into(),
1✔
737
                band: 1,
1✔
738
                global_geo_transform: TestDefault::test_default(),
1✔
739
                grid_array: Grid::new([2, 2].into(), vec![7, 6, 5, 4]).unwrap().into(),
1✔
740
                properties: Default::default(),
1✔
741
                cache_hint: CacheHint::default(),
1✔
742
            },
1✔
743
            RasterTile2D {
1✔
744
                time: TimeInterval::new_unchecked(5, 10),
1✔
745
                tile_position: [-1, 0].into(),
1✔
746
                band: 0,
1✔
747
                global_geo_transform: TestDefault::test_default(),
1✔
748
                grid_array: Grid::new([2, 2].into(), vec![8, 9, 10, 11]).unwrap().into(),
1✔
749
                properties: Default::default(),
1✔
750
                cache_hint: CacheHint::default(),
1✔
751
            },
1✔
752
            RasterTile2D {
1✔
753
                time: TimeInterval::new_unchecked(5, 10),
1✔
754
                tile_position: [-1, 0].into(),
1✔
755
                band: 1,
1✔
756
                global_geo_transform: TestDefault::test_default(),
1✔
757
                grid_array: Grid::new([2, 2].into(), vec![11, 10, 9, 8]).unwrap().into(),
1✔
758
                properties: Default::default(),
1✔
759
                cache_hint: CacheHint::default(),
1✔
760
            },
1✔
761
            RasterTile2D {
1✔
762
                time: TimeInterval::new_unchecked(5, 10),
1✔
763
                tile_position: [-1, 1].into(),
1✔
764
                band: 0,
1✔
765
                global_geo_transform: TestDefault::test_default(),
1✔
766
                grid_array: Grid::new([2, 2].into(), vec![12, 13, 14, 15])
1✔
767
                    .unwrap()
1✔
768
                    .into(),
1✔
769
                properties: Default::default(),
1✔
770
                cache_hint: CacheHint::default(),
1✔
771
            },
1✔
772
            RasterTile2D {
1✔
773
                time: TimeInterval::new_unchecked(5, 10),
1✔
774
                tile_position: [-1, 1].into(),
1✔
775
                band: 1,
1✔
776
                global_geo_transform: TestDefault::test_default(),
1✔
777
                grid_array: Grid::new([2, 2].into(), vec![15, 14, 13, 12])
1✔
778
                    .unwrap()
1✔
779
                    .into(),
1✔
780
                properties: Default::default(),
1✔
781
                cache_hint: CacheHint::default(),
1✔
782
            },
1✔
783
        ];
1✔
784

1✔
785
        let data2: Vec<RasterTile2D<u8>> = vec![
1✔
786
            RasterTile2D {
1✔
787
                time: TimeInterval::new_unchecked(0, 5),
1✔
788
                tile_position: [-1, 0].into(),
1✔
789
                band: 0,
1✔
790
                global_geo_transform: TestDefault::test_default(),
1✔
791
                grid_array: Grid::new([2, 2].into(), vec![16, 17, 18, 19])
1✔
792
                    .unwrap()
1✔
793
                    .into(),
1✔
794
                properties: Default::default(),
1✔
795
                cache_hint: CacheHint::default(),
1✔
796
            },
1✔
797
            RasterTile2D {
1✔
798
                time: TimeInterval::new_unchecked(0, 5),
1✔
799
                tile_position: [-1, 0].into(),
1✔
800
                band: 1,
1✔
801
                global_geo_transform: TestDefault::test_default(),
1✔
802
                grid_array: Grid::new([2, 2].into(), vec![19, 18, 17, 16])
1✔
803
                    .unwrap()
1✔
804
                    .into(),
1✔
805
                properties: Default::default(),
1✔
806
                cache_hint: CacheHint::default(),
1✔
807
            },
1✔
808
            RasterTile2D {
1✔
809
                time: TimeInterval::new_unchecked(0, 5),
1✔
810
                tile_position: [-1, 1].into(),
1✔
811
                band: 0,
1✔
812
                global_geo_transform: TestDefault::test_default(),
1✔
813
                grid_array: Grid::new([2, 2].into(), vec![20, 21, 22, 23])
1✔
814
                    .unwrap()
1✔
815
                    .into(),
1✔
816
                properties: Default::default(),
1✔
817
                cache_hint: CacheHint::default(),
1✔
818
            },
1✔
819
            RasterTile2D {
1✔
820
                time: TimeInterval::new_unchecked(0, 5),
1✔
821
                tile_position: [-1, 1].into(),
1✔
822
                band: 1,
1✔
823
                global_geo_transform: TestDefault::test_default(),
1✔
824
                grid_array: Grid::new([2, 2].into(), vec![32, 22, 21, 20])
1✔
825
                    .unwrap()
1✔
826
                    .into(),
1✔
827
                properties: Default::default(),
1✔
828
                cache_hint: CacheHint::default(),
1✔
829
            },
1✔
830
            RasterTile2D {
1✔
831
                time: TimeInterval::new_unchecked(5, 10),
1✔
832
                tile_position: [-1, 0].into(),
1✔
833
                band: 0,
1✔
834
                global_geo_transform: TestDefault::test_default(),
1✔
835
                grid_array: Grid::new([2, 2].into(), vec![24, 25, 26, 27])
1✔
836
                    .unwrap()
1✔
837
                    .into(),
1✔
838
                properties: Default::default(),
1✔
839
                cache_hint: CacheHint::default(),
1✔
840
            },
1✔
841
            RasterTile2D {
1✔
842
                time: TimeInterval::new_unchecked(5, 10),
1✔
843
                tile_position: [-1, 0].into(),
1✔
844
                band: 1,
1✔
845
                global_geo_transform: TestDefault::test_default(),
1✔
846
                grid_array: Grid::new([2, 2].into(), vec![27, 26, 25, 24])
1✔
847
                    .unwrap()
1✔
848
                    .into(),
1✔
849
                properties: Default::default(),
1✔
850
                cache_hint: CacheHint::default(),
1✔
851
            },
1✔
852
            RasterTile2D {
1✔
853
                time: TimeInterval::new_unchecked(5, 10),
1✔
854
                tile_position: [-1, 1].into(),
1✔
855
                band: 0,
1✔
856
                global_geo_transform: TestDefault::test_default(),
1✔
857
                grid_array: Grid::new([2, 2].into(), vec![28, 29, 30, 31])
1✔
858
                    .unwrap()
1✔
859
                    .into(),
1✔
860
                properties: Default::default(),
1✔
861
                cache_hint: CacheHint::default(),
1✔
862
            },
1✔
863
            RasterTile2D {
1✔
864
                time: TimeInterval::new_unchecked(5, 10),
1✔
865
                tile_position: [-1, 1].into(),
1✔
866
                band: 1,
1✔
867
                global_geo_transform: TestDefault::test_default(),
1✔
868
                grid_array: Grid::new([2, 2].into(), vec![31, 30, 39, 28])
1✔
869
                    .unwrap()
1✔
870
                    .into(),
1✔
871
                properties: Default::default(),
1✔
872
                cache_hint: CacheHint::default(),
1✔
873
            },
1✔
874
        ];
1✔
875

1✔
876
        let mrs1 = MockRasterSource {
1✔
877
            params: MockRasterSourceParams {
1✔
878
                data: data.clone(),
1✔
879
                result_descriptor: RasterResultDescriptor {
1✔
880
                    data_type: RasterDataType::U8,
1✔
881
                    spatial_reference: SpatialReference::epsg_4326().into(),
1✔
882
                    time: None,
1✔
883
                    bbox: None,
1✔
884
                    resolution: None,
1✔
885
                    bands: vec![
1✔
886
                        RasterBandDescriptor::new("mrs1 band1".to_string(), Measurement::Unitless),
1✔
887
                        RasterBandDescriptor::new("mrs1 band2".to_string(), Measurement::Unitless),
1✔
888
                    ]
1✔
889
                    .try_into()
1✔
890
                    .unwrap(),
1✔
891
                },
1✔
892
            },
1✔
893
        }
1✔
894
        .boxed();
1✔
895

1✔
896
        let mrs2 = MockRasterSource {
1✔
897
            params: MockRasterSourceParams {
1✔
898
                data: data2.clone(),
1✔
899
                result_descriptor: RasterResultDescriptor {
1✔
900
                    data_type: RasterDataType::U8,
1✔
901
                    spatial_reference: SpatialReference::epsg_4326().into(),
1✔
902
                    time: None,
1✔
903
                    bbox: None,
1✔
904
                    resolution: None,
1✔
905
                    bands: vec![
1✔
906
                        RasterBandDescriptor::new("mrs2 band1".to_string(), Measurement::Unitless),
1✔
907
                        RasterBandDescriptor::new("mrs2 band2".to_string(), Measurement::Unitless),
1✔
908
                    ]
1✔
909
                    .try_into()
1✔
910
                    .unwrap(),
1✔
911
                },
1✔
912
            },
1✔
913
        }
1✔
914
        .boxed();
1✔
915

1✔
916
        let mut exe_ctx = MockExecutionContext::test_default();
1✔
917
        exe_ctx.tiling_specification.tile_size_in_pixels = GridShape {
1✔
918
            shape_array: [2, 2],
1✔
919
        };
1✔
920

1✔
921
        let qp1 = mrs1
1✔
922
            .initialize(WorkflowOperatorPath::initialize_root(), &exe_ctx)
1✔
923
            .await
1✔
924
            .unwrap()
1✔
925
            .query_processor()
1✔
926
            .unwrap()
1✔
927
            .get_u8()
1✔
928
            .unwrap();
1✔
929

1✔
930
        let qp2 = mrs2
1✔
931
            .initialize(WorkflowOperatorPath::initialize_root(), &exe_ctx)
1✔
932
            .await
1✔
933
            .unwrap()
1✔
934
            .query_processor()
1✔
935
            .unwrap()
1✔
936
            .get_u8()
1✔
937
            .unwrap();
1✔
938

1✔
939
        let query_ctx = MockQueryContext::test_default();
1✔
940

1✔
941
        let stacker = RasterStackerAdapter::new(
1✔
942
            vec![
1✔
943
                (
1✔
944
                    QueryWrapper {
1✔
945
                        p: &qp1,
1✔
946
                        ctx: &query_ctx,
1✔
947
                    },
1✔
948
                    vec![0, 1],
1✔
949
                )
1✔
950
                    .into(),
1✔
951
                (
1✔
952
                    QueryWrapper {
1✔
953
                        p: &qp2,
1✔
954
                        ctx: &query_ctx,
1✔
955
                    },
1✔
956
                    vec![0, 1],
1✔
957
                )
1✔
958
                    .into(),
1✔
959
            ],
1✔
960
            PartialQueryRect {
1✔
961
                spatial_bounds: SpatialPartition2D::new_unchecked([0., 1.].into(), [3., 0.].into()),
1✔
962
                time_interval: TimeInterval::new_unchecked(0, 10),
1✔
963
                spatial_resolution: SpatialResolution::one(),
1✔
964
            },
1✔
965
        );
1✔
966

1✔
967
        let result = stacker.collect::<Vec<_>>().await;
1✔
968
        let result = result.into_iter().collect::<Result<Vec<_>>>().unwrap();
1✔
969

1✔
970
        let expected: Vec<_> = data
1✔
971
            .chunks(2)
1✔
972
            .zip(
1✔
973
                data2
1✔
974
                    .into_iter()
1✔
975
                    .map(|mut tile| {
8✔
976
                        tile.band += 2;
8✔
977
                        tile
8✔
978
                    })
8✔
979
                    .collect::<Vec<_>>()
1✔
980
                    .chunks(2),
1✔
981
            )
1✔
982
            .flat_map(|(chunk1, chunk2)| chunk1.iter().chain(chunk2.iter()))
4✔
983
            .cloned()
1✔
984
            .collect();
1✔
985

1✔
986
        assert!(expected.tiles_equal_ignoring_cache_hint(&result));
1✔
987
    }
1✔
988

989
    #[tokio::test]
990
    #[allow(clippy::too_many_lines)]
991
    async fn it_aligns_temporally_while_stacking_stacks() {
1✔
992
        let data: Vec<RasterTile2D<u8>> = vec![
1✔
993
            RasterTile2D {
1✔
994
                time: TimeInterval::new_unchecked(0, 5),
1✔
995
                tile_position: [-1, 0].into(),
1✔
996
                band: 0,
1✔
997
                global_geo_transform: TestDefault::test_default(),
1✔
998
                grid_array: Grid::new([2, 2].into(), vec![0, 1, 2, 3]).unwrap().into(),
1✔
999
                properties: Default::default(),
1✔
1000
                cache_hint: CacheHint::default(),
1✔
1001
            },
1✔
1002
            RasterTile2D {
1✔
1003
                time: TimeInterval::new_unchecked(0, 5),
1✔
1004
                tile_position: [-1, 0].into(),
1✔
1005
                band: 1,
1✔
1006
                global_geo_transform: TestDefault::test_default(),
1✔
1007
                grid_array: Grid::new([2, 2].into(), vec![3, 2, 1, 0]).unwrap().into(),
1✔
1008
                properties: Default::default(),
1✔
1009
                cache_hint: CacheHint::default(),
1✔
1010
            },
1✔
1011
            RasterTile2D {
1✔
1012
                time: TimeInterval::new_unchecked(0, 5),
1✔
1013
                tile_position: [-1, 1].into(),
1✔
1014
                band: 0,
1✔
1015
                global_geo_transform: TestDefault::test_default(),
1✔
1016
                grid_array: Grid::new([2, 2].into(), vec![4, 5, 6, 7]).unwrap().into(),
1✔
1017
                properties: Default::default(),
1✔
1018
                cache_hint: CacheHint::default(),
1✔
1019
            },
1✔
1020
            RasterTile2D {
1✔
1021
                time: TimeInterval::new_unchecked(0, 5),
1✔
1022
                tile_position: [-1, 1].into(),
1✔
1023
                band: 1,
1✔
1024
                global_geo_transform: TestDefault::test_default(),
1✔
1025
                grid_array: Grid::new([2, 2].into(), vec![7, 6, 5, 4]).unwrap().into(),
1✔
1026
                properties: Default::default(),
1✔
1027
                cache_hint: CacheHint::default(),
1✔
1028
            },
1✔
1029
            RasterTile2D {
1✔
1030
                time: TimeInterval::new_unchecked(5, 10),
1✔
1031
                tile_position: [-1, 0].into(),
1✔
1032
                band: 0,
1✔
1033
                global_geo_transform: TestDefault::test_default(),
1✔
1034
                grid_array: Grid::new([2, 2].into(), vec![8, 9, 10, 11]).unwrap().into(),
1✔
1035
                properties: Default::default(),
1✔
1036
                cache_hint: CacheHint::default(),
1✔
1037
            },
1✔
1038
            RasterTile2D {
1✔
1039
                time: TimeInterval::new_unchecked(5, 10),
1✔
1040
                tile_position: [-1, 0].into(),
1✔
1041
                band: 1,
1✔
1042
                global_geo_transform: TestDefault::test_default(),
1✔
1043
                grid_array: Grid::new([2, 2].into(), vec![11, 10, 9, 8]).unwrap().into(),
1✔
1044
                properties: Default::default(),
1✔
1045
                cache_hint: CacheHint::default(),
1✔
1046
            },
1✔
1047
            RasterTile2D {
1✔
1048
                time: TimeInterval::new_unchecked(5, 10),
1✔
1049
                tile_position: [-1, 1].into(),
1✔
1050
                band: 0,
1✔
1051
                global_geo_transform: TestDefault::test_default(),
1✔
1052
                grid_array: Grid::new([2, 2].into(), vec![12, 13, 14, 15])
1✔
1053
                    .unwrap()
1✔
1054
                    .into(),
1✔
1055
                properties: Default::default(),
1✔
1056
                cache_hint: CacheHint::default(),
1✔
1057
            },
1✔
1058
            RasterTile2D {
1✔
1059
                time: TimeInterval::new_unchecked(5, 10),
1✔
1060
                tile_position: [-1, 1].into(),
1✔
1061
                band: 1,
1✔
1062
                global_geo_transform: TestDefault::test_default(),
1✔
1063
                grid_array: Grid::new([2, 2].into(), vec![15, 14, 13, 12])
1✔
1064
                    .unwrap()
1✔
1065
                    .into(),
1✔
1066
                properties: Default::default(),
1✔
1067
                cache_hint: CacheHint::default(),
1✔
1068
            },
1✔
1069
        ];
1✔
1070

1✔
1071
        let data2: Vec<RasterTile2D<u8>> = vec![
1✔
1072
            RasterTile2D {
1✔
1073
                time: TimeInterval::new_unchecked(0, 2),
1✔
1074
                tile_position: [-1, 0].into(),
1✔
1075
                band: 0,
1✔
1076
                global_geo_transform: TestDefault::test_default(),
1✔
1077
                grid_array: Grid::new([2, 2].into(), vec![16, 17, 18, 19])
1✔
1078
                    .unwrap()
1✔
1079
                    .into(),
1✔
1080
                properties: Default::default(),
1✔
1081
                cache_hint: CacheHint::default(),
1✔
1082
            },
1✔
1083
            RasterTile2D {
1✔
1084
                time: TimeInterval::new_unchecked(0, 2),
1✔
1085
                tile_position: [-1, 0].into(),
1✔
1086
                band: 1,
1✔
1087
                global_geo_transform: TestDefault::test_default(),
1✔
1088
                grid_array: Grid::new([2, 2].into(), vec![19, 18, 17, 16])
1✔
1089
                    .unwrap()
1✔
1090
                    .into(),
1✔
1091
                properties: Default::default(),
1✔
1092
                cache_hint: CacheHint::default(),
1✔
1093
            },
1✔
1094
            RasterTile2D {
1✔
1095
                time: TimeInterval::new_unchecked(0, 2),
1✔
1096
                tile_position: [-1, 1].into(),
1✔
1097
                band: 0,
1✔
1098
                global_geo_transform: TestDefault::test_default(),
1✔
1099
                grid_array: Grid::new([2, 2].into(), vec![20, 21, 22, 23])
1✔
1100
                    .unwrap()
1✔
1101
                    .into(),
1✔
1102
                properties: Default::default(),
1✔
1103
                cache_hint: CacheHint::default(),
1✔
1104
            },
1✔
1105
            RasterTile2D {
1✔
1106
                time: TimeInterval::new_unchecked(0, 2),
1✔
1107
                tile_position: [-1, 1].into(),
1✔
1108
                band: 1,
1✔
1109
                global_geo_transform: TestDefault::test_default(),
1✔
1110
                grid_array: Grid::new([2, 2].into(), vec![32, 22, 21, 20])
1✔
1111
                    .unwrap()
1✔
1112
                    .into(),
1✔
1113
                properties: Default::default(),
1✔
1114
                cache_hint: CacheHint::default(),
1✔
1115
            },
1✔
1116
            RasterTile2D {
1✔
1117
                time: TimeInterval::new_unchecked(2, 10),
1✔
1118
                tile_position: [-1, 0].into(),
1✔
1119
                band: 0,
1✔
1120
                global_geo_transform: TestDefault::test_default(),
1✔
1121
                grid_array: Grid::new([2, 2].into(), vec![24, 25, 26, 27])
1✔
1122
                    .unwrap()
1✔
1123
                    .into(),
1✔
1124
                properties: Default::default(),
1✔
1125
                cache_hint: CacheHint::default(),
1✔
1126
            },
1✔
1127
            RasterTile2D {
1✔
1128
                time: TimeInterval::new_unchecked(2, 10),
1✔
1129
                tile_position: [-1, 0].into(),
1✔
1130
                band: 1,
1✔
1131
                global_geo_transform: TestDefault::test_default(),
1✔
1132
                grid_array: Grid::new([2, 2].into(), vec![27, 26, 25, 24])
1✔
1133
                    .unwrap()
1✔
1134
                    .into(),
1✔
1135
                properties: Default::default(),
1✔
1136
                cache_hint: CacheHint::default(),
1✔
1137
            },
1✔
1138
            RasterTile2D {
1✔
1139
                time: TimeInterval::new_unchecked(2, 10),
1✔
1140
                tile_position: [-1, 1].into(),
1✔
1141
                band: 0,
1✔
1142
                global_geo_transform: TestDefault::test_default(),
1✔
1143
                grid_array: Grid::new([2, 2].into(), vec![28, 29, 30, 31])
1✔
1144
                    .unwrap()
1✔
1145
                    .into(),
1✔
1146
                properties: Default::default(),
1✔
1147
                cache_hint: CacheHint::default(),
1✔
1148
            },
1✔
1149
            RasterTile2D {
1✔
1150
                time: TimeInterval::new_unchecked(2, 10),
1✔
1151
                tile_position: [-1, 1].into(),
1✔
1152
                band: 1,
1✔
1153
                global_geo_transform: TestDefault::test_default(),
1✔
1154
                grid_array: Grid::new([2, 2].into(), vec![31, 30, 39, 28])
1✔
1155
                    .unwrap()
1✔
1156
                    .into(),
1✔
1157
                properties: Default::default(),
1✔
1158
                cache_hint: CacheHint::default(),
1✔
1159
            },
1✔
1160
        ];
1✔
1161

1✔
1162
        let mrs1 = MockRasterSource {
1✔
1163
            params: MockRasterSourceParams {
1✔
1164
                data: data.clone(),
1✔
1165
                result_descriptor: RasterResultDescriptor {
1✔
1166
                    data_type: RasterDataType::U8,
1✔
1167
                    spatial_reference: SpatialReference::epsg_4326().into(),
1✔
1168
                    time: None,
1✔
1169
                    bbox: None,
1✔
1170
                    resolution: None,
1✔
1171
                    bands: vec![
1✔
1172
                        RasterBandDescriptor::new("mrs1 band1".to_string(), Measurement::Unitless),
1✔
1173
                        RasterBandDescriptor::new("mrs1 band2".to_string(), Measurement::Unitless),
1✔
1174
                    ]
1✔
1175
                    .try_into()
1✔
1176
                    .unwrap(),
1✔
1177
                },
1✔
1178
            },
1✔
1179
        }
1✔
1180
        .boxed();
1✔
1181

1✔
1182
        let mrs2 = MockRasterSource {
1✔
1183
            params: MockRasterSourceParams {
1✔
1184
                data: data2.clone(),
1✔
1185
                result_descriptor: RasterResultDescriptor {
1✔
1186
                    data_type: RasterDataType::U8,
1✔
1187
                    spatial_reference: SpatialReference::epsg_4326().into(),
1✔
1188
                    time: None,
1✔
1189
                    bbox: None,
1✔
1190
                    resolution: None,
1✔
1191
                    bands: vec![
1✔
1192
                        RasterBandDescriptor::new("mrs2 band1".to_string(), Measurement::Unitless),
1✔
1193
                        RasterBandDescriptor::new("mrs2 band2".to_string(), Measurement::Unitless),
1✔
1194
                    ]
1✔
1195
                    .try_into()
1✔
1196
                    .unwrap(),
1✔
1197
                },
1✔
1198
            },
1✔
1199
        }
1✔
1200
        .boxed();
1✔
1201

1✔
1202
        let mut exe_ctx = MockExecutionContext::test_default();
1✔
1203
        exe_ctx.tiling_specification.tile_size_in_pixels = GridShape {
1✔
1204
            shape_array: [2, 2],
1✔
1205
        };
1✔
1206

1✔
1207
        let qp1 = mrs1
1✔
1208
            .initialize(WorkflowOperatorPath::initialize_root(), &exe_ctx)
1✔
1209
            .await
1✔
1210
            .unwrap()
1✔
1211
            .query_processor()
1✔
1212
            .unwrap()
1✔
1213
            .get_u8()
1✔
1214
            .unwrap();
1✔
1215

1✔
1216
        let qp2 = mrs2
1✔
1217
            .initialize(WorkflowOperatorPath::initialize_root(), &exe_ctx)
1✔
1218
            .await
1✔
1219
            .unwrap()
1✔
1220
            .query_processor()
1✔
1221
            .unwrap()
1✔
1222
            .get_u8()
1✔
1223
            .unwrap();
1✔
1224

1✔
1225
        let query_ctx = MockQueryContext::test_default();
1✔
1226

1✔
1227
        let stacker = RasterStackerAdapter::new(
1✔
1228
            vec![
1✔
1229
                (
1✔
1230
                    QueryWrapper {
1✔
1231
                        p: &qp1,
1✔
1232
                        ctx: &query_ctx,
1✔
1233
                    },
1✔
1234
                    vec![0, 1],
1✔
1235
                )
1✔
1236
                    .into(),
1✔
1237
                (
1✔
1238
                    QueryWrapper {
1✔
1239
                        p: &qp2,
1✔
1240
                        ctx: &query_ctx,
1✔
1241
                    },
1✔
1242
                    vec![0, 1],
1✔
1243
                )
1✔
1244
                    .into(),
1✔
1245
            ],
1✔
1246
            PartialQueryRect {
1✔
1247
                spatial_bounds: SpatialPartition2D::new_unchecked([0., 1.].into(), [3., 0.].into()),
1✔
1248
                time_interval: TimeInterval::new_unchecked(0, 10),
1✔
1249
                spatial_resolution: SpatialResolution::one(),
1✔
1250
            },
1✔
1251
        );
1✔
1252

1✔
1253
        let result = stacker.collect::<Vec<_>>().await;
1✔
1254
        let result = result.into_iter().collect::<Result<Vec<_>>>().unwrap();
1✔
1255

1✔
1256
        let expected: Vec<RasterTile2D<u8>> = vec![
1✔
1257
            RasterTile2D {
1✔
1258
                time: TimeInterval::new_unchecked(0, 2),
1✔
1259
                tile_position: [-1, 0].into(),
1✔
1260
                band: 0,
1✔
1261
                global_geo_transform: TestDefault::test_default(),
1✔
1262
                grid_array: Grid::new([2, 2].into(), vec![0, 1, 2, 3]).unwrap().into(),
1✔
1263
                properties: Default::default(),
1✔
1264
                cache_hint: CacheHint::default(),
1✔
1265
            },
1✔
1266
            RasterTile2D {
1✔
1267
                time: TimeInterval::new_unchecked(0, 2),
1✔
1268
                tile_position: [-1, 0].into(),
1✔
1269
                band: 1,
1✔
1270
                global_geo_transform: TestDefault::test_default(),
1✔
1271
                grid_array: Grid::new([2, 2].into(), vec![3, 2, 1, 0]).unwrap().into(),
1✔
1272
                properties: Default::default(),
1✔
1273
                cache_hint: CacheHint::default(),
1✔
1274
            },
1✔
1275
            RasterTile2D {
1✔
1276
                time: TimeInterval::new_unchecked(0, 2),
1✔
1277
                tile_position: [-1, 0].into(),
1✔
1278
                band: 2,
1✔
1279
                global_geo_transform: TestDefault::test_default(),
1✔
1280
                grid_array: Grid::new([2, 2].into(), vec![16, 17, 18, 19])
1✔
1281
                    .unwrap()
1✔
1282
                    .into(),
1✔
1283
                properties: Default::default(),
1✔
1284
                cache_hint: CacheHint::default(),
1✔
1285
            },
1✔
1286
            RasterTile2D {
1✔
1287
                time: TimeInterval::new_unchecked(0, 2),
1✔
1288
                tile_position: [-1, 0].into(),
1✔
1289
                band: 3,
1✔
1290
                global_geo_transform: TestDefault::test_default(),
1✔
1291
                grid_array: Grid::new([2, 2].into(), vec![19, 18, 17, 16])
1✔
1292
                    .unwrap()
1✔
1293
                    .into(),
1✔
1294
                properties: Default::default(),
1✔
1295
                cache_hint: CacheHint::default(),
1✔
1296
            },
1✔
1297
            RasterTile2D {
1✔
1298
                time: TimeInterval::new_unchecked(0, 2),
1✔
1299
                tile_position: [-1, 1].into(),
1✔
1300
                band: 0,
1✔
1301
                global_geo_transform: TestDefault::test_default(),
1✔
1302
                grid_array: Grid::new([2, 2].into(), vec![4, 5, 6, 7]).unwrap().into(),
1✔
1303
                properties: Default::default(),
1✔
1304
                cache_hint: CacheHint::default(),
1✔
1305
            },
1✔
1306
            RasterTile2D {
1✔
1307
                time: TimeInterval::new_unchecked(0, 2),
1✔
1308
                tile_position: [-1, 1].into(),
1✔
1309
                band: 1,
1✔
1310
                global_geo_transform: TestDefault::test_default(),
1✔
1311
                grid_array: Grid::new([2, 2].into(), vec![7, 6, 5, 4]).unwrap().into(),
1✔
1312
                properties: Default::default(),
1✔
1313
                cache_hint: CacheHint::default(),
1✔
1314
            },
1✔
1315
            RasterTile2D {
1✔
1316
                time: TimeInterval::new_unchecked(0, 2),
1✔
1317
                tile_position: [-1, 1].into(),
1✔
1318
                band: 2,
1✔
1319
                global_geo_transform: TestDefault::test_default(),
1✔
1320
                grid_array: Grid::new([2, 2].into(), vec![20, 21, 22, 23])
1✔
1321
                    .unwrap()
1✔
1322
                    .into(),
1✔
1323
                properties: Default::default(),
1✔
1324
                cache_hint: CacheHint::default(),
1✔
1325
            },
1✔
1326
            RasterTile2D {
1✔
1327
                time: TimeInterval::new_unchecked(0, 2),
1✔
1328
                tile_position: [-1, 1].into(),
1✔
1329
                band: 3,
1✔
1330
                global_geo_transform: TestDefault::test_default(),
1✔
1331
                grid_array: Grid::new([2, 2].into(), vec![32, 22, 21, 20])
1✔
1332
                    .unwrap()
1✔
1333
                    .into(),
1✔
1334
                properties: Default::default(),
1✔
1335
                cache_hint: CacheHint::default(),
1✔
1336
            },
1✔
1337
            RasterTile2D {
1✔
1338
                time: TimeInterval::new_unchecked(2, 5),
1✔
1339
                tile_position: [-1, 0].into(),
1✔
1340
                band: 0,
1✔
1341
                global_geo_transform: TestDefault::test_default(),
1✔
1342
                grid_array: Grid::new([2, 2].into(), vec![0, 1, 2, 3]).unwrap().into(),
1✔
1343
                properties: Default::default(),
1✔
1344
                cache_hint: CacheHint::default(),
1✔
1345
            },
1✔
1346
            RasterTile2D {
1✔
1347
                time: TimeInterval::new_unchecked(2, 5),
1✔
1348
                tile_position: [-1, 0].into(),
1✔
1349
                band: 1,
1✔
1350
                global_geo_transform: TestDefault::test_default(),
1✔
1351
                grid_array: Grid::new([2, 2].into(), vec![3, 2, 1, 0]).unwrap().into(),
1✔
1352
                properties: Default::default(),
1✔
1353
                cache_hint: CacheHint::default(),
1✔
1354
            },
1✔
1355
            RasterTile2D {
1✔
1356
                time: TimeInterval::new_unchecked(2, 5),
1✔
1357
                tile_position: [-1, 0].into(),
1✔
1358
                band: 2,
1✔
1359
                global_geo_transform: TestDefault::test_default(),
1✔
1360
                grid_array: Grid::new([2, 2].into(), vec![24, 25, 26, 27])
1✔
1361
                    .unwrap()
1✔
1362
                    .into(),
1✔
1363
                properties: Default::default(),
1✔
1364
                cache_hint: CacheHint::default(),
1✔
1365
            },
1✔
1366
            RasterTile2D {
1✔
1367
                time: TimeInterval::new_unchecked(2, 5),
1✔
1368
                tile_position: [-1, 0].into(),
1✔
1369
                band: 3,
1✔
1370
                global_geo_transform: TestDefault::test_default(),
1✔
1371
                grid_array: Grid::new([2, 2].into(), vec![27, 26, 25, 24])
1✔
1372
                    .unwrap()
1✔
1373
                    .into(),
1✔
1374
                properties: Default::default(),
1✔
1375
                cache_hint: CacheHint::default(),
1✔
1376
            },
1✔
1377
            RasterTile2D {
1✔
1378
                time: TimeInterval::new_unchecked(2, 5),
1✔
1379
                tile_position: [-1, 1].into(),
1✔
1380
                band: 0,
1✔
1381
                global_geo_transform: TestDefault::test_default(),
1✔
1382
                grid_array: Grid::new([2, 2].into(), vec![4, 5, 6, 7]).unwrap().into(),
1✔
1383
                properties: Default::default(),
1✔
1384
                cache_hint: CacheHint::default(),
1✔
1385
            },
1✔
1386
            RasterTile2D {
1✔
1387
                time: TimeInterval::new_unchecked(2, 5),
1✔
1388
                tile_position: [-1, 1].into(),
1✔
1389
                band: 1,
1✔
1390
                global_geo_transform: TestDefault::test_default(),
1✔
1391
                grid_array: Grid::new([2, 2].into(), vec![7, 6, 5, 4]).unwrap().into(),
1✔
1392
                properties: Default::default(),
1✔
1393
                cache_hint: CacheHint::default(),
1✔
1394
            },
1✔
1395
            RasterTile2D {
1✔
1396
                time: TimeInterval::new_unchecked(2, 5),
1✔
1397
                tile_position: [-1, 1].into(),
1✔
1398
                band: 2,
1✔
1399
                global_geo_transform: TestDefault::test_default(),
1✔
1400
                grid_array: Grid::new([2, 2].into(), vec![28, 29, 30, 31])
1✔
1401
                    .unwrap()
1✔
1402
                    .into(),
1✔
1403
                properties: Default::default(),
1✔
1404
                cache_hint: CacheHint::default(),
1✔
1405
            },
1✔
1406
            RasterTile2D {
1✔
1407
                time: TimeInterval::new_unchecked(2, 5),
1✔
1408
                tile_position: [-1, 1].into(),
1✔
1409
                band: 3,
1✔
1410
                global_geo_transform: TestDefault::test_default(),
1✔
1411
                grid_array: Grid::new([2, 2].into(), vec![31, 30, 39, 28])
1✔
1412
                    .unwrap()
1✔
1413
                    .into(),
1✔
1414
                properties: Default::default(),
1✔
1415
                cache_hint: CacheHint::default(),
1✔
1416
            },
1✔
1417
            RasterTile2D {
1✔
1418
                time: TimeInterval::new_unchecked(5, 10),
1✔
1419
                tile_position: [-1, 0].into(),
1✔
1420
                band: 0,
1✔
1421
                global_geo_transform: TestDefault::test_default(),
1✔
1422
                grid_array: Grid::new([2, 2].into(), vec![8, 9, 10, 11]).unwrap().into(),
1✔
1423
                properties: Default::default(),
1✔
1424
                cache_hint: CacheHint::default(),
1✔
1425
            },
1✔
1426
            RasterTile2D {
1✔
1427
                time: TimeInterval::new_unchecked(5, 10),
1✔
1428
                tile_position: [-1, 0].into(),
1✔
1429
                band: 1,
1✔
1430
                global_geo_transform: TestDefault::test_default(),
1✔
1431
                grid_array: Grid::new([2, 2].into(), vec![11, 10, 9, 8]).unwrap().into(),
1✔
1432
                properties: Default::default(),
1✔
1433
                cache_hint: CacheHint::default(),
1✔
1434
            },
1✔
1435
            RasterTile2D {
1✔
1436
                time: TimeInterval::new_unchecked(5, 10),
1✔
1437
                tile_position: [-1, 0].into(),
1✔
1438
                band: 2,
1✔
1439
                global_geo_transform: TestDefault::test_default(),
1✔
1440
                grid_array: Grid::new([2, 2].into(), vec![24, 25, 26, 27])
1✔
1441
                    .unwrap()
1✔
1442
                    .into(),
1✔
1443
                properties: Default::default(),
1✔
1444
                cache_hint: CacheHint::default(),
1✔
1445
            },
1✔
1446
            RasterTile2D {
1✔
1447
                time: TimeInterval::new_unchecked(5, 10),
1✔
1448
                tile_position: [-1, 0].into(),
1✔
1449
                band: 3,
1✔
1450
                global_geo_transform: TestDefault::test_default(),
1✔
1451
                grid_array: Grid::new([2, 2].into(), vec![27, 26, 25, 24])
1✔
1452
                    .unwrap()
1✔
1453
                    .into(),
1✔
1454
                properties: Default::default(),
1✔
1455
                cache_hint: CacheHint::default(),
1✔
1456
            },
1✔
1457
            RasterTile2D {
1✔
1458
                time: TimeInterval::new_unchecked(5, 10),
1✔
1459
                tile_position: [-1, 1].into(),
1✔
1460
                band: 0,
1✔
1461
                global_geo_transform: TestDefault::test_default(),
1✔
1462
                grid_array: Grid::new([2, 2].into(), vec![12, 13, 14, 15])
1✔
1463
                    .unwrap()
1✔
1464
                    .into(),
1✔
1465
                properties: Default::default(),
1✔
1466
                cache_hint: CacheHint::default(),
1✔
1467
            },
1✔
1468
            RasterTile2D {
1✔
1469
                time: TimeInterval::new_unchecked(5, 10),
1✔
1470
                tile_position: [-1, 1].into(),
1✔
1471
                band: 1,
1✔
1472
                global_geo_transform: TestDefault::test_default(),
1✔
1473
                grid_array: Grid::new([2, 2].into(), vec![15, 14, 13, 12])
1✔
1474
                    .unwrap()
1✔
1475
                    .into(),
1✔
1476
                properties: Default::default(),
1✔
1477
                cache_hint: CacheHint::default(),
1✔
1478
            },
1✔
1479
            RasterTile2D {
1✔
1480
                time: TimeInterval::new_unchecked(5, 10),
1✔
1481
                tile_position: [-1, 1].into(),
1✔
1482
                band: 2,
1✔
1483
                global_geo_transform: TestDefault::test_default(),
1✔
1484
                grid_array: Grid::new([2, 2].into(), vec![28, 29, 30, 31])
1✔
1485
                    .unwrap()
1✔
1486
                    .into(),
1✔
1487
                properties: Default::default(),
1✔
1488
                cache_hint: CacheHint::default(),
1✔
1489
            },
1✔
1490
            RasterTile2D {
1✔
1491
                time: TimeInterval::new_unchecked(5, 10),
1✔
1492
                tile_position: [-1, 1].into(),
1✔
1493
                band: 3,
1✔
1494
                global_geo_transform: TestDefault::test_default(),
1✔
1495
                grid_array: Grid::new([2, 2].into(), vec![31, 30, 39, 28])
1✔
1496
                    .unwrap()
1✔
1497
                    .into(),
1✔
1498
                properties: Default::default(),
1✔
1499
                cache_hint: CacheHint::default(),
1✔
1500
            },
1✔
1501
        ];
1✔
1502

1✔
1503
        assert!(expected.tiles_equal_ignoring_cache_hint(&result));
1✔
1504
    }
1✔
1505

1506
    #[tokio::test]
1507
    #[allow(clippy::too_many_lines)]
1508
    async fn it_stacks_more() {
1✔
1509
        // input 1: 3 bands
1✔
1510
        let data: Vec<RasterTile2D<u8>> = vec![
1✔
1511
            RasterTile2D {
1✔
1512
                time: TimeInterval::new_unchecked(0, 5),
1✔
1513
                tile_position: [-1, 0].into(),
1✔
1514
                band: 0,
1✔
1515
                global_geo_transform: TestDefault::test_default(),
1✔
1516
                grid_array: Grid::new([2, 2].into(), vec![0, 1, 2, 3]).unwrap().into(),
1✔
1517
                properties: Default::default(),
1✔
1518
                cache_hint: CacheHint::default(),
1✔
1519
            },
1✔
1520
            RasterTile2D {
1✔
1521
                time: TimeInterval::new_unchecked(0, 5),
1✔
1522
                tile_position: [-1, 0].into(),
1✔
1523
                band: 1,
1✔
1524
                global_geo_transform: TestDefault::test_default(),
1✔
1525
                grid_array: Grid::new([2, 2].into(), vec![3, 2, 1, 0]).unwrap().into(),
1✔
1526
                properties: Default::default(),
1✔
1527
                cache_hint: CacheHint::default(),
1✔
1528
            },
1✔
1529
            RasterTile2D {
1✔
1530
                time: TimeInterval::new_unchecked(0, 5),
1✔
1531
                tile_position: [-1, 0].into(),
1✔
1532
                band: 2,
1✔
1533
                global_geo_transform: TestDefault::test_default(),
1✔
1534
                grid_array: Grid::new([2, 2].into(), vec![223, 222, 221, 20])
1✔
1535
                    .unwrap()
1✔
1536
                    .into(),
1✔
1537
                properties: Default::default(),
1✔
1538
                cache_hint: CacheHint::default(),
1✔
1539
            },
1✔
1540
            RasterTile2D {
1✔
1541
                time: TimeInterval::new_unchecked(0, 5),
1✔
1542
                tile_position: [-1, 1].into(),
1✔
1543
                band: 0,
1✔
1544
                global_geo_transform: TestDefault::test_default(),
1✔
1545
                grid_array: Grid::new([2, 2].into(), vec![4, 5, 6, 7]).unwrap().into(),
1✔
1546
                properties: Default::default(),
1✔
1547
                cache_hint: CacheHint::default(),
1✔
1548
            },
1✔
1549
            RasterTile2D {
1✔
1550
                time: TimeInterval::new_unchecked(0, 5),
1✔
1551
                tile_position: [-1, 1].into(),
1✔
1552
                band: 1,
1✔
1553
                global_geo_transform: TestDefault::test_default(),
1✔
1554
                grid_array: Grid::new([2, 2].into(), vec![7, 6, 5, 4]).unwrap().into(),
1✔
1555
                properties: Default::default(),
1✔
1556
                cache_hint: CacheHint::default(),
1✔
1557
            },
1✔
1558
            RasterTile2D {
1✔
1559
                time: TimeInterval::new_unchecked(0, 5),
1✔
1560
                tile_position: [-1, 1].into(),
1✔
1561
                band: 2,
1✔
1562
                global_geo_transform: TestDefault::test_default(),
1✔
1563
                grid_array: Grid::new([2, 2].into(), vec![227, 226, 225, 224])
1✔
1564
                    .unwrap()
1✔
1565
                    .into(),
1✔
1566
                properties: Default::default(),
1✔
1567
                cache_hint: CacheHint::default(),
1✔
1568
            },
1✔
1569
            RasterTile2D {
1✔
1570
                time: TimeInterval::new_unchecked(5, 10),
1✔
1571
                tile_position: [-1, 0].into(),
1✔
1572
                band: 0,
1✔
1573
                global_geo_transform: TestDefault::test_default(),
1✔
1574
                grid_array: Grid::new([2, 2].into(), vec![8, 9, 10, 11]).unwrap().into(),
1✔
1575
                properties: Default::default(),
1✔
1576
                cache_hint: CacheHint::default(),
1✔
1577
            },
1✔
1578
            RasterTile2D {
1✔
1579
                time: TimeInterval::new_unchecked(5, 10),
1✔
1580
                tile_position: [-1, 0].into(),
1✔
1581
                band: 1,
1✔
1582
                global_geo_transform: TestDefault::test_default(),
1✔
1583
                grid_array: Grid::new([2, 2].into(), vec![11, 10, 9, 8]).unwrap().into(),
1✔
1584
                properties: Default::default(),
1✔
1585
                cache_hint: CacheHint::default(),
1✔
1586
            },
1✔
1587
            RasterTile2D {
1✔
1588
                time: TimeInterval::new_unchecked(5, 10),
1✔
1589
                tile_position: [-1, 0].into(),
1✔
1590
                band: 2,
1✔
1591
                global_geo_transform: TestDefault::test_default(),
1✔
1592
                grid_array: Grid::new([2, 2].into(), vec![211, 210, 29, 28])
1✔
1593
                    .unwrap()
1✔
1594
                    .into(),
1✔
1595
                properties: Default::default(),
1✔
1596
                cache_hint: CacheHint::default(),
1✔
1597
            },
1✔
1598
            RasterTile2D {
1✔
1599
                time: TimeInterval::new_unchecked(5, 10),
1✔
1600
                tile_position: [-1, 1].into(),
1✔
1601
                band: 0,
1✔
1602
                global_geo_transform: TestDefault::test_default(),
1✔
1603
                grid_array: Grid::new([2, 2].into(), vec![12, 13, 14, 15])
1✔
1604
                    .unwrap()
1✔
1605
                    .into(),
1✔
1606
                properties: Default::default(),
1✔
1607
                cache_hint: CacheHint::default(),
1✔
1608
            },
1✔
1609
            RasterTile2D {
1✔
1610
                time: TimeInterval::new_unchecked(5, 10),
1✔
1611
                tile_position: [-1, 1].into(),
1✔
1612
                band: 1,
1✔
1613
                global_geo_transform: TestDefault::test_default(),
1✔
1614
                grid_array: Grid::new([2, 2].into(), vec![15, 14, 13, 12])
1✔
1615
                    .unwrap()
1✔
1616
                    .into(),
1✔
1617
                properties: Default::default(),
1✔
1618
                cache_hint: CacheHint::default(),
1✔
1619
            },
1✔
1620
            RasterTile2D {
1✔
1621
                time: TimeInterval::new_unchecked(5, 10),
1✔
1622
                tile_position: [-1, 1].into(),
1✔
1623
                band: 2,
1✔
1624
                global_geo_transform: TestDefault::test_default(),
1✔
1625
                grid_array: Grid::new([2, 2].into(), vec![215, 214, 213, 212])
1✔
1626
                    .unwrap()
1✔
1627
                    .into(),
1✔
1628
                properties: Default::default(),
1✔
1629
                cache_hint: CacheHint::default(),
1✔
1630
            },
1✔
1631
        ];
1✔
1632

1✔
1633
        // input 2: 1 band
1✔
1634
        let data2: Vec<RasterTile2D<u8>> = vec![
1✔
1635
            RasterTile2D {
1✔
1636
                time: TimeInterval::new_unchecked(0, 2),
1✔
1637
                tile_position: [-1, 0].into(),
1✔
1638
                band: 0,
1✔
1639
                global_geo_transform: TestDefault::test_default(),
1✔
1640
                grid_array: Grid::new([2, 2].into(), vec![88, 77, 66, 55])
1✔
1641
                    .unwrap()
1✔
1642
                    .into(),
1✔
1643
                properties: Default::default(),
1✔
1644
                cache_hint: CacheHint::default(),
1✔
1645
            },
1✔
1646
            RasterTile2D {
1✔
1647
                time: TimeInterval::new_unchecked(0, 2),
1✔
1648
                tile_position: [-1, 1].into(),
1✔
1649
                band: 0,
1✔
1650
                global_geo_transform: TestDefault::test_default(),
1✔
1651
                grid_array: Grid::new([2, 2].into(), vec![87, 76, 65, 54])
1✔
1652
                    .unwrap()
1✔
1653
                    .into(),
1✔
1654
                properties: Default::default(),
1✔
1655
                cache_hint: CacheHint::default(),
1✔
1656
            },
1✔
1657
            RasterTile2D {
1✔
1658
                time: TimeInterval::new_unchecked(2, 10),
1✔
1659
                tile_position: [-1, 0].into(),
1✔
1660
                band: 0,
1✔
1661
                global_geo_transform: TestDefault::test_default(),
1✔
1662
                grid_array: Grid::new([2, 2].into(), vec![86, 75, 63, 51])
1✔
1663
                    .unwrap()
1✔
1664
                    .into(),
1✔
1665
                properties: Default::default(),
1✔
1666
                cache_hint: CacheHint::default(),
1✔
1667
            },
1✔
1668
            RasterTile2D {
1✔
1669
                time: TimeInterval::new_unchecked(2, 10),
1✔
1670
                tile_position: [-1, 1].into(),
1✔
1671
                band: 0,
1✔
1672
                global_geo_transform: TestDefault::test_default(),
1✔
1673
                grid_array: Grid::new([2, 2].into(), vec![85, 74, 62, 50])
1✔
1674
                    .unwrap()
1✔
1675
                    .into(),
1✔
1676
                properties: Default::default(),
1✔
1677
                cache_hint: CacheHint::default(),
1✔
1678
            },
1✔
1679
        ];
1✔
1680

1✔
1681
        // input 3: 2 bands
1✔
1682
        let data3: Vec<RasterTile2D<u8>> = vec![
1✔
1683
            RasterTile2D {
1✔
1684
                time: TimeInterval::new_unchecked(0, 2),
1✔
1685
                tile_position: [-1, 0].into(),
1✔
1686
                band: 0,
1✔
1687
                global_geo_transform: TestDefault::test_default(),
1✔
1688
                grid_array: Grid::new([2, 2].into(), vec![16, 17, 18, 19])
1✔
1689
                    .unwrap()
1✔
1690
                    .into(),
1✔
1691
                properties: Default::default(),
1✔
1692
                cache_hint: CacheHint::default(),
1✔
1693
            },
1✔
1694
            RasterTile2D {
1✔
1695
                time: TimeInterval::new_unchecked(0, 2),
1✔
1696
                tile_position: [-1, 0].into(),
1✔
1697
                band: 1,
1✔
1698
                global_geo_transform: TestDefault::test_default(),
1✔
1699
                grid_array: Grid::new([2, 2].into(), vec![19, 18, 17, 16])
1✔
1700
                    .unwrap()
1✔
1701
                    .into(),
1✔
1702
                properties: Default::default(),
1✔
1703
                cache_hint: CacheHint::default(),
1✔
1704
            },
1✔
1705
            RasterTile2D {
1✔
1706
                time: TimeInterval::new_unchecked(0, 2),
1✔
1707
                tile_position: [-1, 1].into(),
1✔
1708
                band: 0,
1✔
1709
                global_geo_transform: TestDefault::test_default(),
1✔
1710
                grid_array: Grid::new([2, 2].into(), vec![20, 21, 22, 23])
1✔
1711
                    .unwrap()
1✔
1712
                    .into(),
1✔
1713
                properties: Default::default(),
1✔
1714
                cache_hint: CacheHint::default(),
1✔
1715
            },
1✔
1716
            RasterTile2D {
1✔
1717
                time: TimeInterval::new_unchecked(0, 2),
1✔
1718
                tile_position: [-1, 1].into(),
1✔
1719
                band: 1,
1✔
1720
                global_geo_transform: TestDefault::test_default(),
1✔
1721
                grid_array: Grid::new([2, 2].into(), vec![32, 22, 21, 20])
1✔
1722
                    .unwrap()
1✔
1723
                    .into(),
1✔
1724
                properties: Default::default(),
1✔
1725
                cache_hint: CacheHint::default(),
1✔
1726
            },
1✔
1727
            RasterTile2D {
1✔
1728
                time: TimeInterval::new_unchecked(2, 10),
1✔
1729
                tile_position: [-1, 0].into(),
1✔
1730
                band: 0,
1✔
1731
                global_geo_transform: TestDefault::test_default(),
1✔
1732
                grid_array: Grid::new([2, 2].into(), vec![24, 25, 26, 27])
1✔
1733
                    .unwrap()
1✔
1734
                    .into(),
1✔
1735
                properties: Default::default(),
1✔
1736
                cache_hint: CacheHint::default(),
1✔
1737
            },
1✔
1738
            RasterTile2D {
1✔
1739
                time: TimeInterval::new_unchecked(2, 10),
1✔
1740
                tile_position: [-1, 0].into(),
1✔
1741
                band: 1,
1✔
1742
                global_geo_transform: TestDefault::test_default(),
1✔
1743
                grid_array: Grid::new([2, 2].into(), vec![27, 26, 25, 24])
1✔
1744
                    .unwrap()
1✔
1745
                    .into(),
1✔
1746
                properties: Default::default(),
1✔
1747
                cache_hint: CacheHint::default(),
1✔
1748
            },
1✔
1749
            RasterTile2D {
1✔
1750
                time: TimeInterval::new_unchecked(2, 10),
1✔
1751
                tile_position: [-1, 1].into(),
1✔
1752
                band: 0,
1✔
1753
                global_geo_transform: TestDefault::test_default(),
1✔
1754
                grid_array: Grid::new([2, 2].into(), vec![28, 29, 30, 31])
1✔
1755
                    .unwrap()
1✔
1756
                    .into(),
1✔
1757
                properties: Default::default(),
1✔
1758
                cache_hint: CacheHint::default(),
1✔
1759
            },
1✔
1760
            RasterTile2D {
1✔
1761
                time: TimeInterval::new_unchecked(2, 10),
1✔
1762
                tile_position: [-1, 1].into(),
1✔
1763
                band: 1,
1✔
1764
                global_geo_transform: TestDefault::test_default(),
1✔
1765
                grid_array: Grid::new([2, 2].into(), vec![31, 30, 39, 28])
1✔
1766
                    .unwrap()
1✔
1767
                    .into(),
1✔
1768
                properties: Default::default(),
1✔
1769
                cache_hint: CacheHint::default(),
1✔
1770
            },
1✔
1771
        ];
1✔
1772

1✔
1773
        let mrs1 = MockRasterSource {
1✔
1774
            params: MockRasterSourceParams {
1✔
1775
                data: data.clone(),
1✔
1776
                result_descriptor: RasterResultDescriptor {
1✔
1777
                    data_type: RasterDataType::U8,
1✔
1778
                    spatial_reference: SpatialReference::epsg_4326().into(),
1✔
1779
                    time: None,
1✔
1780
                    bbox: None,
1✔
1781
                    resolution: None,
1✔
1782
                    bands: vec![
1✔
1783
                        RasterBandDescriptor::new("mrs1 band1".to_string(), Measurement::Unitless),
1✔
1784
                        RasterBandDescriptor::new("mrs1 band2".to_string(), Measurement::Unitless),
1✔
1785
                        RasterBandDescriptor::new("mrs1 band3".to_string(), Measurement::Unitless),
1✔
1786
                    ]
1✔
1787
                    .try_into()
1✔
1788
                    .unwrap(),
1✔
1789
                },
1✔
1790
            },
1✔
1791
        }
1✔
1792
        .boxed();
1✔
1793

1✔
1794
        let mrs2 = MockRasterSource {
1✔
1795
            params: MockRasterSourceParams {
1✔
1796
                data: data2.clone(),
1✔
1797
                result_descriptor: RasterResultDescriptor {
1✔
1798
                    data_type: RasterDataType::U8,
1✔
1799
                    spatial_reference: SpatialReference::epsg_4326().into(),
1✔
1800
                    time: None,
1✔
1801
                    bbox: None,
1✔
1802
                    resolution: None,
1✔
1803
                    bands: vec![RasterBandDescriptor::new(
1✔
1804
                        "mrs2 band1".to_string(),
1✔
1805
                        Measurement::Unitless,
1✔
1806
                    )]
1✔
1807
                    .try_into()
1✔
1808
                    .unwrap(),
1✔
1809
                },
1✔
1810
            },
1✔
1811
        }
1✔
1812
        .boxed();
1✔
1813

1✔
1814
        let mrs3 = MockRasterSource {
1✔
1815
            params: MockRasterSourceParams {
1✔
1816
                data: data3.clone(),
1✔
1817
                result_descriptor: RasterResultDescriptor {
1✔
1818
                    data_type: RasterDataType::U8,
1✔
1819
                    spatial_reference: SpatialReference::epsg_4326().into(),
1✔
1820
                    time: None,
1✔
1821
                    bbox: None,
1✔
1822
                    resolution: None,
1✔
1823
                    bands: vec![
1✔
1824
                        RasterBandDescriptor::new("mrs3 band1".to_string(), Measurement::Unitless),
1✔
1825
                        RasterBandDescriptor::new("mrs3 band2".to_string(), Measurement::Unitless),
1✔
1826
                    ]
1✔
1827
                    .try_into()
1✔
1828
                    .unwrap(),
1✔
1829
                },
1✔
1830
            },
1✔
1831
        }
1✔
1832
        .boxed();
1✔
1833

1✔
1834
        let mut exe_ctx = MockExecutionContext::test_default();
1✔
1835
        exe_ctx.tiling_specification.tile_size_in_pixels = GridShape {
1✔
1836
            shape_array: [2, 2],
1✔
1837
        };
1✔
1838

1✔
1839
        let qp1 = mrs1
1✔
1840
            .initialize(WorkflowOperatorPath::initialize_root(), &exe_ctx)
1✔
1841
            .await
1✔
1842
            .unwrap()
1✔
1843
            .query_processor()
1✔
1844
            .unwrap()
1✔
1845
            .get_u8()
1✔
1846
            .unwrap();
1✔
1847

1✔
1848
        let qp2 = mrs2
1✔
1849
            .initialize(WorkflowOperatorPath::initialize_root(), &exe_ctx)
1✔
1850
            .await
1✔
1851
            .unwrap()
1✔
1852
            .query_processor()
1✔
1853
            .unwrap()
1✔
1854
            .get_u8()
1✔
1855
            .unwrap();
1✔
1856

1✔
1857
        let qp3 = mrs3
1✔
1858
            .initialize(WorkflowOperatorPath::initialize_root(), &exe_ctx)
1✔
1859
            .await
1✔
1860
            .unwrap()
1✔
1861
            .query_processor()
1✔
1862
            .unwrap()
1✔
1863
            .get_u8()
1✔
1864
            .unwrap();
1✔
1865

1✔
1866
        let query_ctx = MockQueryContext::test_default();
1✔
1867

1✔
1868
        let stacker = RasterStackerAdapter::new(
1✔
1869
            vec![
1✔
1870
                (
1✔
1871
                    QueryWrapper {
1✔
1872
                        p: &qp1,
1✔
1873
                        ctx: &query_ctx,
1✔
1874
                    },
1✔
1875
                    vec![0, 1, 2],
1✔
1876
                )
1✔
1877
                    .into(),
1✔
1878
                (
1✔
1879
                    QueryWrapper {
1✔
1880
                        p: &qp2,
1✔
1881
                        ctx: &query_ctx,
1✔
1882
                    },
1✔
1883
                    vec![0],
1✔
1884
                )
1✔
1885
                    .into(),
1✔
1886
                (
1✔
1887
                    QueryWrapper {
1✔
1888
                        p: &qp3,
1✔
1889
                        ctx: &query_ctx,
1✔
1890
                    },
1✔
1891
                    vec![0, 1],
1✔
1892
                )
1✔
1893
                    .into(),
1✔
1894
            ],
1✔
1895
            PartialQueryRect {
1✔
1896
                spatial_bounds: SpatialPartition2D::new_unchecked([0., 1.].into(), [3., 0.].into()),
1✔
1897
                time_interval: TimeInterval::new_unchecked(0, 10),
1✔
1898
                spatial_resolution: SpatialResolution::one(),
1✔
1899
            },
1✔
1900
        );
1✔
1901

1✔
1902
        let result = stacker.collect::<Vec<_>>().await;
1✔
1903
        let result = result.into_iter().collect::<Result<Vec<_>>>().unwrap();
1✔
1904

1✔
1905
        let expected: Vec<RasterTile2D<u8>> = vec![
1✔
1906
            // time slice 1
1✔
1907
            RasterTile2D {
1✔
1908
                time: TimeInterval::new_unchecked(0, 2),
1✔
1909
                tile_position: [-1, 0].into(),
1✔
1910
                band: 0,
1✔
1911
                global_geo_transform: TestDefault::test_default(),
1✔
1912
                grid_array: Grid::new([2, 2].into(), vec![0, 1, 2, 3]).unwrap().into(),
1✔
1913
                properties: Default::default(),
1✔
1914
                cache_hint: CacheHint::default(),
1✔
1915
            },
1✔
1916
            RasterTile2D {
1✔
1917
                time: TimeInterval::new_unchecked(0, 2),
1✔
1918
                tile_position: [-1, 0].into(),
1✔
1919
                band: 1,
1✔
1920
                global_geo_transform: TestDefault::test_default(),
1✔
1921
                grid_array: Grid::new([2, 2].into(), vec![3, 2, 1, 0]).unwrap().into(),
1✔
1922
                properties: Default::default(),
1✔
1923
                cache_hint: CacheHint::default(),
1✔
1924
            },
1✔
1925
            RasterTile2D {
1✔
1926
                time: TimeInterval::new_unchecked(0, 2),
1✔
1927
                tile_position: [-1, 0].into(),
1✔
1928
                band: 2,
1✔
1929
                global_geo_transform: TestDefault::test_default(),
1✔
1930
                grid_array: Grid::new([2, 2].into(), vec![223, 222, 221, 20])
1✔
1931
                    .unwrap()
1✔
1932
                    .into(),
1✔
1933
                properties: Default::default(),
1✔
1934
                cache_hint: CacheHint::default(),
1✔
1935
            },
1✔
1936
            RasterTile2D {
1✔
1937
                time: TimeInterval::new_unchecked(0, 2),
1✔
1938
                tile_position: [-1, 0].into(),
1✔
1939
                band: 3,
1✔
1940
                global_geo_transform: TestDefault::test_default(),
1✔
1941
                grid_array: Grid::new([2, 2].into(), vec![88, 77, 66, 55])
1✔
1942
                    .unwrap()
1✔
1943
                    .into(),
1✔
1944
                properties: Default::default(),
1✔
1945

1✔
1946
                cache_hint: CacheHint::default(),
1✔
1947
            },
1✔
1948
            RasterTile2D {
1✔
1949
                time: TimeInterval::new_unchecked(0, 2),
1✔
1950
                tile_position: [-1, 0].into(),
1✔
1951
                band: 4,
1✔
1952
                global_geo_transform: TestDefault::test_default(),
1✔
1953
                grid_array: Grid::new([2, 2].into(), vec![16, 17, 18, 19])
1✔
1954
                    .unwrap()
1✔
1955
                    .into(),
1✔
1956
                properties: Default::default(),
1✔
1957
                cache_hint: CacheHint::default(),
1✔
1958
            },
1✔
1959
            RasterTile2D {
1✔
1960
                time: TimeInterval::new_unchecked(0, 2),
1✔
1961
                tile_position: [-1, 0].into(),
1✔
1962
                band: 5,
1✔
1963
                global_geo_transform: TestDefault::test_default(),
1✔
1964
                grid_array: Grid::new([2, 2].into(), vec![19, 18, 17, 16])
1✔
1965
                    .unwrap()
1✔
1966
                    .into(),
1✔
1967
                properties: Default::default(),
1✔
1968
                cache_hint: CacheHint::default(),
1✔
1969
            },
1✔
1970
            RasterTile2D {
1✔
1971
                time: TimeInterval::new_unchecked(0, 2),
1✔
1972
                tile_position: [-1, 1].into(),
1✔
1973
                band: 0,
1✔
1974
                global_geo_transform: TestDefault::test_default(),
1✔
1975
                grid_array: Grid::new([2, 2].into(), vec![4, 5, 6, 7]).unwrap().into(),
1✔
1976
                properties: Default::default(),
1✔
1977
                cache_hint: CacheHint::default(),
1✔
1978
            },
1✔
1979
            RasterTile2D {
1✔
1980
                time: TimeInterval::new_unchecked(0, 2),
1✔
1981
                tile_position: [-1, 1].into(),
1✔
1982
                band: 1,
1✔
1983
                global_geo_transform: TestDefault::test_default(),
1✔
1984
                grid_array: Grid::new([2, 2].into(), vec![7, 6, 5, 4]).unwrap().into(),
1✔
1985
                properties: Default::default(),
1✔
1986
                cache_hint: CacheHint::default(),
1✔
1987
            },
1✔
1988
            RasterTile2D {
1✔
1989
                time: TimeInterval::new_unchecked(0, 2),
1✔
1990
                tile_position: [-1, 1].into(),
1✔
1991
                band: 2,
1✔
1992
                global_geo_transform: TestDefault::test_default(),
1✔
1993
                grid_array: Grid::new([2, 2].into(), vec![227, 226, 225, 224])
1✔
1994
                    .unwrap()
1✔
1995
                    .into(),
1✔
1996
                properties: Default::default(),
1✔
1997
                cache_hint: CacheHint::default(),
1✔
1998
            },
1✔
1999
            RasterTile2D {
1✔
2000
                time: TimeInterval::new_unchecked(0, 2),
1✔
2001
                tile_position: [-1, 1].into(),
1✔
2002
                band: 3,
1✔
2003
                global_geo_transform: TestDefault::test_default(),
1✔
2004
                grid_array: Grid::new([2, 2].into(), vec![87, 76, 65, 54])
1✔
2005
                    .unwrap()
1✔
2006
                    .into(),
1✔
2007
                properties: Default::default(),
1✔
2008
                cache_hint: CacheHint::default(),
1✔
2009
            },
1✔
2010
            RasterTile2D {
1✔
2011
                time: TimeInterval::new_unchecked(0, 2),
1✔
2012
                tile_position: [-1, 1].into(),
1✔
2013
                band: 4,
1✔
2014
                global_geo_transform: TestDefault::test_default(),
1✔
2015
                grid_array: Grid::new([2, 2].into(), vec![20, 21, 22, 23])
1✔
2016
                    .unwrap()
1✔
2017
                    .into(),
1✔
2018
                properties: Default::default(),
1✔
2019
                cache_hint: CacheHint::default(),
1✔
2020
            },
1✔
2021
            RasterTile2D {
1✔
2022
                time: TimeInterval::new_unchecked(0, 2),
1✔
2023
                tile_position: [-1, 1].into(),
1✔
2024
                band: 5,
1✔
2025
                global_geo_transform: TestDefault::test_default(),
1✔
2026
                grid_array: Grid::new([2, 2].into(), vec![32, 22, 21, 20])
1✔
2027
                    .unwrap()
1✔
2028
                    .into(),
1✔
2029
                properties: Default::default(),
1✔
2030
                cache_hint: CacheHint::default(),
1✔
2031
            },
1✔
2032
            // time slice 2
1✔
2033
            RasterTile2D {
1✔
2034
                time: TimeInterval::new_unchecked(2, 5),
1✔
2035
                tile_position: [-1, 0].into(),
1✔
2036
                band: 0,
1✔
2037
                global_geo_transform: TestDefault::test_default(),
1✔
2038
                grid_array: Grid::new([2, 2].into(), vec![0, 1, 2, 3]).unwrap().into(),
1✔
2039
                properties: Default::default(),
1✔
2040
                cache_hint: CacheHint::default(),
1✔
2041
            },
1✔
2042
            RasterTile2D {
1✔
2043
                time: TimeInterval::new_unchecked(2, 5),
1✔
2044
                tile_position: [-1, 0].into(),
1✔
2045
                band: 1,
1✔
2046
                global_geo_transform: TestDefault::test_default(),
1✔
2047
                grid_array: Grid::new([2, 2].into(), vec![3, 2, 1, 0]).unwrap().into(),
1✔
2048
                properties: Default::default(),
1✔
2049
                cache_hint: CacheHint::default(),
1✔
2050
            },
1✔
2051
            RasterTile2D {
1✔
2052
                time: TimeInterval::new_unchecked(2, 5),
1✔
2053
                tile_position: [-1, 0].into(),
1✔
2054
                band: 2,
1✔
2055
                global_geo_transform: TestDefault::test_default(),
1✔
2056
                grid_array: Grid::new([2, 2].into(), vec![223, 222, 221, 20])
1✔
2057
                    .unwrap()
1✔
2058
                    .into(),
1✔
2059
                properties: Default::default(),
1✔
2060
                cache_hint: CacheHint::default(),
1✔
2061
            },
1✔
2062
            RasterTile2D {
1✔
2063
                time: TimeInterval::new_unchecked(2, 5),
1✔
2064
                tile_position: [-1, 0].into(),
1✔
2065
                band: 3,
1✔
2066
                global_geo_transform: TestDefault::test_default(),
1✔
2067
                grid_array: Grid::new([2, 2].into(), vec![86, 75, 63, 51])
1✔
2068
                    .unwrap()
1✔
2069
                    .into(),
1✔
2070
                properties: Default::default(),
1✔
2071
                cache_hint: CacheHint::default(),
1✔
2072
            },
1✔
2073
            RasterTile2D {
1✔
2074
                time: TimeInterval::new_unchecked(2, 5),
1✔
2075
                tile_position: [-1, 0].into(),
1✔
2076
                band: 4,
1✔
2077
                global_geo_transform: TestDefault::test_default(),
1✔
2078
                grid_array: Grid::new([2, 2].into(), vec![24, 25, 26, 27])
1✔
2079
                    .unwrap()
1✔
2080
                    .into(),
1✔
2081
                properties: Default::default(),
1✔
2082
                cache_hint: CacheHint::default(),
1✔
2083
            },
1✔
2084
            RasterTile2D {
1✔
2085
                time: TimeInterval::new_unchecked(2, 5),
1✔
2086
                tile_position: [-1, 0].into(),
1✔
2087
                band: 5,
1✔
2088
                global_geo_transform: TestDefault::test_default(),
1✔
2089
                grid_array: Grid::new([2, 2].into(), vec![27, 26, 25, 24])
1✔
2090
                    .unwrap()
1✔
2091
                    .into(),
1✔
2092
                properties: Default::default(),
1✔
2093
                cache_hint: CacheHint::default(),
1✔
2094
            },
1✔
2095
            RasterTile2D {
1✔
2096
                time: TimeInterval::new_unchecked(2, 5),
1✔
2097
                tile_position: [-1, 1].into(),
1✔
2098
                band: 0,
1✔
2099
                global_geo_transform: TestDefault::test_default(),
1✔
2100
                grid_array: Grid::new([2, 2].into(), vec![4, 5, 6, 7]).unwrap().into(),
1✔
2101
                properties: Default::default(),
1✔
2102
                cache_hint: CacheHint::default(),
1✔
2103
            },
1✔
2104
            RasterTile2D {
1✔
2105
                time: TimeInterval::new_unchecked(2, 5),
1✔
2106
                tile_position: [-1, 1].into(),
1✔
2107
                band: 1,
1✔
2108
                global_geo_transform: TestDefault::test_default(),
1✔
2109
                grid_array: Grid::new([2, 2].into(), vec![7, 6, 5, 4]).unwrap().into(),
1✔
2110
                properties: Default::default(),
1✔
2111
                cache_hint: CacheHint::default(),
1✔
2112
            },
1✔
2113
            RasterTile2D {
1✔
2114
                time: TimeInterval::new_unchecked(2, 5),
1✔
2115
                tile_position: [-1, 1].into(),
1✔
2116
                band: 2,
1✔
2117
                global_geo_transform: TestDefault::test_default(),
1✔
2118
                grid_array: Grid::new([2, 2].into(), vec![227, 226, 225, 224])
1✔
2119
                    .unwrap()
1✔
2120
                    .into(),
1✔
2121
                properties: Default::default(),
1✔
2122
                cache_hint: CacheHint::default(),
1✔
2123
            },
1✔
2124
            RasterTile2D {
1✔
2125
                time: TimeInterval::new_unchecked(2, 5),
1✔
2126
                tile_position: [-1, 1].into(),
1✔
2127
                band: 3,
1✔
2128
                global_geo_transform: TestDefault::test_default(),
1✔
2129
                grid_array: Grid::new([2, 2].into(), vec![85, 74, 62, 50])
1✔
2130
                    .unwrap()
1✔
2131
                    .into(),
1✔
2132
                properties: Default::default(),
1✔
2133
                cache_hint: CacheHint::default(),
1✔
2134
            },
1✔
2135
            RasterTile2D {
1✔
2136
                time: TimeInterval::new_unchecked(2, 5),
1✔
2137
                tile_position: [-1, 1].into(),
1✔
2138
                band: 4,
1✔
2139
                global_geo_transform: TestDefault::test_default(),
1✔
2140
                grid_array: Grid::new([2, 2].into(), vec![28, 29, 30, 31])
1✔
2141
                    .unwrap()
1✔
2142
                    .into(),
1✔
2143
                properties: Default::default(),
1✔
2144
                cache_hint: CacheHint::default(),
1✔
2145
            },
1✔
2146
            RasterTile2D {
1✔
2147
                time: TimeInterval::new_unchecked(2, 5),
1✔
2148
                tile_position: [-1, 1].into(),
1✔
2149
                band: 5,
1✔
2150
                global_geo_transform: TestDefault::test_default(),
1✔
2151
                grid_array: Grid::new([2, 2].into(), vec![31, 30, 39, 28])
1✔
2152
                    .unwrap()
1✔
2153
                    .into(),
1✔
2154
                properties: Default::default(),
1✔
2155
                cache_hint: CacheHint::default(),
1✔
2156
            },
1✔
2157
            // time slice 3
1✔
2158
            RasterTile2D {
1✔
2159
                time: TimeInterval::new_unchecked(5, 10),
1✔
2160
                tile_position: [-1, 0].into(),
1✔
2161
                band: 0,
1✔
2162
                global_geo_transform: TestDefault::test_default(),
1✔
2163
                grid_array: Grid::new([2, 2].into(), vec![8, 9, 10, 11]).unwrap().into(),
1✔
2164
                properties: Default::default(),
1✔
2165
                cache_hint: CacheHint::default(),
1✔
2166
            },
1✔
2167
            RasterTile2D {
1✔
2168
                time: TimeInterval::new_unchecked(5, 10),
1✔
2169
                tile_position: [-1, 0].into(),
1✔
2170
                band: 1,
1✔
2171
                global_geo_transform: TestDefault::test_default(),
1✔
2172
                grid_array: Grid::new([2, 2].into(), vec![11, 10, 9, 8]).unwrap().into(),
1✔
2173
                properties: Default::default(),
1✔
2174
                cache_hint: CacheHint::default(),
1✔
2175
            },
1✔
2176
            RasterTile2D {
1✔
2177
                time: TimeInterval::new_unchecked(5, 10),
1✔
2178
                tile_position: [-1, 0].into(),
1✔
2179
                band: 2,
1✔
2180
                global_geo_transform: TestDefault::test_default(),
1✔
2181
                grid_array: Grid::new([2, 2].into(), vec![211, 210, 29, 28])
1✔
2182
                    .unwrap()
1✔
2183
                    .into(),
1✔
2184
                properties: Default::default(),
1✔
2185
                cache_hint: CacheHint::default(),
1✔
2186
            },
1✔
2187
            RasterTile2D {
1✔
2188
                time: TimeInterval::new_unchecked(5, 10),
1✔
2189
                tile_position: [-1, 0].into(),
1✔
2190
                band: 3,
1✔
2191
                global_geo_transform: TestDefault::test_default(),
1✔
2192
                grid_array: Grid::new([2, 2].into(), vec![86, 75, 63, 51])
1✔
2193
                    .unwrap()
1✔
2194
                    .into(),
1✔
2195
                properties: Default::default(),
1✔
2196
                cache_hint: CacheHint::default(),
1✔
2197
            },
1✔
2198
            RasterTile2D {
1✔
2199
                time: TimeInterval::new_unchecked(5, 10),
1✔
2200
                tile_position: [-1, 0].into(),
1✔
2201
                band: 4,
1✔
2202
                global_geo_transform: TestDefault::test_default(),
1✔
2203
                grid_array: Grid::new([2, 2].into(), vec![24, 25, 26, 27])
1✔
2204
                    .unwrap()
1✔
2205
                    .into(),
1✔
2206
                properties: Default::default(),
1✔
2207
                cache_hint: CacheHint::default(),
1✔
2208
            },
1✔
2209
            RasterTile2D {
1✔
2210
                time: TimeInterval::new_unchecked(5, 10),
1✔
2211
                tile_position: [-1, 0].into(),
1✔
2212
                band: 5,
1✔
2213
                global_geo_transform: TestDefault::test_default(),
1✔
2214
                grid_array: Grid::new([2, 2].into(), vec![27, 26, 25, 24])
1✔
2215
                    .unwrap()
1✔
2216
                    .into(),
1✔
2217
                properties: Default::default(),
1✔
2218
                cache_hint: CacheHint::default(),
1✔
2219
            },
1✔
2220
            RasterTile2D {
1✔
2221
                time: TimeInterval::new_unchecked(5, 10),
1✔
2222
                tile_position: [-1, 1].into(),
1✔
2223
                band: 0,
1✔
2224
                global_geo_transform: TestDefault::test_default(),
1✔
2225
                grid_array: Grid::new([2, 2].into(), vec![12, 13, 14, 15])
1✔
2226
                    .unwrap()
1✔
2227
                    .into(),
1✔
2228
                properties: Default::default(),
1✔
2229
                cache_hint: CacheHint::default(),
1✔
2230
            },
1✔
2231
            RasterTile2D {
1✔
2232
                time: TimeInterval::new_unchecked(5, 10),
1✔
2233
                tile_position: [-1, 1].into(),
1✔
2234
                band: 1,
1✔
2235
                global_geo_transform: TestDefault::test_default(),
1✔
2236
                grid_array: Grid::new([2, 2].into(), vec![15, 14, 13, 12])
1✔
2237
                    .unwrap()
1✔
2238
                    .into(),
1✔
2239
                properties: Default::default(),
1✔
2240
                cache_hint: CacheHint::default(),
1✔
2241
            },
1✔
2242
            RasterTile2D {
1✔
2243
                time: TimeInterval::new_unchecked(5, 10),
1✔
2244
                tile_position: [-1, 1].into(),
1✔
2245
                band: 2,
1✔
2246
                global_geo_transform: TestDefault::test_default(),
1✔
2247
                grid_array: Grid::new([2, 2].into(), vec![215, 214, 213, 212])
1✔
2248
                    .unwrap()
1✔
2249
                    .into(),
1✔
2250
                properties: Default::default(),
1✔
2251
                cache_hint: CacheHint::default(),
1✔
2252
            },
1✔
2253
            RasterTile2D {
1✔
2254
                time: TimeInterval::new_unchecked(5, 10),
1✔
2255
                tile_position: [-1, 1].into(),
1✔
2256
                band: 3,
1✔
2257
                global_geo_transform: TestDefault::test_default(),
1✔
2258
                grid_array: Grid::new([2, 2].into(), vec![85, 74, 62, 50])
1✔
2259
                    .unwrap()
1✔
2260
                    .into(),
1✔
2261
                properties: Default::default(),
1✔
2262
                cache_hint: CacheHint::default(),
1✔
2263
            },
1✔
2264
            RasterTile2D {
1✔
2265
                time: TimeInterval::new_unchecked(5, 10),
1✔
2266
                tile_position: [-1, 1].into(),
1✔
2267
                band: 4,
1✔
2268
                global_geo_transform: TestDefault::test_default(),
1✔
2269
                grid_array: Grid::new([2, 2].into(), vec![28, 29, 30, 31])
1✔
2270
                    .unwrap()
1✔
2271
                    .into(),
1✔
2272
                properties: Default::default(),
1✔
2273
                cache_hint: CacheHint::default(),
1✔
2274
            },
1✔
2275
            RasterTile2D {
1✔
2276
                time: TimeInterval::new_unchecked(5, 10),
1✔
2277
                tile_position: [-1, 1].into(),
1✔
2278
                band: 5,
1✔
2279
                global_geo_transform: TestDefault::test_default(),
1✔
2280
                grid_array: Grid::new([2, 2].into(), vec![31, 30, 39, 28])
1✔
2281
                    .unwrap()
1✔
2282
                    .into(),
1✔
2283
                properties: Default::default(),
1✔
2284
                cache_hint: CacheHint::default(),
1✔
2285
            },
1✔
2286
        ];
1✔
2287

1✔
2288
        assert!(expected.tiles_equal_ignoring_cache_hint(&result));
1✔
2289
    }
1✔
2290
}
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

© 2026 Coveralls, Inc