zig/test/behavior/slice.zig

169 lines
4.4 KiB
Zig

const std = @import("std");
const expect = std.testing.expect;
const expectEqualSlices = std.testing.expectEqualSlices;
const expectEqual = std.testing.expectEqual;
const mem = std.mem;
// comptime array passed as slice argument
comptime {
const S = struct {
fn indexOfScalarPos(comptime T: type, slice: []const T, start_index: usize, value: T) ?usize {
var i: usize = start_index;
while (i < slice.len) : (i += 1) {
if (slice[i] == value) return i;
}
return null;
}
fn indexOfScalar(comptime T: type, slice: []const T, value: T) ?usize {
return indexOfScalarPos(T, slice, 0, value);
}
};
const unsigned = [_]type{ c_uint, c_ulong, c_ulonglong };
const list: []const type = &unsigned;
var pos = S.indexOfScalar(type, list, c_ulong).?;
if (pos != 1) @compileError("bad pos");
}
test "slicing" {
var array: [20]i32 = undefined;
array[5] = 1234;
var slice = array[5..10];
if (slice.len != 5) unreachable;
const ptr = &slice[0];
if (ptr.* != 1234) unreachable;
var slice_rest = array[10..];
if (slice_rest.len != 10) unreachable;
}
test "const slice" {
comptime {
const a = "1234567890";
try expect(a.len == 10);
const b = a[1..2];
try expect(b.len == 1);
try expect(b[0] == '2');
}
}
test "comptime slice of undefined pointer of length 0" {
const slice1 = @as([*]i32, undefined)[0..0];
try expect(slice1.len == 0);
const slice2 = @as([*]i32, undefined)[100..100];
try expect(slice2.len == 0);
}
test "implicitly cast array of size 0 to slice" {
var msg = [_]u8{};
try assertLenIsZero(&msg);
}
fn assertLenIsZero(msg: []const u8) !void {
try expect(msg.len == 0);
}
test "access len index of sentinel-terminated slice" {
const S = struct {
fn doTheTest() !void {
var slice: [:0]const u8 = "hello";
try expect(slice.len == 5);
try expect(slice[5] == 0);
}
};
try S.doTheTest();
comptime try S.doTheTest();
}
test "comptime slice of slice preserves comptime var" {
comptime {
var buff: [10]u8 = undefined;
buff[0..][0..][0] = 1;
try expect(buff[0..][0..][0] == 1);
}
}
test "slice of type" {
comptime {
var types_array = [_]type{ i32, f64, type };
for (types_array) |T, i| {
switch (i) {
0 => try expect(T == i32),
1 => try expect(T == f64),
2 => try expect(T == type),
else => unreachable,
}
}
for (types_array[0..]) |T, i| {
switch (i) {
0 => try expect(T == i32),
1 => try expect(T == f64),
2 => try expect(T == type),
else => unreachable,
}
}
}
}
test "generic malloc free" {
const a = memAlloc(u8, 10) catch unreachable;
memFree(u8, a);
}
var some_mem: [100]u8 = undefined;
fn memAlloc(comptime T: type, n: usize) anyerror![]T {
return @ptrCast([*]T, &some_mem[0])[0..n];
}
fn memFree(comptime T: type, memory: []T) void {
_ = memory;
}
test "slice of hardcoded address to pointer" {
const S = struct {
fn doTheTest() !void {
const pointer = @intToPtr([*]u8, 0x04)[0..2];
comptime try expect(@TypeOf(pointer) == *[2]u8);
const slice: []const u8 = pointer;
try expect(@ptrToInt(slice.ptr) == 4);
try expect(slice.len == 2);
}
};
try S.doTheTest();
}
test "comptime slice of pointer preserves comptime var" {
comptime {
var buff: [10]u8 = undefined;
var a = @ptrCast([*]u8, &buff);
a[0..1][0] = 1;
try expect(buff[0..][0..][0] == 1);
}
}
test "comptime pointer cast array and then slice" {
const array = [_]u8{ 1, 2, 3, 4, 5, 6, 7, 8 };
const ptrA: [*]const u8 = @ptrCast([*]const u8, &array);
const sliceA: []const u8 = ptrA[0..2];
const ptrB: [*]const u8 = &array;
const sliceB: []const u8 = ptrB[0..2];
try expect(sliceA[1] == 2);
try expect(sliceB[1] == 2);
}
test "slicing zero length array" {
const s1 = ""[0..];
const s2 = ([_]u32{})[0..];
try expect(s1.len == 0);
try expect(s2.len == 0);
try expect(mem.eql(u8, s1, ""));
try expect(mem.eql(u32, s2, &[_]u32{}));
}