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

vortex-data / vortex / 17041372319

18 Aug 2025 01:01PM UTC coverage: 88.047% (+0.1%) from 87.913%
17041372319

Pull #4177

github

web-flow
Merge 74cbbea45 into abfc8534c
Pull Request #4177: feat: ArrayOperations infallible

1187 of 1273 new or added lines in 146 files covered. (93.24%)

18 existing lines in 12 files now uncovered.

56492 of 64161 relevant lines covered (88.05%)

622803.37 hits per line

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

93.46
/vortex-array/src/compute/conformance/cast.rs
1
// SPDX-License-Identifier: Apache-2.0
2
// SPDX-FileCopyrightText: Copyright the Vortex contributors
3

4
use vortex_dtype::{DType, Nullability, PType};
5
use vortex_error::VortexUnwrap;
6

7
use crate::Array;
8
use crate::compute::cast;
9

10
/// Test conformance of the cast compute function for an array.
11
///
12
/// This function tests various casting scenarios including:
13
/// - Casting between numeric types (widening and narrowing)
14
/// - Casting between signed and unsigned types
15
/// - Casting between integral and floating-point types
16
/// - Casting with nullability changes
17
/// - Casting between string types (Utf8/Binary)
18
/// - Edge cases like overflow behavior
19
pub fn test_cast_conformance(array: &dyn Array) {
2,760✔
20
    let dtype = array.dtype();
2,760✔
21

22
    // Always test identity cast and nullability changes
23
    test_cast_identity(array);
2,760✔
24

25
    // Test AllValid to NonNullable and back if applicable
26
    test_cast_allvalid_to_nonnullable_and_back(array);
2,760✔
27

28
    // Test based on the specific DType
29
    match dtype {
2,760✔
30
        DType::Null => test_cast_from_null(array),
5✔
31
        DType::Bool(nullability) => test_cast_from_bool(array, *nullability),
240✔
32
        DType::Primitive(ptype, nullability) => {
2,054✔
33
            test_cast_nullability_changes_primitive(array, *ptype, *nullability);
2,054✔
34
            match ptype {
2,054✔
35
                PType::U8 => test_cast_from_u8(array),
161✔
36
                PType::U16 => test_cast_from_u16(array),
79✔
37
                PType::U32 => test_cast_from_u32(array),
200✔
38
                PType::U64 => test_cast_from_u64(array),
157✔
39
                PType::I8 => test_cast_from_i8(array),
1✔
40
                PType::I16 => test_cast_from_i16(array),
79✔
41
                PType::I32 => test_cast_from_i32(array),
591✔
42
                PType::I64 => test_cast_from_i64(array),
118✔
43
                PType::F16 => test_cast_from_f16(array),
×
44
                PType::F32 => test_cast_from_f32(array),
394✔
45
                PType::F64 => test_cast_from_f64(array),
274✔
46
            }
47
        }
48
        DType::Decimal(_, nullability) => test_cast_from_decimal(array, *nullability),
199✔
49
        DType::Utf8(nullability) => test_cast_from_utf8(array, *nullability),
125✔
50
        DType::Binary(nullability) => test_cast_from_binary(array, *nullability),
5✔
51
        DType::Struct(_, nullability) => test_cast_from_struct(array, *nullability),
5✔
52
        DType::List(_, nullability) => test_cast_from_list(array, *nullability),
6✔
53
        DType::Extension(_) => test_cast_from_extension(array),
121✔
54
    }
55
}
2,760✔
56

57
fn test_cast_identity(array: &dyn Array) {
2,760✔
58
    // Casting to the same type should be a no-op
59
    let result = cast(array, array.dtype()).vortex_unwrap();
2,760✔
60
    assert_eq!(result.len(), array.len());
2,760✔
61
    assert_eq!(result.dtype(), array.dtype());
2,760✔
62

63
    // Verify values are unchanged
64
    for i in 0..array.len().min(10) {
13,706✔
65
        assert_eq!(array.scalar_at(i), result.scalar_at(i),);
13,706✔
66
    }
67
}
2,760✔
68

69
fn test_cast_from_null(array: &dyn Array) {
5✔
70
    // Null can be cast to itself
71
    let result = cast(array, &DType::Null).vortex_unwrap();
5✔
72
    assert_eq!(result.len(), array.len());
5✔
73
    assert_eq!(result.dtype(), &DType::Null);
5✔
74

75
    // Null can also be cast to any nullable type
76
    let nullable_types = vec![
5✔
77
        DType::Bool(Nullability::Nullable),
5✔
78
        DType::Primitive(PType::I32, Nullability::Nullable),
5✔
79
        DType::Primitive(PType::F64, Nullability::Nullable),
5✔
80
        DType::Utf8(Nullability::Nullable),
5✔
81
        DType::Binary(Nullability::Nullable),
5✔
82
    ];
83

84
    for dtype in nullable_types {
30✔
85
        let result = cast(array, &dtype).vortex_unwrap();
25✔
86
        assert_eq!(result.len(), array.len());
25✔
87
        assert_eq!(result.dtype(), &dtype);
25✔
88

89
        // Verify all values are null
90
        for i in 0..array.len().min(10) {
105✔
91
            assert!(result.scalar_at(i).is_null());
105✔
92
        }
93
    }
94

95
    // Casting to non-nullable types should fail
96
    let non_nullable_types = vec![
5✔
97
        DType::Bool(Nullability::NonNullable),
5✔
98
        DType::Primitive(PType::I32, Nullability::NonNullable),
5✔
99
    ];
100

101
    for dtype in non_nullable_types {
15✔
102
        assert!(cast(array, &dtype).is_err());
10✔
103
    }
104
}
5✔
105

106
fn test_cast_from_bool(array: &dyn Array, nullability: Nullability) {
240✔
107
    // Test nullability changes
108
    test_cast_nullability_changes(array, &DType::Bool(Nullability::Nullable));
240✔
109
    if nullability == Nullability::Nullable {
240✔
110
        // Try casting to non-nullable (may fail if nulls present)
196✔
111
        let _ = cast(array, &DType::Bool(Nullability::NonNullable));
196✔
112
    }
196✔
113

114
    // Test bool to numeric casts (true -> 1, false -> 0)
115
    test_cast_to_primitive(array, PType::U8);
240✔
116
    test_cast_to_primitive(array, PType::I32);
240✔
117
    test_cast_to_primitive(array, PType::F32);
240✔
118
}
240✔
119

120
fn test_cast_from_decimal(array: &dyn Array, nullability: Nullability) {
199✔
121
    // Test nullability changes for the same decimal type
122
    if let DType::Decimal(decimal_type, _) = array.dtype() {
199✔
123
        test_cast_nullability_changes(array, &DType::Decimal(*decimal_type, Nullability::Nullable));
199✔
124
        if nullability == Nullability::Nullable {
199✔
125
            // Try casting to non-nullable (may fail if nulls present)
40✔
126
            let _ = cast(
40✔
127
                array,
40✔
128
                &DType::Decimal(*decimal_type, Nullability::NonNullable),
40✔
129
            );
40✔
130
        }
159✔
131
    }
×
132
}
199✔
133

134
fn test_cast_from_utf8(array: &dyn Array, nullability: Nullability) {
125✔
135
    // Test nullability changes
136
    test_cast_nullability_changes(array, &DType::Utf8(Nullability::Nullable));
125✔
137
    if nullability == Nullability::Nullable {
125✔
138
        // Try casting to non-nullable (may fail if nulls present)
42✔
139
        let _ = cast(array, &DType::Utf8(Nullability::NonNullable));
42✔
140
    }
83✔
141

142
    // UTF-8 strings can potentially be cast to Binary
143
    test_cast_to_type_safe(array, &DType::Binary(nullability));
125✔
144
}
125✔
145

146
fn test_cast_from_binary(array: &dyn Array, nullability: Nullability) {
5✔
147
    // Test nullability changes
148
    test_cast_nullability_changes(array, &DType::Binary(Nullability::Nullable));
5✔
149
    if nullability == Nullability::Nullable {
5✔
150
        // Try casting to non-nullable (may fail if nulls present)
3✔
151
        let _ = cast(array, &DType::Binary(Nullability::NonNullable));
3✔
152
    }
3✔
153

154
    // Binary might be castable to UTF-8 if it contains valid UTF-8
155
    test_cast_to_type_safe(array, &DType::Utf8(nullability));
5✔
156
}
5✔
157

158
fn test_cast_from_struct(array: &dyn Array, nullability: Nullability) {
5✔
159
    // Test nullability changes for the same struct type
160
    if let DType::Struct(fields, _) = array.dtype() {
5✔
161
        test_cast_nullability_changes(array, &DType::Struct(fields.clone(), Nullability::Nullable));
5✔
162
        if nullability == Nullability::Nullable {
5✔
163
            // Try casting to non-nullable (may fail if nulls present)
1✔
164
            let _ = cast(
1✔
165
                array,
1✔
166
                &DType::Struct(fields.clone(), Nullability::NonNullable),
1✔
167
            );
1✔
168
        }
4✔
169
    }
×
170
}
5✔
171

172
fn test_cast_from_list(array: &dyn Array, nullability: Nullability) {
6✔
173
    // Test nullability changes for the same list type
174
    if let DType::List(element_type, _) = array.dtype() {
6✔
175
        test_cast_nullability_changes(
6✔
176
            array,
6✔
177
            &DType::List(element_type.clone(), Nullability::Nullable),
6✔
178
        );
179
        if nullability == Nullability::Nullable {
6✔
180
            // Try casting to non-nullable (may fail if nulls present)
1✔
181
            let _ = cast(
1✔
182
                array,
1✔
183
                &DType::List(element_type.clone(), Nullability::NonNullable),
1✔
184
            );
1✔
185
        }
5✔
186
    }
×
187
}
6✔
188

189
fn test_cast_from_extension(array: &dyn Array) {
121✔
190
    // Extension types typically only cast to themselves
191
    // The specific casting rules depend on the extension type
192
    if let DType::Extension(ext_dtype) = array.dtype() {
121✔
193
        let result = cast(array, &DType::Extension(ext_dtype.clone())).vortex_unwrap();
121✔
194
        assert_eq!(result.len(), array.len());
121✔
195
        assert_eq!(result.dtype(), array.dtype());
121✔
196
    }
×
197
}
121✔
198

199
fn test_cast_allvalid_to_nonnullable_and_back(array: &dyn Array) {
2,760✔
200
    // Skip if array is null type (special case)
201
    if array.dtype() == &DType::Null {
2,760✔
202
        return;
5✔
203
    }
2,755✔
204

205
    // Only test if array has no nulls
206
    if let Ok(null_count) = array.invalid_count()
2,755✔
207
        && null_count == 0
2,755✔
208
    {
209
        // Test casting to NonNullable if currently Nullable
210
        if array.dtype().nullability() == Nullability::Nullable {
2,232✔
211
            let non_nullable_dtype = array.dtype().with_nullability(Nullability::NonNullable);
118✔
212

213
            // Cast to NonNullable
214
            if let Ok(non_nullable) = cast(array, &non_nullable_dtype) {
118✔
215
                assert_eq!(non_nullable.dtype(), &non_nullable_dtype);
118✔
216
                assert_eq!(non_nullable.len(), array.len());
118✔
217

218
                // Cast back to Nullable
219
                let nullable_dtype = array.dtype().with_nullability(Nullability::Nullable);
118✔
220
                let back_to_nullable = cast(&non_nullable, &nullable_dtype).vortex_unwrap();
118✔
221
                assert_eq!(back_to_nullable.dtype(), &nullable_dtype);
118✔
222
                assert_eq!(back_to_nullable.len(), array.len());
118✔
223

224
                // Verify values are unchanged
225
                for i in 0..array.len().min(10) {
276✔
226
                    assert_eq!(array.scalar_at(i), back_to_nullable.scalar_at(i));
276✔
227
                }
228
            }
×
229
        }
230
        // Test casting to Nullable if currently NonNullable
231
        else if array.dtype().nullability() == Nullability::NonNullable {
2,114✔
232
            let nullable_dtype = array.dtype().with_nullability(Nullability::Nullable);
2,114✔
233

234
            // Cast to Nullable
235
            let nullable = cast(array, &nullable_dtype).vortex_unwrap();
2,114✔
236
            assert_eq!(nullable.dtype(), &nullable_dtype);
2,114✔
237
            assert_eq!(nullable.len(), array.len());
2,114✔
238

239
            // Cast back to NonNullable
240
            let non_nullable_dtype = array.dtype().with_nullability(Nullability::NonNullable);
2,114✔
241
            let back_to_non_nullable = cast(&nullable, &non_nullable_dtype).vortex_unwrap();
2,114✔
242
            assert_eq!(back_to_non_nullable.dtype(), &non_nullable_dtype);
2,114✔
243
            assert_eq!(back_to_non_nullable.len(), array.len());
2,114✔
244

245
            // Verify values are unchanged
246
            for i in 0..array.len().min(10) {
10,775✔
247
                assert_eq!(array.scalar_at(i), back_to_non_nullable.scalar_at(i));
10,775✔
248
            }
249
        }
×
250
    }
523✔
251
}
2,760✔
252

253
fn test_cast_nullability_changes(array: &dyn Array, nullable_version: &DType) {
580✔
254
    // Test casting to nullable version
255
    if array.dtype().nullability() == Nullability::NonNullable {
580✔
256
        let result = cast(array, nullable_version).vortex_unwrap();
297✔
257
        assert_eq!(result.len(), array.len());
297✔
258
        assert_eq!(result.dtype(), nullable_version);
297✔
259

260
        // IMPORTANT: Nullability casting should preserve the encoding
261
        assert_eq!(
297✔
262
            result.encoding().id(),
297✔
263
            array.encoding().id(),
297✔
264
            "Nullability cast should preserve encoding"
×
265
        );
266

267
        // Values should be unchanged
268
        for i in 0..array.len().min(10) {
1,195✔
269
            assert_eq!(array.scalar_at(i), result.scalar_at(i),);
1,195✔
270
        }
271
    }
283✔
272
}
580✔
273

274
fn test_cast_nullability_changes_primitive(
2,054✔
275
    array: &dyn Array,
2,054✔
276
    ptype: PType,
2,054✔
277
    nullability: Nullability,
2,054✔
278
) {
2,054✔
279
    // Test casting to nullable version
280
    if nullability == Nullability::NonNullable {
2,054✔
281
        let nullable_dtype = DType::Primitive(ptype, Nullability::Nullable);
1,737✔
282
        let result = cast(array, &nullable_dtype).vortex_unwrap();
1,737✔
283
        assert_eq!(result.len(), array.len());
1,737✔
284
        assert_eq!(result.dtype(), &nullable_dtype);
1,737✔
285

286
        // IMPORTANT: Nullability casting should preserve the encoding
287
        assert_eq!(
1,737✔
288
            result.encoding().id(),
1,737✔
289
            array.encoding().id(),
1,737✔
290
            "Nullability cast should preserve encoding"
×
291
        );
292

293
        // Values should be unchanged
294
        for i in 0..array.len().min(10) {
9,336✔
295
            assert_eq!(array.scalar_at(i), result.scalar_at(i),);
9,336✔
296
        }
297
    }
317✔
298

299
    // Test casting from nullable to non-nullable (only if no nulls present)
300
    if nullability == Nullability::Nullable {
2,054✔
301
        // Try to cast to non-nullable and see if it succeeds
302
        let non_nullable_dtype = DType::Primitive(ptype, Nullability::NonNullable);
317✔
303
        if let Ok(result) = cast(array, &non_nullable_dtype) {
317✔
304
            assert_eq!(result.len(), array.len());
×
305
            assert_eq!(result.dtype(), &non_nullable_dtype);
×
306

307
            // IMPORTANT: Nullability casting should preserve the encoding
308
            assert_eq!(
×
309
                result.encoding().id(),
×
310
                array.encoding().id(),
×
311
                "Nullability cast should preserve encoding"
×
312
            );
313

314
            // Values should be unchanged
315
            for i in 0..array.len().min(10) {
×
NEW
316
                assert_eq!(array.scalar_at(i), result.scalar_at(i),);
×
317
            }
318
        }
317✔
319
    }
1,737✔
320
}
2,054✔
321

322
fn test_cast_from_u8(array: &dyn Array) {
161✔
323
    // Test widening casts
324
    test_cast_to_primitive(array, PType::U16);
161✔
325
    test_cast_to_primitive(array, PType::U32);
161✔
326
    test_cast_to_primitive(array, PType::U64);
161✔
327
    test_cast_to_primitive(array, PType::I16);
161✔
328
    test_cast_to_primitive(array, PType::I32);
161✔
329
    test_cast_to_primitive(array, PType::I64);
161✔
330
    test_cast_to_primitive(array, PType::F32);
161✔
331
    test_cast_to_primitive(array, PType::F64);
161✔
332

333
    // Test same-width cast
334
    test_cast_to_primitive(array, PType::I8);
161✔
335
}
161✔
336

337
fn test_cast_from_u16(array: &dyn Array) {
79✔
338
    // Test narrowing cast
339
    test_cast_to_primitive(array, PType::U8);
79✔
340

341
    // Test widening casts
342
    test_cast_to_primitive(array, PType::U32);
79✔
343
    test_cast_to_primitive(array, PType::U64);
79✔
344
    test_cast_to_primitive(array, PType::I32);
79✔
345
    test_cast_to_primitive(array, PType::I64);
79✔
346
    test_cast_to_primitive(array, PType::F32);
79✔
347
    test_cast_to_primitive(array, PType::F64);
79✔
348

349
    // Test same-width cast
350
    test_cast_to_primitive(array, PType::I16);
79✔
351
}
79✔
352

353
fn test_cast_from_u32(array: &dyn Array) {
200✔
354
    // Test narrowing casts
355
    test_cast_to_primitive(array, PType::U8);
200✔
356
    test_cast_to_primitive(array, PType::U16);
200✔
357
    test_cast_to_primitive(array, PType::I8);
200✔
358
    test_cast_to_primitive(array, PType::I16);
200✔
359

360
    // Test widening casts
361
    test_cast_to_primitive(array, PType::U64);
200✔
362
    test_cast_to_primitive(array, PType::I64);
200✔
363
    test_cast_to_primitive(array, PType::F64);
200✔
364

365
    // Test same-width casts
366
    test_cast_to_primitive(array, PType::I32);
200✔
367
    test_cast_to_primitive(array, PType::F32);
200✔
368
}
200✔
369

370
fn test_cast_from_u64(array: &dyn Array) {
157✔
371
    // Test narrowing casts
372
    test_cast_to_primitive(array, PType::U8);
157✔
373
    test_cast_to_primitive(array, PType::U16);
157✔
374
    test_cast_to_primitive(array, PType::U32);
157✔
375
    test_cast_to_primitive(array, PType::I8);
157✔
376
    test_cast_to_primitive(array, PType::I16);
157✔
377
    test_cast_to_primitive(array, PType::I32);
157✔
378
    test_cast_to_primitive(array, PType::F32);
157✔
379

380
    // Test same-width casts
381
    test_cast_to_primitive(array, PType::I64);
157✔
382
    test_cast_to_primitive(array, PType::F64);
157✔
383
}
157✔
384

385
fn test_cast_from_i8(array: &dyn Array) {
1✔
386
    // Test widening casts
387
    test_cast_to_primitive(array, PType::I16);
1✔
388
    test_cast_to_primitive(array, PType::I32);
1✔
389
    test_cast_to_primitive(array, PType::I64);
1✔
390
    test_cast_to_primitive(array, PType::F32);
1✔
391
    test_cast_to_primitive(array, PType::F64);
1✔
392

393
    // Test same-width cast (may fail for negative values)
394
    test_cast_to_primitive(array, PType::U8);
1✔
395
}
1✔
396

397
fn test_cast_from_i16(array: &dyn Array) {
79✔
398
    // Test narrowing cast
399
    test_cast_to_primitive(array, PType::I8);
79✔
400

401
    // Test widening casts
402
    test_cast_to_primitive(array, PType::I32);
79✔
403
    test_cast_to_primitive(array, PType::I64);
79✔
404
    test_cast_to_primitive(array, PType::F32);
79✔
405
    test_cast_to_primitive(array, PType::F64);
79✔
406

407
    // Test same-width cast (may fail for negative values)
408
    test_cast_to_primitive(array, PType::U16);
79✔
409
}
79✔
410

411
fn test_cast_from_i32(array: &dyn Array) {
591✔
412
    // Test narrowing casts
413
    test_cast_to_primitive(array, PType::I8);
591✔
414
    test_cast_to_primitive(array, PType::I16);
591✔
415

416
    // Test widening casts
417
    test_cast_to_primitive(array, PType::I64);
591✔
418
    test_cast_to_primitive(array, PType::F64);
591✔
419

420
    // Test same-width casts
421
    test_cast_to_primitive(array, PType::F32);
591✔
422
    test_cast_to_primitive(array, PType::U32);
591✔
423
}
591✔
424

425
fn test_cast_from_i64(array: &dyn Array) {
118✔
426
    // Test narrowing casts
427
    test_cast_to_primitive(array, PType::I8);
118✔
428
    test_cast_to_primitive(array, PType::I16);
118✔
429
    test_cast_to_primitive(array, PType::I32);
118✔
430
    test_cast_to_primitive(array, PType::F32);
118✔
431

432
    // Test same-width cast
433
    test_cast_to_primitive(array, PType::F64);
118✔
434
    test_cast_to_primitive(array, PType::U64);
118✔
435
}
118✔
436

437
fn test_cast_from_f16(array: &dyn Array) {
×
438
    // Test casts to other float types
439
    test_cast_to_primitive(array, PType::F32);
×
440
    test_cast_to_primitive(array, PType::F64);
×
441
}
×
442

443
fn test_cast_from_f32(array: &dyn Array) {
394✔
444
    // Test narrowing cast
445
    test_cast_to_primitive(array, PType::F16);
394✔
446

447
    // Test widening cast
448
    test_cast_to_primitive(array, PType::F64);
394✔
449

450
    // Test casts to integer types (truncation)
451
    test_cast_to_integral_types(array);
394✔
452
}
394✔
453

454
fn test_cast_from_f64(array: &dyn Array) {
274✔
455
    // Test narrowing casts
456
    test_cast_to_primitive(array, PType::F16);
274✔
457
    test_cast_to_primitive(array, PType::F32);
274✔
458

459
    // Test casts to integer types (truncation)
460
    test_cast_to_integral_types(array);
274✔
461
}
274✔
462

463
fn test_cast_to_integral_types(array: &dyn Array) {
668✔
464
    // Test casting to all integral types
465
    // Some may fail due to out-of-range values
466
    test_cast_to_primitive(array, PType::I8);
668✔
467
    test_cast_to_primitive(array, PType::U8);
668✔
468
    test_cast_to_primitive(array, PType::I16);
668✔
469
    test_cast_to_primitive(array, PType::U16);
668✔
470
    test_cast_to_primitive(array, PType::I32);
668✔
471
    test_cast_to_primitive(array, PType::U32);
668✔
472
    test_cast_to_primitive(array, PType::I64);
668✔
473
    test_cast_to_primitive(array, PType::U64);
668✔
474
}
668✔
475

476
fn test_cast_to_primitive(array: &dyn Array, target_ptype: PType) {
17,428✔
477
    let target_dtype = DType::Primitive(target_ptype, array.dtype().nullability());
17,428✔
478
    test_cast_to_type_safe(array, &target_dtype);
17,428✔
479
}
17,428✔
480

481
fn test_cast_to_type_safe(array: &dyn Array, target_dtype: &DType) {
17,558✔
482
    // Attempt the cast
483
    let result = match cast(array, target_dtype) {
17,558✔
484
        Ok(r) => r,
14,864✔
485
        Err(_) => {
486
            // Some casts may fail (e.g., negative to unsigned, out-of-range values)
487
            // This is expected behavior
488
            return;
2,694✔
489
        }
490
    };
491

492
    assert_eq!(result.len(), array.len());
14,864✔
493
    assert_eq!(result.dtype(), target_dtype);
14,864✔
494

495
    // For valid casts, verify the values are correctly converted
496
    // We verify up to the first 10 values (or all if less than 10)
497
    for i in 0..array.len().min(10) {
79,893✔
498
        let original = array.scalar_at(i);
79,893✔
499
        let casted = result.scalar_at(i);
79,893✔
500

501
        // For nullability-only changes, values should be identical
502
        if array.dtype().eq_ignore_nullability(target_dtype) {
79,893✔
503
            assert_eq!(
×
504
                original, casted,
505
                "Value at index {i} changed during nullability cast"
×
506
            );
507
        } else {
508
            // For type conversions, at least verify we can retrieve the values
509
            // and that null values remain null
510
            if original.is_null() {
79,893✔
511
                assert!(
5,458✔
512
                    casted.is_null(),
5,458✔
513
                    "Null value at index {i} became non-null after cast"
×
514
                );
515
            } else {
516
                assert!(
74,435✔
517
                    !casted.is_null(),
74,435✔
518
                    "Non-null value at index {i} became null after cast"
×
519
                );
520
            }
521
        }
522
    }
523
}
17,558✔
524

525
#[cfg(test)]
526
mod tests {
527
    use vortex_buffer::buffer;
528
    use vortex_dtype::{DType, FieldNames, Nullability};
529

530
    use super::*;
531
    use crate::IntoArray;
532
    use crate::arrays::{
533
        BoolArray, ListArray, NullArray, PrimitiveArray, StructArray, VarBinArray,
534
    };
535

536
    #[test]
537
    fn test_cast_conformance_u32() {
1✔
538
        let array = buffer![0u32, 100, 200, 65535, 1000000].into_array();
1✔
539
        test_cast_conformance(array.as_ref());
1✔
540
    }
1✔
541

542
    #[test]
543
    fn test_cast_conformance_i32() {
1✔
544
        let array = buffer![-100i32, -1, 0, 1, 100].into_array();
1✔
545
        test_cast_conformance(array.as_ref());
1✔
546
    }
1✔
547

548
    #[test]
549
    fn test_cast_conformance_f32() {
1✔
550
        let array = buffer![0.0f32, 1.5, -2.5, 100.0, 1e6].into_array();
1✔
551
        test_cast_conformance(array.as_ref());
1✔
552
    }
1✔
553

554
    #[test]
555
    fn test_cast_conformance_nullable() {
1✔
556
        let array = PrimitiveArray::from_option_iter([Some(1u8), None, Some(255), Some(0), None]);
1✔
557
        test_cast_conformance(array.as_ref());
1✔
558
    }
1✔
559

560
    #[test]
561
    fn test_cast_conformance_bool() {
1✔
562
        let array = BoolArray::from_iter(vec![true, false, true, false]);
1✔
563
        test_cast_conformance(array.as_ref());
1✔
564
    }
1✔
565

566
    #[test]
567
    fn test_cast_conformance_null() {
1✔
568
        let array = NullArray::new(5);
1✔
569
        test_cast_conformance(array.as_ref());
1✔
570
    }
1✔
571

572
    #[test]
573
    fn test_cast_conformance_utf8() {
1✔
574
        let array = VarBinArray::from_iter(
1✔
575
            vec![Some("hello"), None, Some("world")],
1✔
576
            DType::Utf8(Nullability::Nullable),
1✔
577
        );
578
        test_cast_conformance(array.as_ref());
1✔
579
    }
1✔
580

581
    #[test]
582
    fn test_cast_conformance_binary() {
1✔
583
        let array = VarBinArray::from_iter(
1✔
584
            vec![Some(b"data".as_slice()), None, Some(b"bytes".as_slice())],
1✔
585
            DType::Binary(Nullability::Nullable),
1✔
586
        );
587
        test_cast_conformance(array.as_ref());
1✔
588
    }
1✔
589

590
    #[test]
591
    fn test_cast_conformance_struct() {
1✔
592
        let names: FieldNames = vec!["a".into(), "b".into()].into();
1✔
593

594
        let a = buffer![1i32, 2, 3].into_array();
1✔
595
        let b = VarBinArray::from_iter(
1✔
596
            vec![Some("x"), None, Some("z")],
1✔
597
            DType::Utf8(Nullability::Nullable),
1✔
598
        )
599
        .into_array();
1✔
600

601
        let array =
1✔
602
            StructArray::try_new(names, vec![a, b], 3, crate::validity::Validity::NonNullable)
1✔
603
                .unwrap();
1✔
604
        test_cast_conformance(array.as_ref());
1✔
605
    }
1✔
606

607
    #[test]
608
    fn test_cast_conformance_list() {
1✔
609
        let data = buffer![1i32, 2, 3, 4, 5, 6].into_array();
1✔
610
        let offsets = buffer![0i64, 2, 2, 5, 6].into_array();
1✔
611

612
        let array =
1✔
613
            ListArray::try_new(data, offsets, crate::validity::Validity::NonNullable).unwrap();
1✔
614
        test_cast_conformance(array.as_ref());
1✔
615
    }
1✔
616
}
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