diff --git a/doc/langref.html.in b/doc/langref.html.in index e6bdb6312..b1cf5ffc7 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -344,16 +344,16 @@ pub fn main() void { {#header_close#} {#header_open|Comments#} {#code_begin|test|comments#} -const assert = @import("std").debug.assert; +const expect = @import("std").testing.expect; test "comments" { // Comments in Zig start with "//" and end at the next LF byte (end of line). // The below line is a comment, and won't be executed. - //assert(false); + //expect(false); const x = true; // another comment - assert(x); + expect(x); } {#code_end#}

@@ -695,19 +695,19 @@ pub fn main() void { and character literals.

{#code_begin|test#} -const assert = @import("std").debug.assert; +const expect = @import("std").testing.expect; const mem = @import("std").mem; test "string literals" { const bytes = "hello"; - assert(@TypeOf(bytes) == *const [5:0]u8); - assert(bytes.len == 5); - assert(bytes[1] == 'e'); - assert(bytes[5] == 0); - assert('e' == '\x65'); - assert('\u{1f4a9}' == 128169); - assert('πŸ’―' == 128175); - assert(mem.eql(u8, "hello", "h\x65llo")); + expect(@TypeOf(bytes) == *const [5:0]u8); + expect(bytes.len == 5); + expect(bytes[1] == 'e'); + expect(bytes[5] == 0); + expect('e' == '\x65'); + expect('\u{1f4a9}' == 128169); + expect('πŸ’―' == 128175); + expect(mem.eql(u8, "hello", "h\x65llo")); } {#code_end#} {#see_also|Arrays|Zig Test|Source Encoding#} @@ -800,14 +800,14 @@ test "assignment" {

{#syntax#}const{#endsyntax#} applies to all of the bytes that the identifier immediately addresses. {#link|Pointers#} have their own const-ness.

If you need a variable that you can modify, use the {#syntax#}var{#endsyntax#} keyword:

{#code_begin|test#} -const assert = @import("std").debug.assert; +const expect = @import("std").testing.expect; test "var" { var y: i32 = 5678; y += 1; - assert(y == 5679); + expect(y == 5679); } {#code_end#}

Variables must be initialized:

@@ -821,12 +821,12 @@ test "initialization" { {#header_open|undefined#}

Use {#syntax#}undefined{#endsyntax#} to leave variables uninitialized:

{#code_begin|test#} -const assert = @import("std").debug.assert; +const expect = @import("std").testing.expect; test "init with undefined" { var x: i32 = undefined; x = 1; - assert(x == 1); + expect(x == 1); } {#code_end#}

@@ -868,8 +868,8 @@ var y: i32 = add(10, x); const x: i32 = add(12, 34); test "global variables" { - assert(x == 46); - assert(y == 56); + expect(x == 46); + expect(y == 56); } fn add(a: i32, b: i32) i32 { @@ -877,18 +877,18 @@ fn add(a: i32, b: i32) i32 { } const std = @import("std"); -const assert = std.debug.assert; +const expect = std.testing.expect; {#code_end#}

Global variables may be declared inside a {#link|struct#}, {#link|union#}, or {#link|enum#}:

{#code_begin|test|namespaced_global#} const std = @import("std"); -const assert = std.debug.assert; +const expect = std.testing.expect; test "namespaced global variable" { - assert(foo() == 1235); - assert(foo() == 1236); + expect(foo() == 1235); + expect(foo() == 1236); } fn foo() i32 { @@ -957,7 +957,7 @@ fn testTls(context: void) void {

{#code_begin|test|comptime_vars#} const std = @import("std"); -const assert = std.debug.assert; +const expect = std.testing.expect; test "comptime vars" { var x: i32 = 1; @@ -966,8 +966,8 @@ test "comptime vars" { x += 1; y += 1; - assert(x == 2); - assert(y == 2); + expect(x == 2); + expect(y == 2); if (y != 2) { // This compile error never triggers because y is a comptime variable, @@ -1757,7 +1757,7 @@ orelse catch {#header_close#} {#header_open|Arrays#} {#code_begin|test|arrays#} -const assert = @import("std").debug.assert; +const expect = @import("std").testing.expect; const mem = @import("std").mem; // array literal @@ -1765,14 +1765,14 @@ const message = [_]u8{ 'h', 'e', 'l', 'l', 'o' }; // get the size of an array comptime { - assert(message.len == 5); + expect(message.len == 5); } // A string literal is a pointer to an array literal. const same_message = "hello"; comptime { - assert(mem.eql(u8, &message, same_message)); + expect(mem.eql(u8, &message, same_message)); } test "iterate over an array" { @@ -1780,7 +1780,7 @@ test "iterate over an array" { for (message) |byte| { sum += byte; } - assert(sum == 'h' + 'e' + 'l' * 2 + 'o'); + expect(sum == 'h' + 'e' + 'l' * 2 + 'o'); } // modifiable array @@ -1790,8 +1790,8 @@ test "modify an array" { for (some_integers) |*item, i| { item.* = @intCast(i32, i); } - assert(some_integers[10] == 10); - assert(some_integers[99] == 99); + expect(some_integers[10] == 10); + expect(some_integers[99] == 99); } // array concatenation works if the values are known @@ -1800,7 +1800,7 @@ const part_one = [_]i32{ 1, 2, 3, 4 }; const part_two = [_]i32{ 5, 6, 7, 8 }; const all_of_it = part_one ++ part_two; comptime { - assert(mem.eql(i32, &all_of_it, &[_]i32{ 1, 2, 3, 4, 5, 6, 7, 8 })); + expect(mem.eql(i32, &all_of_it, &[_]i32{ 1, 2, 3, 4, 5, 6, 7, 8 })); } // remember that string literals are arrays @@ -1808,21 +1808,21 @@ const hello = "hello"; const world = "world"; const hello_world = hello ++ " " ++ world; comptime { - assert(mem.eql(u8, hello_world, "hello world")); + expect(mem.eql(u8, hello_world, "hello world")); } // ** does repeating patterns const pattern = "ab" ** 3; comptime { - assert(mem.eql(u8, pattern, "ababab")); + expect(mem.eql(u8, pattern, "ababab")); } // initialize an array to zero const all_zero = [_]u16{0} ** 10; comptime { - assert(all_zero.len == 10); - assert(all_zero[5] == 0); + expect(all_zero.len == 10); + expect(all_zero[5] == 0); } // use compile-time code to initialize an array @@ -1842,8 +1842,8 @@ const Point = struct { }; test "compile-time array initialization" { - assert(fancy_array[4].x == 4); - assert(fancy_array[4].y == 8); + expect(fancy_array[4].x == 4); + expect(fancy_array[4].y == 8); } // call a function to initialize an array @@ -1855,9 +1855,9 @@ fn makePoint(x: i32) Point { }; } test "array initialization with function calls" { - assert(more_points[4].x == 3); - assert(more_points[4].y == 6); - assert(more_points.len == 10); + expect(more_points[4].x == 3); + expect(more_points[4].y == 6); + expect(more_points.len == 10); } {#code_end#} {#see_also|for|Slices#} @@ -1867,14 +1867,14 @@ test "array initialization with function calls" { the type can be omitted from array literals:

{#code_begin|test|anon_list#} const std = @import("std"); -const assert = std.debug.assert; +const expect = std.testing.expect; test "anonymous list literal syntax" { var array: [4]u8 = .{11, 22, 33, 44}; - assert(array[0] == 11); - assert(array[1] == 22); - assert(array[2] == 33); - assert(array[3] == 44); + expect(array[0] == 11); + expect(array[1] == 22); + expect(array[2] == 33); + expect(array[3] == 44); } {#code_end#}

@@ -1883,18 +1883,18 @@ test "anonymous list literal syntax" {

{#code_begin|test|infer_list_literal#} const std = @import("std"); -const assert = std.debug.assert; +const expect = std.testing.expect; test "fully anonymous list literal" { dump(.{ @as(u32, 1234), @as(f64, 12.34), true, "hi"}); } fn dump(args: anytype) void { - assert(args.@"0" == 1234); - assert(args.@"1" == 12.34); - assert(args.@"2"); - assert(args.@"3"[0] == 'h'); - assert(args.@"3"[1] == 'i'); + expect(args.@"0" == 1234); + expect(args.@"1" == 12.34); + expect(args.@"2"); + expect(args.@"3"[0] == 'h'); + expect(args.@"3"[1] == 'i'); } {#code_end#} {#header_close#} @@ -1905,7 +1905,7 @@ fn dump(args: anytype) void {

{#code_begin|test|multidimensional#} const std = @import("std"); -const assert = std.debug.assert; +const expect = std.testing.expect; const mat4x4 = [4][4]f32{ [_]f32{ 1.0, 0.0, 0.0, 0.0 }, @@ -1915,13 +1915,13 @@ const mat4x4 = [4][4]f32{ }; test "multidimensional arrays" { // Access the 2D array by indexing the outer array, and then the inner array. - assert(mat4x4[1][1] == 1.0); + expect(mat4x4[1][1] == 1.0); // Here we iterate with for loops. for (mat4x4) |row, row_index| { for (row) |cell, column_index| { if (row_index == column_index) { - assert(cell == 1.0); + expect(cell == 1.0); } } } @@ -1936,14 +1936,14 @@ test "multidimensional arrays" {

{#code_begin|test|null_terminated_array#} const std = @import("std"); -const assert = std.debug.assert; +const expect = std.testing.expect; test "null terminated array" { const array = [_:0]u8 {1, 2, 3, 4}; - assert(@TypeOf(array) == [4:0]u8); - assert(array.len == 4); - assert(array[4] == 0); + expect(@TypeOf(array) == [4:0]u8); + expect(array.len == 4); + expect(array[4] == 0); } {#code_end#} {#see_also|Sentinel-Terminated Pointers|Sentinel-Terminated Slices#} @@ -2013,7 +2013,7 @@ test "null terminated array" {

Use {#syntax#}&x{#endsyntax#} to obtain a single-item pointer:

{#code_begin|test#} -const assert = @import("std").debug.assert; +const expect = @import("std").testing.expect; test "address of syntax" { // Get the address of a variable: @@ -2021,17 +2021,17 @@ test "address of syntax" { const x_ptr = &x; // Dereference a pointer: - assert(x_ptr.* == 1234); + expect(x_ptr.* == 1234); // When you get the address of a const variable, you get a const pointer to a single item. - assert(@TypeOf(x_ptr) == *const i32); + expect(@TypeOf(x_ptr) == *const i32); // If you want to mutate the value, you'd need an address of a mutable variable: var y: i32 = 5678; const y_ptr = &y; - assert(@TypeOf(y_ptr) == *i32); + expect(@TypeOf(y_ptr) == *i32); y_ptr.* += 1; - assert(y_ptr.* == 5679); + expect(y_ptr.* == 5679); } test "pointer array access" { @@ -2040,11 +2040,11 @@ test "pointer array access" { // does not support pointer arithmetic. var array = [_]u8{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; const ptr = &array[2]; - assert(@TypeOf(ptr) == *u8); + expect(@TypeOf(ptr) == *u8); - assert(array[2] == 3); + expect(array[2] == 3); ptr.* += 1; - assert(array[2] == 4); + expect(array[2] == 4); } {#code_end#}

@@ -2057,22 +2057,22 @@ test "pointer array access" { we prefer slices to pointers.

{#code_begin|test#} -const assert = @import("std").debug.assert; +const expect = @import("std").testing.expect; test "pointer slicing" { var array = [_]u8{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; const slice = array[2..4]; - assert(slice.len == 2); + expect(slice.len == 2); - assert(array[3] == 4); + expect(array[3] == 4); slice[1] += 1; - assert(array[3] == 5); + expect(array[3] == 5); } {#code_end#}

Pointers work at compile-time too, as long as the code does not depend on an undefined memory layout:

{#code_begin|test#} -const assert = @import("std").debug.assert; +const expect = @import("std").testing.expect; test "comptime pointers" { comptime { @@ -2080,26 +2080,26 @@ test "comptime pointers" { const ptr = &x; ptr.* += 1; x += 1; - assert(ptr.* == 3); + expect(ptr.* == 3); } } {#code_end#}

To convert an integer address into a pointer, use {#syntax#}@intToPtr{#endsyntax#}. To convert a pointer to an integer, use {#syntax#}@ptrToInt{#endsyntax#}:

{#code_begin|test#} -const assert = @import("std").debug.assert; +const expect = @import("std").testing.expect; test "@ptrToInt and @intToPtr" { const ptr = @intToPtr(*i32, 0xdeadbee0); const addr = @ptrToInt(ptr); - assert(@TypeOf(addr) == usize); - assert(addr == 0xdeadbee0); + expect(@TypeOf(addr) == usize); + expect(addr == 0xdeadbee0); } {#code_end#}

Zig is able to preserve memory addresses in comptime code, as long as the pointer is never dereferenced:

{#code_begin|test#} -const assert = @import("std").debug.assert; +const expect = @import("std").testing.expect; test "comptime @intToPtr" { comptime { @@ -2107,8 +2107,8 @@ test "comptime @intToPtr" { // ptr is never dereferenced. const ptr = @intToPtr(*i32, 0xdeadbee0); const addr = @ptrToInt(ptr); - assert(@TypeOf(addr) == usize); - assert(addr == 0xdeadbee0); + expect(@TypeOf(addr) == usize); + expect(addr == 0xdeadbee0); } } {#code_end#} @@ -2119,11 +2119,11 @@ test "comptime @intToPtr" { In the following code, loads and stores with {#syntax#}mmio_ptr{#endsyntax#} are guaranteed to all happen and in the same order as in source code:

{#code_begin|test#} -const assert = @import("std").debug.assert; +const expect = @import("std").testing.expect; test "volatile" { const mmio_ptr = @intToPtr(*volatile u8, 0x12345678); - assert(@TypeOf(mmio_ptr) == *volatile u8); + expect(@TypeOf(mmio_ptr) == *volatile u8); } {#code_end#}

@@ -2139,25 +2139,25 @@ test "volatile" {

{#code_begin|test#} const std = @import("std"); -const assert = std.debug.assert; +const expect = std.testing.expect; test "pointer casting" { const bytes align(@alignOf(u32)) = [_]u8{ 0x12, 0x12, 0x12, 0x12 }; const u32_ptr = @ptrCast(*const u32, &bytes); - assert(u32_ptr.* == 0x12121212); + expect(u32_ptr.* == 0x12121212); // Even this example is contrived - there are better ways to do the above than // pointer casting. For example, using a slice narrowing cast: const u32_value = std.mem.bytesAsSlice(u32, bytes[0..])[0]; - assert(u32_value == 0x12121212); + expect(u32_value == 0x12121212); // And even another way, the most straightforward way to do it: - assert(@bitCast(u32, bytes) == 0x12121212); + expect(@bitCast(u32, bytes) == 0x12121212); } test "pointer child type" { // pointer types have a `child` field which tells you the type they point to. - assert(@typeInfo(*u32).Pointer.child == u32); + expect(@typeInfo(*u32).Pointer.child == u32); } {#code_end#} {#header_open|Alignment#} @@ -2177,15 +2177,15 @@ test "pointer child type" {

{#code_begin|test#} const std = @import("std"); -const assert = std.debug.assert; +const expect = std.testing.expect; test "variable alignment" { var x: i32 = 1234; const align_of_i32 = @alignOf(@TypeOf(x)); - assert(@TypeOf(&x) == *i32); - assert(*i32 == *align(align_of_i32) i32); + expect(@TypeOf(&x) == *i32); + expect(*i32 == *align(align_of_i32) i32); if (std.Target.current.cpu.arch == .x86_64) { - assert(@typeInfo(*i32).Pointer.alignment == 4); + expect(@typeInfo(*i32).Pointer.alignment == 4); } } {#code_end#} @@ -2198,16 +2198,16 @@ test "variable alignment" { pointers to them get the specified alignment:

{#code_begin|test#} -const assert = @import("std").debug.assert; +const expect = @import("std").testing.expect; var foo: u8 align(4) = 100; test "global variable alignment" { - assert(@typeInfo(@TypeOf(&foo)).Pointer.alignment == 4); - assert(@TypeOf(&foo) == *align(4) u8); + expect(@typeInfo(@TypeOf(&foo)).Pointer.alignment == 4); + expect(@TypeOf(&foo) == *align(4) u8); const as_pointer_to_array: *[1]u8 = &foo; const as_slice: []u8 = as_pointer_to_array; - assert(@TypeOf(as_slice) == []align(4) u8); + expect(@TypeOf(as_slice) == []align(4) u8); } fn derp() align(@sizeOf(usize) * 2) i32 { return 1234; } @@ -2215,9 +2215,9 @@ fn noop1() align(1) void {} fn noop4() align(4) void {} test "function alignment" { - assert(derp() == 1234); - assert(@TypeOf(noop1) == fn() align(1) void); - assert(@TypeOf(noop4) == fn() align(4) void); + expect(derp() == 1234); + expect(@TypeOf(noop1) == fn() align(1) void); + expect(@TypeOf(noop4) == fn() align(4) void); noop1(); noop4(); } @@ -2234,7 +2234,7 @@ const std = @import("std"); test "pointer alignment safety" { var array align(4) = [_]u32{ 0x11111111, 0x11111111 }; const bytes = std.mem.sliceAsBytes(array[0..]); - std.debug.assert(foo(bytes) == 0x11111111); + std.testing.expect(foo(bytes) == 0x11111111); } fn foo(bytes: []u8) u32 { const slice4 = bytes[1..5]; @@ -2255,12 +2255,12 @@ fn foo(bytes: []u8) u32 {

{#code_begin|test|allowzero#} const std = @import("std"); -const assert = std.debug.assert; +const expect = std.testing.expect; test "allowzero" { var zero: usize = 0; var ptr = @intToPtr(*allowzero i32, zero); - assert(@ptrToInt(ptr) == 0); + expect(@ptrToInt(ptr) == 0); } {#code_end#} {#header_close#} @@ -2292,7 +2292,7 @@ pub fn main() anyerror!void { {#header_open|Slices#} {#code_begin|test_safety|index out of bounds#} -const assert = @import("std").debug.assert; +const expect = @import("std").testing.expect; test "basic slices" { var array = [_]i32{ 1, 2, 3, 4 }; @@ -2302,14 +2302,14 @@ test "basic slices" { // Both can be accessed with the `len` field. var known_at_runtime_zero: usize = 0; const slice = array[known_at_runtime_zero..array.len]; - assert(&slice[0] == &array[0]); - assert(slice.len == array.len); + expect(&slice[0] == &array[0]); + expect(slice.len == array.len); // Using the address-of operator on a slice gives a pointer to a single // item, while using the `ptr` field gives an unknown length pointer. - assert(@TypeOf(slice.ptr) == [*]i32); - assert(@TypeOf(&slice[0]) == *i32); - assert(@ptrToInt(slice.ptr) == @ptrToInt(&slice[0])); + expect(@TypeOf(slice.ptr) == [*]i32); + expect(@TypeOf(&slice[0]) == *i32); + expect(@ptrToInt(slice.ptr) == @ptrToInt(&slice[0])); // Slices have array bounds checking. If you try to access something out // of bounds, you'll get a safety check failure: @@ -2322,7 +2322,7 @@ test "basic slices" {

This is one reason we prefer slices to pointers.

{#code_begin|test|slices#} const std = @import("std"); -const assert = std.debug.assert; +const expect = std.testing.expect; const mem = std.mem; const fmt = std.fmt; @@ -2343,7 +2343,7 @@ test "using slices for strings" { // Generally, you can use UTF-8 and not worry about whether something is a // string. If you don't need to deal with individual characters, no need // to decode. - assert(mem.eql(u8, hello_world, "hello δΈ–η•Œ")); + expect(mem.eql(u8, hello_world, "hello δΈ–η•Œ")); } test "slice pointer" { @@ -2353,16 +2353,16 @@ test "slice pointer" { // You can use slicing syntax to convert a pointer into a slice: const slice = ptr[0..5]; slice[2] = 3; - assert(slice[2] == 3); + expect(slice[2] == 3); // The slice is mutable because we sliced a mutable pointer. // Furthermore, it is actually a pointer to an array, since the start // and end indexes were both comptime-known. - assert(@TypeOf(slice) == *[5]u8); + expect(@TypeOf(slice) == *[5]u8); // You can also slice a slice: const slice2 = slice[2..3]; - assert(slice2.len == 1); - assert(slice2[0] == 3); + expect(slice2.len == 1); + expect(slice2[0] == 3); } {#code_end#} {#see_also|Pointers|for|Arrays#} @@ -2376,13 +2376,13 @@ test "slice pointer" {

{#code_begin|test|null_terminated_slice#} const std = @import("std"); -const assert = std.debug.assert; +const expect = std.testing.expect; test "null terminated slice" { const slice: [:0]const u8 = "hello"; - assert(slice.len == 5); - assert(slice[5] == 0); + expect(slice.len == 5); + expect(slice[5] == 0); } {#code_end#} {#see_also|Sentinel-Terminated Pointers|Sentinel-Terminated Arrays#} @@ -2440,16 +2440,16 @@ const Vec3 = struct { } }; -const assert = @import("std").debug.assert; +const expect = @import("std").testing.expect; test "dot product" { const v1 = Vec3.init(1.0, 0.0, 0.0); const v2 = Vec3.init(0.0, 1.0, 0.0); - assert(v1.dot(v2) == 0.0); + expect(v1.dot(v2) == 0.0); // Other than being available to call with dot syntax, struct methods are // not special. You can reference them as any other declaration inside // the struct: - assert(Vec3.dot(v1, v2) == 0.0); + expect(Vec3.dot(v1, v2) == 0.0); } // Structs can have global declarations. @@ -2458,8 +2458,8 @@ const Empty = struct { pub const PI = 3.14; }; test "struct namespaced variable" { - assert(Empty.PI == 3.14); - assert(@sizeOf(Empty) == 0); + expect(Empty.PI == 3.14); + expect(@sizeOf(Empty) == 0); // you can still instantiate an empty struct const does_nothing = Empty {}; @@ -2477,7 +2477,7 @@ test "field parent pointer" { .y = 0.5678, }; setYBasedOnX(&point.x, 0.9); - assert(point.y == 0.9); + expect(point.y == 0.9); } // You can return a struct from a function. This is how we do generics @@ -2499,19 +2499,19 @@ fn LinkedList(comptime T: type) type { test "linked list" { // Functions called at compile-time are memoized. This means you can // do this: - assert(LinkedList(i32) == LinkedList(i32)); + expect(LinkedList(i32) == LinkedList(i32)); var list = LinkedList(i32) { .first = null, .last = null, .len = 0, }; - assert(list.len == 0); + expect(list.len == 0); // Since types are first class values you can instantiate the type // by assigning it to a variable: const ListOfInts = LinkedList(i32); - assert(ListOfInts == LinkedList(i32)); + expect(ListOfInts == LinkedList(i32)); var node = ListOfInts.Node { .prev = null, @@ -2523,7 +2523,7 @@ test "linked list" { .last = &node, .len = 1, }; - assert(list2.first.?.data == 1234); + expect(list2.first.?.data == 1234); } {#code_end#} @@ -2584,7 +2584,7 @@ test "default struct initialization fields" { {#code_begin|test#} const std = @import("std"); const builtin = std.builtin; -const assert = std.debug.assert; +const expect = std.testing.expect; const Full = packed struct { number: u16, @@ -2601,20 +2601,20 @@ test "@bitCast between packed structs" { } fn doTheTest() void { - assert(@sizeOf(Full) == 2); - assert(@sizeOf(Divided) == 2); + expect(@sizeOf(Full) == 2); + expect(@sizeOf(Divided) == 2); var full = Full{ .number = 0x1234 }; var divided = @bitCast(Divided, full); switch (builtin.endian) { .Big => { - assert(divided.half1 == 0x12); - assert(divided.quarter3 == 0x3); - assert(divided.quarter4 == 0x4); + expect(divided.half1 == 0x12); + expect(divided.quarter3 == 0x3); + expect(divided.quarter4 == 0x4); }, .Little => { - assert(divided.half1 == 0x34); - assert(divided.quarter3 == 0x2); - assert(divided.quarter4 == 0x1); + expect(divided.half1 == 0x34); + expect(divided.quarter3 == 0x2); + expect(divided.quarter4 == 0x1); }, } } @@ -2624,7 +2624,7 @@ fn doTheTest() void {

{#code_begin|test#} const std = @import("std"); -const assert = std.debug.assert; +const expect = std.testing.expect; const BitField = packed struct { a: u3, @@ -2640,7 +2640,7 @@ var foo = BitField{ test "pointer to non-byte-aligned field" { const ptr = &foo.b; - assert(ptr.* == 2); + expect(ptr.* == 2); } {#code_end#}

@@ -2649,7 +2649,7 @@ test "pointer to non-byte-aligned field" {

{#code_begin|test_err|expected type#} const std = @import("std"); -const assert = std.debug.assert; +const expect = std.testing.expect; const BitField = packed struct { a: u3, @@ -2664,7 +2664,7 @@ var bit_field = BitField{ }; test "pointer to non-bit-aligned field" { - assert(bar(&bit_field.b) == 2); + expect(bar(&bit_field.b) == 2); } fn bar(x: *const u3) u3 { @@ -2680,7 +2680,7 @@ fn bar(x: *const u3) u3 {

{#code_begin|test#} const std = @import("std"); -const assert = std.debug.assert; +const expect = std.testing.expect; const BitField = packed struct { a: u3, @@ -2695,8 +2695,8 @@ var bit_field = BitField{ }; test "pointer to non-bit-aligned field" { - assert(@ptrToInt(&bit_field.a) == @ptrToInt(&bit_field.b)); - assert(@ptrToInt(&bit_field.a) == @ptrToInt(&bit_field.c)); + expect(@ptrToInt(&bit_field.a) == @ptrToInt(&bit_field.b)); + expect(@ptrToInt(&bit_field.a) == @ptrToInt(&bit_field.c)); } {#code_end#}

@@ -2704,7 +2704,7 @@ test "pointer to non-bit-aligned field" {

{#code_begin|test#} const std = @import("std"); -const assert = std.debug.assert; +const expect = std.testing.expect; const BitField = packed struct { a: u3, @@ -2714,13 +2714,13 @@ const BitField = packed struct { test "pointer to non-bit-aligned field" { comptime { - assert(@bitOffsetOf(BitField, "a") == 0); - assert(@bitOffsetOf(BitField, "b") == 3); - assert(@bitOffsetOf(BitField, "c") == 6); + expect(@bitOffsetOf(BitField, "a") == 0); + expect(@bitOffsetOf(BitField, "b") == 3); + expect(@bitOffsetOf(BitField, "c") == 6); - assert(@byteOffsetOf(BitField, "a") == 0); - assert(@byteOffsetOf(BitField, "b") == 0); - assert(@byteOffsetOf(BitField, "c") == 0); + expect(@byteOffsetOf(BitField, "a") == 0); + expect(@byteOffsetOf(BitField, "b") == 0); + expect(@byteOffsetOf(BitField, "c") == 0); } } {#code_end#} @@ -2791,7 +2791,7 @@ fn List(comptime T: type) type {

{#code_begin|test|struct_result#} const std = @import("std"); -const assert = std.debug.assert; +const expect = std.testing.expect; const Point = struct {x: i32, y: i32}; @@ -2800,8 +2800,8 @@ test "anonymous struct literal" { .x = 13, .y = 67, }; - assert(pt.x == 13); - assert(pt.y == 67); + expect(pt.x == 13); + expect(pt.y == 67); } {#code_end#}

@@ -2810,7 +2810,7 @@ test "anonymous struct literal" {

{#code_begin|test|struct_anon#} const std = @import("std"); -const assert = std.debug.assert; +const expect = std.testing.expect; test "fully anonymous struct" { dump(.{ @@ -2822,11 +2822,11 @@ test "fully anonymous struct" { } fn dump(args: anytype) void { - assert(args.int == 1234); - assert(args.float == 12.34); - assert(args.b); - assert(args.s[0] == 'h'); - assert(args.s[1] == 'i'); + expect(args.int == 1234); + expect(args.float == 12.34); + expect(args.b); + expect(args.s[0] == 'h'); + expect(args.s[1] == 'i'); } {#code_end#} {#header_close#} @@ -2834,7 +2834,7 @@ fn dump(args: anytype) void { {#header_close#} {#header_open|enum#} {#code_begin|test|enums#} -const assert = @import("std").debug.assert; +const expect = @import("std").testing.expect; const mem = @import("std").mem; // Declare an enum. @@ -2857,9 +2857,9 @@ const Value = enum(u2) { // Now you can cast between u2 and Value. // The ordinal value starts from 0, counting up for each member. test "enum ordinal value" { - assert(@enumToInt(Value.zero) == 0); - assert(@enumToInt(Value.one) == 1); - assert(@enumToInt(Value.two) == 2); + expect(@enumToInt(Value.zero) == 0); + expect(@enumToInt(Value.one) == 1); + expect(@enumToInt(Value.two) == 2); } // You can override the ordinal value for an enum. @@ -2869,9 +2869,9 @@ const Value2 = enum(u32) { million = 1000000, }; test "set enum ordinal value" { - assert(@enumToInt(Value2.hundred) == 100); - assert(@enumToInt(Value2.thousand) == 1000); - assert(@enumToInt(Value2.million) == 1000000); + expect(@enumToInt(Value2.hundred) == 100); + expect(@enumToInt(Value2.thousand) == 1000); + expect(@enumToInt(Value2.million) == 1000000); } // Enums can have methods, the same as structs and unions. @@ -2889,7 +2889,7 @@ const Suit = enum { }; test "enum method" { const p = Suit.spades; - assert(!p.isClubs()); + expect(!p.isClubs()); } // An enum variant of different types can be switched upon. @@ -2905,7 +2905,7 @@ test "enum variant switch" { Foo.number => "this is a number", Foo.none => "this is a none", }; - assert(mem.eql(u8, what_is_it, "this is a number")); + expect(mem.eql(u8, what_is_it, "this is a number")); } // @TagType can be used to access the integer tag type of an enum. @@ -2916,18 +2916,18 @@ const Small = enum { four, }; test "@TagType" { - assert(@TagType(Small) == u2); + expect(@TagType(Small) == u2); } // @typeInfo tells us the field count and the fields names: test "@typeInfo" { - assert(@typeInfo(Small).Enum.fields.len == 4); - assert(mem.eql(u8, @typeInfo(Small).Enum.fields[1].name, "two")); + expect(@typeInfo(Small).Enum.fields.len == 4); + expect(mem.eql(u8, @typeInfo(Small).Enum.fields[1].name, "two")); } // @tagName gives a []const u8 representation of an enum value: test "@tagName" { - assert(mem.eql(u8, @tagName(Small.three), "three")); + expect(mem.eql(u8, @tagName(Small.three), "three")); } {#code_end#} {#see_also|@typeInfo|@tagName|@sizeOf#} @@ -2962,7 +2962,7 @@ test "packed enum" { two, three, }; - std.debug.assert(@sizeOf(Number) == @sizeOf(u8)); + std.testing.expect(@sizeOf(Number) == @sizeOf(u8)); } {#code_end#}

This makes the enum eligible to be in a {#link|packed struct#}.

@@ -2974,7 +2974,7 @@ test "packed enum" {

{#code_begin|test#} const std = @import("std"); -const assert = std.debug.assert; +const expect = std.testing.expect; const Color = enum { auto, @@ -2985,7 +2985,7 @@ const Color = enum { test "enum literals" { const color1: Color = .auto; const color2 = Color.auto; - assert(color1 == color2); + expect(color1 == color2); } test "switch using enum literals" { @@ -2995,7 +2995,7 @@ test "switch using enum literals" { .on => true, .off => false, }; - assert(result); + expect(result); } {#code_end#} {#header_close#} @@ -3014,7 +3014,7 @@ test "switch using enum literals" {

{#code_begin|test#} const std = @import("std"); -const assert = std.debug.assert; +const expect = std.testing.expect; const Number = enum(u8) { one, @@ -3031,12 +3031,12 @@ test "switch on non-exhaustive enum" { .three => false, _ => false, }; - assert(result); + expect(result); const is_one = switch (number) { .one => true, else => false, }; - assert(is_one); + expect(is_one); } {#code_end#} {#header_close#} @@ -3067,7 +3067,7 @@ test "simple union" {

You can activate another field by assigning the entire union:

{#code_begin|test#} const std = @import("std"); -const assert = std.debug.assert; +const expect = std.testing.expect; const Payload = union { int: i64, @@ -3076,9 +3076,9 @@ const Payload = union { }; test "simple union" { var payload = Payload{ .int = 1234 }; - assert(payload.int == 1234); + expect(payload.int == 1234); payload = Payload{ .float = 12.34 }; - assert(payload.float == 12.34); + expect(payload.float == 12.34); } {#code_end#}

@@ -3097,7 +3097,7 @@ test "simple union" {

{#code_begin|test#} const std = @import("std"); -const assert = std.debug.assert; +const expect = std.testing.expect; const ComplexTypeTag = enum { ok, @@ -3110,24 +3110,24 @@ const ComplexType = union(ComplexTypeTag) { test "switch on tagged union" { const c = ComplexType{ .ok = 42 }; - assert(@as(ComplexTypeTag, c) == ComplexTypeTag.ok); + expect(@as(ComplexTypeTag, c) == ComplexTypeTag.ok); switch (c) { - ComplexTypeTag.ok => |value| assert(value == 42), + ComplexTypeTag.ok => |value| expect(value == 42), ComplexTypeTag.not_ok => unreachable, } } test "@TagType" { - assert(@TagType(ComplexType) == ComplexTypeTag); + expect(@TagType(ComplexType) == ComplexTypeTag); } test "coerce to enum" { const c1 = ComplexType{ .ok = 42 }; const c2 = ComplexType.not_ok; - assert(c1 == .ok); - assert(c2 == .not_ok); + expect(c1 == .ok); + expect(c2 == .not_ok); } {#code_end#}

In order to modify the payload of a tagged union in a switch expression, @@ -3135,7 +3135,7 @@ test "coerce to enum" {

{#code_begin|test#} const std = @import("std"); -const assert = std.debug.assert; +const expect = std.testing.expect; const ComplexTypeTag = enum { ok, @@ -3148,14 +3148,14 @@ const ComplexType = union(ComplexTypeTag) { test "modify tagged union in switch" { var c = ComplexType{ .ok = 42 }; - assert(@as(ComplexTypeTag, c) == ComplexTypeTag.ok); + expect(@as(ComplexTypeTag, c) == ComplexTypeTag.ok); switch (c) { ComplexTypeTag.ok => |*value| value.* += 1, ComplexTypeTag.not_ok => unreachable, } - assert(c.ok == 43); + expect(c.ok == 43); } {#code_end#}

@@ -3164,7 +3164,7 @@ test "modify tagged union in switch" {

{#code_begin|test#} const std = @import("std"); -const assert = std.debug.assert; +const expect = std.testing.expect; const Variant = union(enum) { int: i32, @@ -3186,8 +3186,8 @@ test "union method" { var v1 = Variant{ .int = 1 }; var v2 = Variant{ .boolean = false }; - assert(v1.truthy()); - assert(!v2.truthy()); + expect(v1.truthy()); + expect(!v2.truthy()); } {#code_end#}

@@ -3196,7 +3196,7 @@ test "union method" {

{#code_begin|test#} const std = @import("std"); -const assert = std.debug.assert; +const expect = std.testing.expect; const Small2 = union(enum) { a: i32, @@ -3204,7 +3204,7 @@ const Small2 = union(enum) { c: u8, }; test "@tagName" { - assert(std.mem.eql(u8, @tagName(Small2.a), "a")); + expect(std.mem.eql(u8, @tagName(Small2.a), "a")); } {#code_end#} {#header_close#} @@ -3227,7 +3227,7 @@ test "@tagName" { the type:

{#code_begin|test|anon_union#} const std = @import("std"); -const assert = std.debug.assert; +const expect = std.testing.expect; const Number = union { int: i32, @@ -3237,8 +3237,8 @@ const Number = union { test "anonymous union literal syntax" { var i: Number = .{.int = 42}; var f = makeNumber(); - assert(i.int == 42); - assert(f.float == 12.34); + expect(i.int == 42); + expect(f.float == 12.34); } fn makeNumber() Number { @@ -3291,7 +3291,7 @@ test "access variable after block scope" {

{#code_begin|test#} const std = @import("std"); -const assert = std.debug.assert; +const expect = std.testing.expect; test "labeled break from labeled block expression" { var y: i32 = 123; @@ -3300,8 +3300,8 @@ test "labeled break from labeled block expression" { y += 1; break :blk y; }; - assert(x == 124); - assert(y == 124); + expect(x == 124); + expect(y == 124); } {#code_end#}

Here, {#syntax#}blk{#endsyntax#} can be any name.

@@ -3339,7 +3339,7 @@ test "separate scopes" { {#header_open|switch#} {#code_begin|test|switch#} const std = @import("std"); -const assert = std.debug.assert; +const expect = std.testing.expect; test "switch simple" { const a: u64 = 10; @@ -3379,7 +3379,7 @@ test "switch simple" { else => 9, }; - assert(b == 1); + expect(b == 1); } // Switch expressions can be used outside a function: @@ -3409,7 +3409,7 @@ test "switch inside function" { turning it into a pointer.

{#code_begin|test#} -const assert = @import("std").debug.assert; +const expect = @import("std").testing.expect; test "switch on tagged union" { const Point = struct { @@ -3442,8 +3442,8 @@ test "switch on tagged union" { Item.d => 8, }; - assert(b == 6); - assert(a.c.x == 2); + expect(b == 6); + expect(a.c.x == 2); } {#code_end#} {#see_also|comptime|enum|@compileError|Compile Variables#} @@ -3477,7 +3477,7 @@ test "exhaustive switching" {

{#code_begin|test#} const std = @import("std"); -const assert = std.debug.assert; +const expect = std.testing.expect; const Color = enum { auto, @@ -3492,7 +3492,7 @@ test "enum literals with switch" { .on => false, .off => true, }; - assert(result); + expect(result); } {#code_end#} {#header_close#} @@ -3504,21 +3504,21 @@ test "enum literals with switch" { some condition is no longer true.

{#code_begin|test|while#} -const assert = @import("std").debug.assert; +const expect = @import("std").testing.expect; test "while basic" { var i: usize = 0; while (i < 10) { i += 1; } - assert(i == 10); + expect(i == 10); } {#code_end#}

Use {#syntax#}break{#endsyntax#} to exit a while loop early.

{#code_begin|test|while#} -const assert = @import("std").debug.assert; +const expect = @import("std").testing.expect; test "while break" { var i: usize = 0; @@ -3527,14 +3527,14 @@ test "while break" { break; i += 1; } - assert(i == 10); + expect(i == 10); } {#code_end#}

Use {#syntax#}continue{#endsyntax#} to jump back to the beginning of the loop.

{#code_begin|test|while#} -const assert = @import("std").debug.assert; +const expect = @import("std").testing.expect; test "while continue" { var i: usize = 0; @@ -3544,7 +3544,7 @@ test "while continue" { continue; break; } - assert(i == 10); + expect(i == 10); } {#code_end#}

@@ -3552,12 +3552,12 @@ test "while continue" { is continued. The {#syntax#}continue{#endsyntax#} keyword respects this expression.

{#code_begin|test|while#} -const assert = @import("std").debug.assert; +const expect = @import("std").testing.expect; test "while loop continue expression" { var i: usize = 0; while (i < 10) : (i += 1) {} - assert(i == 10); + expect(i == 10); } test "while loop continue expression, more complicated" { @@ -3565,7 +3565,7 @@ test "while loop continue expression, more complicated" { var j: usize = 1; while (i * j < 2000) : ({ i *= 2; j *= 3; }) { const my_ij = i * j; - assert(my_ij < 2000); + expect(my_ij < 2000); } } {#code_end#} @@ -3581,11 +3581,11 @@ test "while loop continue expression, more complicated" { evaluated.

{#code_begin|test|while#} -const assert = @import("std").debug.assert; +const expect = @import("std").testing.expect; test "while else" { - assert(rangeHasNumber(0, 10, 5)); - assert(!rangeHasNumber(0, 10, 15)); + expect(rangeHasNumber(0, 10, 5)); + expect(!rangeHasNumber(0, 10, 15)); } fn rangeHasNumber(begin: usize, end: usize, number: usize) bool { @@ -3634,7 +3634,7 @@ test "nested continue" { be executed on the first null value encountered.

{#code_begin|test|while#} -const assert = @import("std").debug.assert; +const expect = @import("std").testing.expect; test "while null capture" { var sum1: u32 = 0; @@ -3642,14 +3642,14 @@ test "while null capture" { while (eventuallyNullSequence()) |value| { sum1 += value; } - assert(sum1 == 3); + expect(sum1 == 3); var sum2: u32 = 0; numbers_left = 3; while (eventuallyNullSequence()) |value| { sum2 += value; } else { - assert(sum2 == 3); + expect(sum2 == 3); } } @@ -3676,7 +3676,7 @@ fn eventuallyNullSequence() ?u32 { the while condition must have an {#link|Error Union Type#}.

{#code_begin|test|while#} -const assert = @import("std").debug.assert; +const expect = @import("std").testing.expect; test "while error union capture" { var sum1: u32 = 0; @@ -3684,7 +3684,7 @@ test "while error union capture" { while (eventuallyErrorSequence()) |value| { sum1 += value; } else |err| { - assert(err == error.ReachedZero); + expect(err == error.ReachedZero); } } @@ -3706,7 +3706,7 @@ fn eventuallyErrorSequence() anyerror!u32 { such as use types as first class values.

{#code_begin|test#} -const assert = @import("std").debug.assert; +const expect = @import("std").testing.expect; test "inline while loop" { comptime var i = 0; @@ -3720,7 +3720,7 @@ test "inline while loop" { }; sum += typeNameLength(T); } - assert(sum == 9); + expect(sum == 9); } fn typeNameLength(comptime T: type) usize { @@ -3741,7 +3741,7 @@ fn typeNameLength(comptime T: type) usize { {#header_close#} {#header_open|for#} {#code_begin|test|for#} -const assert = @import("std").debug.assert; +const expect = @import("std").testing.expect; test "for basics" { const items = [_]i32 { 4, 5, 3, 4, 0 }; @@ -3755,22 +3755,22 @@ test "for basics" { } sum += value; } - assert(sum == 16); + expect(sum == 16); // To iterate over a portion of a slice, reslice. for (items[0..1]) |value| { sum += value; } - assert(sum == 20); + expect(sum == 20); // To access the index of iteration, specify a second capture value. // This is zero-indexed. var sum2: i32 = 0; for (items) |value, i| { - assert(@TypeOf(i) == usize); + expect(@TypeOf(i) == usize); sum2 += @intCast(i32, i); } - assert(sum2 == 10); + expect(sum2 == 10); } test "for reference" { @@ -3782,9 +3782,9 @@ test "for reference" { value.* += 1; } - assert(items[0] == 4); - assert(items[1] == 5); - assert(items[2] == 3); + expect(items[0] == 4); + expect(items[1] == 5); + expect(items[2] == 3); } test "for else" { @@ -3799,10 +3799,10 @@ test "for else" { sum += value.?; } } else blk: { - assert(sum == 12); + expect(sum == 12); break :blk sum; }; - assert(result == 12); + expect(result == 12); } {#code_end#} {#header_open|Labeled for#} @@ -3810,7 +3810,7 @@ test "for else" { or {#syntax#}continue{#endsyntax#} from within a nested loop:

{#code_begin|test#} const std = @import("std"); -const assert = std.debug.assert; +const expect = std.testing.expect; test "nested break" { var count: usize = 0; @@ -3820,7 +3820,7 @@ test "nested break" { break :outer; } } - assert(count == 1); + expect(count == 1); } test "nested continue" { @@ -3832,7 +3832,7 @@ test "nested continue" { } } - assert(count == 8); + expect(count == 8); } {#code_end#} {#header_close#} @@ -3845,7 +3845,7 @@ test "nested continue" { compile-time known.

{#code_begin|test#} -const assert = @import("std").debug.assert; +const expect = @import("std").testing.expect; test "inline for loop" { const nums = [_]i32{2, 4, 6}; @@ -3859,7 +3859,7 @@ test "inline for loop" { }; sum += typeNameLength(T); } - assert(sum == 9); + expect(sum == 9); } fn typeNameLength(comptime T: type) usize { @@ -3885,14 +3885,14 @@ fn typeNameLength(comptime T: type) usize { // * ?T // * anyerror!T -const assert = @import("std").debug.assert; +const expect = @import("std").testing.expect; test "if expression" { // If expressions are used instead of a ternary expression. const a: u32 = 5; const b: u32 = 4; const result = if (a != b) 47 else 3089; - assert(result == 47); + expect(result == 47); } test "if boolean" { @@ -3900,7 +3900,7 @@ test "if boolean" { const a: u32 = 5; const b: u32 = 4; if (a != b) { - assert(true); + expect(true); } else if (a == 9) { unreachable; } else { @@ -3913,7 +3913,7 @@ test "if optional" { const a: ?u32 = 0; if (a) |value| { - assert(value == 0); + expect(value == 0); } else { unreachable; } @@ -3922,17 +3922,17 @@ test "if optional" { if (b) |value| { unreachable; } else { - assert(true); + expect(true); } // The else is not required. if (a) |value| { - assert(value == 0); + expect(value == 0); } // To test against null only, use the binary equality operator. if (b == null) { - assert(true); + expect(true); } // Access the value by reference using a pointer capture. @@ -3942,7 +3942,7 @@ test "if optional" { } if (c) |value| { - assert(value == 2); + expect(value == 2); } else { unreachable; } @@ -3954,7 +3954,7 @@ test "if error union" { const a: anyerror!u32 = 0; if (a) |value| { - assert(value == 0); + expect(value == 0); } else |err| { unreachable; } @@ -3963,17 +3963,17 @@ test "if error union" { if (b) |value| { unreachable; } else |err| { - assert(err == error.BadValue); + expect(err == error.BadValue); } // The else and |err| capture is strictly required. if (a) |value| { - assert(value == 0); + expect(value == 0); } else |_| {} // To check only the error value, use an empty block expression. if (b) |_| {} else |err| { - assert(err == error.BadValue); + expect(err == error.BadValue); } // Access the value by reference using a pointer capture. @@ -3985,7 +3985,7 @@ test "if error union" { } if (c) |value| { - assert(value == 9); + expect(value == 9); } else |err| { unreachable; } @@ -3997,14 +3997,14 @@ test "if error union with optional" { const a: anyerror!?u32 = 0; if (a) |optional_value| { - assert(optional_value.? == 0); + expect(optional_value.? == 0); } else |err| { unreachable; } const b: anyerror!?u32 = null; if (b) |optional_value| { - assert(optional_value == null); + expect(optional_value == null); } else |err| { unreachable; } @@ -4013,7 +4013,7 @@ test "if error union with optional" { if (c) |optional_value| { unreachable; } else |err| { - assert(err == error.BadValue); + expect(err == error.BadValue); } // Access the value by reference by using a pointer capture each time. @@ -4027,7 +4027,7 @@ test "if error union with optional" { } if (d) |optional_value| { - assert(optional_value.? == 9); + expect(optional_value.? == 9); } else |err| { unreachable; } @@ -4038,7 +4038,7 @@ test "if error union with optional" { {#header_open|defer#} {#code_begin|test|defer#} const std = @import("std"); -const assert = std.debug.assert; +const expect = std.testing.expect; const print = std.debug.print; // defer will execute an expression at the end of the current scope. @@ -4049,14 +4049,14 @@ fn deferExample() usize { defer a = 2; a = 1; } - assert(a == 2); + expect(a == 2); a = 5; return a; } test "defer basics" { - assert(deferExample() == 5); + expect(deferExample() == 5); } // If multiple defer statements are specified, they will be executed in @@ -4133,8 +4133,9 @@ test "basic math" { } } {#code_end#} -

In fact, this is how assert is implemented:

+

In fact, this is how {#syntax#}std.debug.assert{#endsyntax#} is implemented:

{#code_begin|test_err#} +// This is how std.debug.assert is implemented fn assert(ok: bool) void { if (!ok) unreachable; // assertion failure } @@ -4193,19 +4194,19 @@ pub extern "kernel32" fn ExitProcess(exit_code: c_uint) callconv(.Stdcall) noret test "foo" { const value = bar() catch ExitProcess(1); - assert(value == 1234); + expect(value == 1234); } fn bar() anyerror!u32 { return 1234; } -const assert = @import("std").debug.assert; +const expect = @import("std").testing.expect; {#code_end#} {#header_close#} {#header_open|Functions#} {#code_begin|test|functions#} -const assert = @import("std").debug.assert; +const expect = @import("std").testing.expect; // Functions are declared like this fn add(a: i8, b: i8) i8 { @@ -4256,17 +4257,17 @@ fn do_op(fn_call: call2_op, op1: i8, op2: i8) i8 { } test "function" { - assert(do_op(add, 5, 6) == 11); - assert(do_op(sub2, 5, 6) == -1); + expect(do_op(add, 5, 6) == 11); + expect(do_op(sub2, 5, 6) == -1); } {#code_end#}

Function values are like pointers:

{#code_begin|obj#} -const assert = @import("std").debug.assert; +const expect = @import("std").testing.expect; comptime { - assert(@TypeOf(foo) == fn()void); - assert(@sizeOf(fn()void) == @sizeOf(?fn()void)); + expect(@TypeOf(foo) == fn()void); + expect(@sizeOf(fn()void) == @sizeOf(?fn()void)); } fn foo() void { } @@ -4298,10 +4299,10 @@ fn foo(point: Point) i32 { return point.x + point.y; } -const assert = @import("std").debug.assert; +const expect = @import("std").testing.expect; test "pass struct to function" { - assert(foo(Point{ .x = 1, .y = 2 }) == 3); + expect(foo(Point{ .x = 1, .y = 2 }) == 3); } {#code_end#}

@@ -4315,29 +4316,29 @@ test "pass struct to function" { Use {#link|@TypeOf#} and {#link|@typeInfo#} to get information about the inferred type.

{#code_begin|test#} -const assert = @import("std").debug.assert; +const expect = @import("std").testing.expect; fn addFortyTwo(x: anytype) @TypeOf(x) { return x + 42; } test "fn type inference" { - assert(addFortyTwo(1) == 43); - assert(@TypeOf(addFortyTwo(1)) == comptime_int); + expect(addFortyTwo(1) == 43); + expect(@TypeOf(addFortyTwo(1)) == comptime_int); var y: i64 = 2; - assert(addFortyTwo(y) == 44); - assert(@TypeOf(addFortyTwo(y)) == i64); + expect(addFortyTwo(y) == 44); + expect(@TypeOf(addFortyTwo(y)) == i64); } {#code_end#} {#header_close#} {#header_open|Function Reflection#} {#code_begin|test#} -const assert = @import("std").debug.assert; +const expect = @import("std").testing.expect; test "fn reflection" { - assert(@typeInfo(@TypeOf(assert)).Fn.return_type.? == void); - assert(@typeInfo(@TypeOf(assert)).Fn.is_var_args == false); + expect(@typeInfo(@TypeOf(expect)).Fn.return_type.? == void); + expect(@typeInfo(@TypeOf(expect)).Fn.is_var_args == false); } {#code_end#} {#header_close#} @@ -4372,7 +4373,7 @@ const AllocationError = error { test "coerce subset to superset" { const err = foo(AllocationError.OutOfMemory); - std.debug.assert(err == FileOpenError.OutOfMemory); + std.testing.expect(err == FileOpenError.OutOfMemory); } fn foo(err: AllocationError) FileOpenError { @@ -4480,7 +4481,7 @@ fn charToDigit(c: u8) u8 { test "parse u64" { const result = try parseU64("1234", 10); - std.debug.assert(result == 1234); + std.testing.expect(result == 1234); } {#code_end#}

@@ -4625,7 +4626,7 @@ fn createFoo(param: i32) !Foo {

An error union is created with the {#syntax#}!{#endsyntax#} binary operator. You can use compile-time reflection to access the child type of an error union:

{#code_begin|test#} -const assert = @import("std").debug.assert; +const expect = @import("std").testing.expect; test "error union" { var foo: anyerror!i32 = undefined; @@ -4637,10 +4638,10 @@ test "error union" { foo = error.SomeError; // Use compile-time reflection to access the payload type of an error union: - comptime assert(@typeInfo(@TypeOf(foo)).ErrorUnion.payload == i32); + comptime expect(@typeInfo(@TypeOf(foo)).ErrorUnion.payload == i32); // Use compile-time reflection to access the error set type of an error union: - comptime assert(@typeInfo(@TypeOf(foo)).ErrorUnion.error_set == anyerror); + comptime expect(@typeInfo(@TypeOf(foo)).ErrorUnion.error_set == anyerror); } {#code_end#} {#header_open|Merging Error Sets#} @@ -5007,7 +5008,7 @@ fn doAThing(optional_foo: ?*Foo) void {

An optional is created by putting {#syntax#}?{#endsyntax#} in front of a type. You can use compile-time reflection to access the child type of an optional:

{#code_begin|test#} -const assert = @import("std").debug.assert; +const expect = @import("std").testing.expect; test "optional type" { // Declare an optional and coerce from null: @@ -5017,7 +5018,7 @@ test "optional type" { foo = 1234; // Use compile-time reflection to access the child type of the optional: - comptime assert(@typeInfo(@TypeOf(foo)).Optional.child == i32); + comptime expect(@typeInfo(@TypeOf(foo)).Optional.child == i32); } {#code_end#} {#header_close#} @@ -5034,7 +5035,7 @@ const optional_value: ?i32 = null;

An optional pointer is guaranteed to be the same size as a pointer. The {#syntax#}null{#endsyntax#} of the optional is guaranteed to be address 0.

{#code_begin|test#} -const assert = @import("std").debug.assert; +const expect = @import("std").testing.expect; test "optional pointers" { // Pointers cannot be null. If you want a null pointer, use the optional @@ -5044,11 +5045,11 @@ test "optional pointers" { var x: i32 = 1; ptr = &x; - assert(ptr.?.* == 1); + expect(ptr.?.* == 1); // Optional pointers are the same size as normal pointers, because pointer // value 0 is used as the null value. - assert(@sizeOf(?*i32) == @sizeOf(*i32)); + expect(@sizeOf(?*i32) == @sizeOf(*i32)); } {#code_end#} {#header_close#} @@ -5115,13 +5116,13 @@ fn foo(a: *const i32) void {}

{#code_begin|test#} const std = @import("std"); -const assert = std.debug.assert; +const expect = std.testing.expect; const mem = std.mem; test "cast *[1][*]const u8 to [*]const ?[*]const u8" { const window_name = [1][*]const u8{"window name"}; const x: [*]const ?[*]const u8 = &window_name; - assert(mem.eql(u8, std.mem.spanZ(@ptrCast([*:0]const u8, x[0].?)), "window name")); + expect(mem.eql(u8, std.mem.spanZ(@ptrCast([*:0]const u8, x[0].?)), "window name")); } {#code_end#} {#header_close#} @@ -5132,7 +5133,7 @@ test "cast *[1][*]const u8 to [*]const ?[*]const u8" {

{#code_begin|test#} const std = @import("std"); -const assert = std.debug.assert; +const expect = std.testing.expect; const mem = std.mem; test "integer widening" { @@ -5142,13 +5143,13 @@ test "integer widening" { var d: u64 = c; var e: u64 = d; var f: u128 = e; - assert(f == a); + expect(f == a); } test "implicit unsigned integer to signed integer" { var a: u8 = 250; var b: i16 = a; - assert(b == 250); + expect(b == 250); } test "float widening" { @@ -5160,7 +5161,7 @@ test "float widening" { var b: f32 = a; var c: f64 = b; var d: f128 = c; - assert(d == a); + expect(d == a); } {#code_end#} {#header_close#} @@ -5183,7 +5184,7 @@ test "implicit cast to comptime_int" { {#header_open|Type Coercion: Arrays and Pointers#} {#code_begin|test|coerce_arrays_and_ptrs#} const std = @import("std"); -const assert = std.debug.assert; +const expect = std.testing.expect; // This cast exists primarily so that string literals can be // passed to functions that accept const slices. However @@ -5192,41 +5193,41 @@ const assert = std.debug.assert; test "[N]T to []const T" { var x1: []const u8 = "hello"; var x2: []const u8 = &[5]u8{ 'h', 'e', 'l', 'l', 111 }; - assert(std.mem.eql(u8, x1, x2)); + expect(std.mem.eql(u8, x1, x2)); var y: []const f32 = &[2]f32{ 1.2, 3.4 }; - assert(y[0] == 1.2); + expect(y[0] == 1.2); } // Likewise, it works when the destination type is an error union. test "[N]T to E![]const T" { var x1: anyerror![]const u8 = "hello"; var x2: anyerror![]const u8 = &[5]u8{ 'h', 'e', 'l', 'l', 111 }; - assert(std.mem.eql(u8, try x1, try x2)); + expect(std.mem.eql(u8, try x1, try x2)); var y: anyerror![]const f32 = &[2]f32{ 1.2, 3.4 }; - assert((try y)[0] == 1.2); + expect((try y)[0] == 1.2); } // Likewise, it works when the destination type is an optional. test "[N]T to ?[]const T" { var x1: ?[]const u8 = "hello"; var x2: ?[]const u8 = &[5]u8{ 'h', 'e', 'l', 'l', 111 }; - assert(std.mem.eql(u8, x1.?, x2.?)); + expect(std.mem.eql(u8, x1.?, x2.?)); var y: ?[]const f32 = &[2]f32{ 1.2, 3.4 }; - assert(y.?[0] == 1.2); + expect(y.?[0] == 1.2); } // In this cast, the array length becomes the slice length. test "*[N]T to []T" { var buf: [5]u8 = "hello".*; const x: []u8 = &buf; - assert(std.mem.eql(u8, x, "hello")); + expect(std.mem.eql(u8, x, "hello")); const buf2 = [2]f32{ 1.2, 3.4 }; const x2: []const f32 = &buf2; - assert(std.mem.eql(f32, x2, &[2]f32{ 1.2, 3.4 })); + expect(std.mem.eql(f32, x2, &[2]f32{ 1.2, 3.4 })); } // Single-item pointers to arrays can be coerced to @@ -5234,7 +5235,7 @@ test "*[N]T to []T" { test "*[N]T to [*]T" { var buf: [5]u8 = "hello".*; const x: [*]u8 = &buf; - assert(x[4] == 'o'); + expect(x[4] == 'o'); // x[5] would be an uncaught out of bounds pointer dereference! } @@ -5242,7 +5243,7 @@ test "*[N]T to [*]T" { test "*[N]T to ?[*]T" { var buf: [5]u8 = "hello".*; const x: ?[*]u8 = &buf; - assert(x.?[4] == 'o'); + expect(x.?[4] == 'o'); } // Single-item pointers can be cast to len-1 single-item arrays. @@ -5250,7 +5251,7 @@ test "*T to *[1]T" { var x: i32 = 1234; const y: *[1]i32 = &x; const z: [*]i32 = y; - assert(z[0] == 1234); + expect(z[0] == 1234); } {#code_end#} {#see_also|C Pointers#} @@ -5261,27 +5262,27 @@ test "*T to *[1]T" {

{#code_begin|test#} const std = @import("std"); -const assert = std.debug.assert; +const expect = std.testing.expect; test "coerce to optionals" { const x: ?i32 = 1234; const y: ?i32 = null; - assert(x.? == 1234); - assert(y == null); + expect(x.? == 1234); + expect(y == null); } {#code_end#}

It works nested inside the {#link|Error Union Type#}, too:

{#code_begin|test#} const std = @import("std"); -const assert = std.debug.assert; +const expect = std.testing.expect; test "coerce to optionals wrapped in error union" { const x: anyerror!?i32 = 1234; const y: anyerror!?i32 = null; - assert((try x).? == 1234); - assert((try y) == null); + expect((try x).? == 1234); + expect((try y) == null); } {#code_end#} {#header_close#} @@ -5291,13 +5292,13 @@ test "coerce to optionals wrapped in error union" {

{#code_begin|test#} const std = @import("std"); -const assert = std.debug.assert; +const expect = std.testing.expect; test "coercion to error unions" { const x: anyerror!i32 = 1234; const y: anyerror!i32 = error.Failure; - assert((try x) == 1234); + expect((try x) == 1234); std.testing.expectError(error.Failure, y); } {#code_end#} @@ -5308,12 +5309,12 @@ test "coercion to error unions" {

{#code_begin|test#} const std = @import("std"); -const assert = std.debug.assert; +const expect = std.testing.expect; test "coercing large integer type to smaller one when value is comptime known to fit" { const x: u64 = 255; const y: u8 = x; - assert(y == 255); + expect(y == 255); } {#code_end#} {#header_close#} @@ -5324,7 +5325,7 @@ test "coercing large integer type to smaller one when value is comptime known to

{#code_begin|test#} const std = @import("std"); -const assert = std.debug.assert; +const expect = std.testing.expect; const E = enum { one, @@ -5341,11 +5342,11 @@ const U = union(E) { test "coercion between unions and enums" { var u = U{ .two = 12.34 }; var e: E = u; - assert(e == E.two); + expect(e == E.two); const three = E.three; var another_u: U = three; - assert(another_u == E.three); + expect(another_u == E.three); } {#code_end#} {#see_also|union|enum#} @@ -5411,22 +5412,22 @@ test "coercion of zero bit types" {

{#code_begin|test|peer_type_resolution#} const std = @import("std"); -const assert = std.debug.assert; +const expect = std.testing.expect; const mem = std.mem; test "peer resolve int widening" { var a: i8 = 12; var b: i16 = 34; var c = a + b; - assert(c == 46); - assert(@TypeOf(c) == i16); + expect(c == 46); + expect(@TypeOf(c) == i16); } test "peer resolve arrays of different size to const slice" { - assert(mem.eql(u8, boolToStr(true), "true")); - assert(mem.eql(u8, boolToStr(false), "false")); - comptime assert(mem.eql(u8, boolToStr(true), "true")); - comptime assert(mem.eql(u8, boolToStr(false), "false")); + expect(mem.eql(u8, boolToStr(true), "true")); + expect(mem.eql(u8, boolToStr(false), "false")); + comptime expect(mem.eql(u8, boolToStr(true), "true")); + comptime expect(mem.eql(u8, boolToStr(false), "false")); } fn boolToStr(b: bool) []const u8 { return if (b) "true" else "false"; @@ -5439,16 +5440,16 @@ test "peer resolve array and const slice" { fn testPeerResolveArrayConstSlice(b: bool) void { const value1 = if (b) "aoeu" else @as([]const u8, "zz"); const value2 = if (b) @as([]const u8, "zz") else "aoeu"; - assert(mem.eql(u8, value1, "aoeu")); - assert(mem.eql(u8, value2, "zz")); + expect(mem.eql(u8, value1, "aoeu")); + expect(mem.eql(u8, value2, "zz")); } test "peer type resolution: ?T and T" { - assert(peerTypeTAndOptionalT(true, false).? == 0); - assert(peerTypeTAndOptionalT(false, false).? == 3); + expect(peerTypeTAndOptionalT(true, false).? == 0); + expect(peerTypeTAndOptionalT(false, false).? == 3); comptime { - assert(peerTypeTAndOptionalT(true, false).? == 0); - assert(peerTypeTAndOptionalT(false, false).? == 3); + expect(peerTypeTAndOptionalT(true, false).? == 0); + expect(peerTypeTAndOptionalT(false, false).? == 3); } } fn peerTypeTAndOptionalT(c: bool, b: bool) ?usize { @@ -5460,11 +5461,11 @@ fn peerTypeTAndOptionalT(c: bool, b: bool) ?usize { } test "peer type resolution: *[0]u8 and []const u8" { - assert(peerTypeEmptyArrayAndSlice(true, "hi").len == 0); - assert(peerTypeEmptyArrayAndSlice(false, "hi").len == 1); + expect(peerTypeEmptyArrayAndSlice(true, "hi").len == 0); + expect(peerTypeEmptyArrayAndSlice(false, "hi").len == 1); comptime { - assert(peerTypeEmptyArrayAndSlice(true, "hi").len == 0); - assert(peerTypeEmptyArrayAndSlice(false, "hi").len == 1); + expect(peerTypeEmptyArrayAndSlice(true, "hi").len == 0); + expect(peerTypeEmptyArrayAndSlice(false, "hi").len == 1); } } fn peerTypeEmptyArrayAndSlice(a: bool, slice: []const u8) []const u8 { @@ -5478,14 +5479,14 @@ test "peer type resolution: *[0]u8, []const u8, and anyerror![]u8" { { var data = "hi".*; const slice = data[0..]; - assert((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0); - assert((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1); + expect((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0); + expect((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1); } comptime { var data = "hi".*; const slice = data[0..]; - assert((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0); - assert((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1); + expect((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0); + expect((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1); } } fn peerTypeEmptyArrayAndSliceAndError(a: bool, slice: []u8) anyerror![]u8 { @@ -5499,8 +5500,8 @@ fn peerTypeEmptyArrayAndSliceAndError(a: bool, slice: []u8) anyerror![]u8 { test "peer type resolution: *const T and ?*T" { const a = @intToPtr(*const usize, 0x123456780); const b = @intToPtr(?*usize, 0x123456780); - assert(a == b); - assert(b == a); + expect(a == b); + expect(b == a); } {#code_end#} {#header_close#} @@ -5547,7 +5548,7 @@ export fn entry() void {

{#code_begin|test#} const std = @import("std"); -const assert = std.debug.assert; +const expect = std.testing.expect; test "turn HashMap into a set with void" { var map = std.AutoHashMap(i32, void).init(std.testing.allocator); @@ -5556,11 +5557,11 @@ test "turn HashMap into a set with void" { try map.put(1, {}); try map.put(2, {}); - assert(map.contains(2)); - assert(!map.contains(3)); + expect(map.contains(2)); + expect(!map.contains(3)); _ = map.remove(2); - assert(!map.contains(2)); + expect(!map.contains(2)); } {#code_end#}

Note that this is different from using a dummy value for the hash map value. @@ -5607,7 +5608,7 @@ fn foo() i32 {

Pointers to zero bit types also have zero bits. They always compare equal to each other:

{#code_begin|test#} const std = @import("std"); -const assert = std.debug.assert; +const expect = std.testing.expect; test "pointer to empty struct" { const Empty = struct {}; @@ -5615,7 +5616,7 @@ test "pointer to empty struct" { var b = Empty{}; var ptr_a = &a; var ptr_b = &b; - comptime assert(ptr_a == ptr_b); + comptime expect(ptr_a == ptr_b); } {#code_end#}

The type being pointed to can only ever be one value; therefore loads and stores are @@ -5650,7 +5651,7 @@ test "@intToPtr for pointer to zero bit type" { usingnamespace @import("std"); test "using std namespace" { - debug.assert(true); + testing.expect(true); } {#code_end#}

@@ -5762,7 +5763,7 @@ fn max(comptime T: type, a: T, b: T) T { } } test "try to compare bools" { - @import("std").debug.assert(max(bool, false, true) == true); + @import("std").testing.expect(max(bool, false, true) == true); } {#code_end#}

@@ -5802,7 +5803,7 @@ fn max(a: bool, b: bool) bool { For example:

{#code_begin|test|comptime_vars#} -const assert = @import("std").debug.assert; +const expect = @import("std").testing.expect; const CmdFn = struct { name: []const u8, @@ -5830,9 +5831,9 @@ fn performFn(comptime prefix_char: u8, start_value: i32) i32 { } test "perform fn" { - assert(performFn('t', 1) == 6); - assert(performFn('o', 0) == 1); - assert(performFn('w', 99) == 99); + expect(performFn('t', 1) == 6); + expect(performFn('o', 0) == 1); + expect(performFn('w', 99) == 99); } {#code_end#}

@@ -5843,7 +5844,7 @@ test "perform fn" {

{#code_begin|syntax#} // From the line: -// assert(performFn('t', 1) == 6); +// expect(performFn('t', 1) == 6); fn performFn(start_value: i32) i32 { var result: i32 = start_value; result = two(result); @@ -5853,7 +5854,7 @@ fn performFn(start_value: i32) i32 { {#code_end#} {#code_begin|syntax#} // From the line: -// assert(performFn('o', 0) == 1); +// expect(performFn('o', 0) == 1); fn performFn(start_value: i32) i32 { var result: i32 = start_value; result = one(result); @@ -5862,7 +5863,7 @@ fn performFn(start_value: i32) i32 { {#code_end#} {#code_begin|syntax#} // From the line: -// assert(performFn('w', 99) == 99); +// expect(performFn('w', 99) == 99); fn performFn(start_value: i32) i32 { var result: i32 = start_value; return result; @@ -5915,7 +5916,7 @@ test "foo" { Let's look at an example:

{#code_begin|test#} -const assert = @import("std").debug.assert; +const expect = @import("std").testing.expect; fn fibonacci(index: u32) u32 { if (index < 2) return index; @@ -5924,11 +5925,11 @@ fn fibonacci(index: u32) u32 { test "fibonacci" { // test fibonacci at run-time - assert(fibonacci(7) == 13); + expect(fibonacci(7) == 13); // test fibonacci at compile-time comptime { - assert(fibonacci(7) == 13); + expect(fibonacci(7) == 13); } } {#code_end#} @@ -5936,7 +5937,7 @@ test "fibonacci" { Imagine if we had forgotten the base case of the recursive function and tried to run the tests:

{#code_begin|test_err|operation caused overflow#} -const assert = @import("std").debug.assert; +const expect = @import("std").testing.expect; fn fibonacci(index: u32) u32 { //if (index < 2) return index; @@ -5945,7 +5946,7 @@ fn fibonacci(index: u32) u32 { test "fibonacci" { comptime { - assert(fibonacci(7) == 13); + expect(fibonacci(7) == 13); } } {#code_end#} @@ -5959,7 +5960,7 @@ test "fibonacci" { But what would have happened if we used a signed integer?

{#code_begin|test_err|evaluation exceeded 1000 backwards branches#} -const assert = @import("std").debug.assert; +const expect = @import("std").testing.expect; fn fibonacci(index: i32) i32 { //if (index < 2) return index; @@ -5968,7 +5969,7 @@ fn fibonacci(index: i32) i32 { test "fibonacci" { comptime { - assert(fibonacci(7) == 13); + expect(fibonacci(7) == 13); } } {#code_end#} @@ -5979,10 +5980,10 @@ test "fibonacci" { {#link|@setEvalBranchQuota#} to change the default number 1000 to something else.

- What if we fix the base case, but put the wrong value in the {#syntax#}assert{#endsyntax#} line? + What if we fix the base case, but put the wrong value in the {#syntax#}expect{#endsyntax#} line?

- {#code_begin|test_err|unable to evaluate constant expression#} -const assert = @import("std").debug.assert; + {#code_begin|test_err|encountered @panic at compile-time#} +const expect = @import("std").testing.expect; fn fibonacci(index: i32) i32 { if (index < 2) return index; @@ -5991,16 +5992,15 @@ fn fibonacci(index: i32) i32 { test "fibonacci" { comptime { - assert(fibonacci(7) == 99999); + expect(fibonacci(7) == 99999); } } {#code_end#}

- What happened is Zig started interpreting the {#syntax#}assert{#endsyntax#} function with the + What happened is Zig started interpreting the {#syntax#}expect{#endsyntax#} function with the parameter {#syntax#}ok{#endsyntax#} set to {#syntax#}false{#endsyntax#}. When the interpreter hit - {#syntax#}unreachable{#endsyntax#} it emitted a compile error, because reaching unreachable - code is undefined behavior, and undefined behavior causes a compile error if it is detected - at compile-time. + {#syntax#}@panic{#endsyntax#} it emitted a compile error because a panic during compile + causes a compile error if it is detected at compile-time.

@@ -6042,7 +6042,7 @@ fn sum(numbers: []const i32) i32 { } test "variable values" { - @import("std").debug.assert(sum_of_first_25_primes == 1060); + @import("std").testing.expect(sum_of_first_25_primes == 1060); } {#code_end#}

@@ -6435,7 +6435,7 @@ volatile ( {#code_begin|test|global-asm#} {#target_linux_x86_64#} const std = @import("std"); -const assert = std.debug.assert; +const expect = std.testing.expect; comptime { asm ( @@ -6450,7 +6450,7 @@ comptime { extern fn my_func(a: i32, b: i32) i32; test "global assembly" { - assert(my_func(12, 34) == 46); + expect(my_func(12, 34) == 46); } {#code_end#} {#header_close#} @@ -6485,13 +6485,13 @@ test "global assembly" {

{#code_begin|test#} const std = @import("std"); -const assert = std.debug.assert; +const expect = std.testing.expect; var x: i32 = 1; test "suspend with no resume" { var frame = async func(); - assert(x == 2); + expect(x == 2); } fn func() void { @@ -6511,21 +6511,21 @@ fn func() void {

{#code_begin|test#} const std = @import("std"); -const assert = std.debug.assert; +const expect = std.testing.expect; var the_frame: anyframe = undefined; var result = false; test "async function suspend with block" { _ = async testSuspendBlock(); - assert(!result); + expect(!result); resume the_frame; - assert(result); + expect(result); } fn testSuspendBlock() void { suspend { - comptime assert(@TypeOf(@frame()) == *@Frame(testSuspendBlock)); + comptime expect(@TypeOf(@frame()) == *@Frame(testSuspendBlock)); the_frame = @frame(); } result = true; @@ -6549,12 +6549,12 @@ fn testSuspendBlock() void {

{#code_begin|test#} const std = @import("std"); -const assert = std.debug.assert; +const expect = std.testing.expect; test "resume from suspend" { var my_result: i32 = 1; _ = async testResumeFromSuspend(&my_result); - std.debug.assert(my_result == 2); + std.testing.expect(my_result == 2); } fn testResumeFromSuspend(my_result: *i32) void { suspend { @@ -6578,7 +6578,7 @@ fn testResumeFromSuspend(my_result: *i32) void {

{#code_begin|test#} const std = @import("std"); -const assert = std.debug.assert; +const expect = std.testing.expect; test "async and await" { // Here we have an exception where we do not match an async @@ -6592,7 +6592,7 @@ test "async and await" { fn amain() void { var frame = async func(); - comptime assert(@TypeOf(frame) == @Frame(func)); + comptime expect(@TypeOf(frame) == @Frame(func)); const ptr: anyframe->void = &frame; const any_ptr: anyframe = ptr; @@ -6622,7 +6622,7 @@ fn func() void {

{#code_begin|test#} const std = @import("std"); -const assert = std.debug.assert; +const expect = std.testing.expect; var the_frame: anyframe = undefined; var final_result: i32 = 0; @@ -6633,8 +6633,8 @@ test "async function await" { seq('f'); resume the_frame; seq('i'); - assert(final_result == 1234); - assert(std.mem.eql(u8, &seq_points, "abcdefghi")); + expect(final_result == 1234); + expect(std.mem.eql(u8, &seq_points, "abcdefghi")); } fn amain() void { seq('b'); @@ -6848,9 +6848,9 @@ fn readFile(allocator: *Allocator, filename: []const u8) ![]u8 { for the current target to match the C ABI. When the child type of a pointer has this alignment, the alignment can be omitted from the type.

-
{#syntax#}const assert = @import("std").debug.assert;
+      
{#syntax#}const expect = @import("std").testing.expect;
 comptime {
-    assert(*u32 == *align(@alignOf(u32)) u32);
+    expect(*u32 == *align(@alignOf(u32)) u32);
 }{#endsyntax#}

The result is a target-specific compile time constant. It is guaranteed to be @@ -6886,7 +6886,7 @@ comptime {

{#code_begin|test#} const std = @import("std"); -const assert = std.debug.assert; +const expect = std.testing.expect; test "async fn pointer in a struct field" { var data: i32 = 1; @@ -6896,9 +6896,9 @@ test "async fn pointer in a struct field" { var foo = Foo{ .bar = func }; var bytes: [64]u8 align(@alignOf(@Frame(func))) = undefined; const f = @asyncCall(&bytes, {}, foo.bar, .{&data}); - assert(data == 2); + expect(data == 2); resume f; - assert(data == 4); + expect(data == 4); } fn func(y: *i32) void { @@ -7082,10 +7082,10 @@ fn func(y: *i32) void { Calls a function, in the same way that invoking an expression with parentheses does:

{#code_begin|test|call#} -const assert = @import("std").debug.assert; +const expect = @import("std").testing.expect; test "noinline function call" { - assert(@call(.{}, add, .{3, 9}) == 12); + expect(@call(.{}, add, .{3, 9}) == 12); } fn add(a: i32, b: i32) i32 { @@ -7544,14 +7544,14 @@ const Point = struct { }; test "field access by string" { - const assert = std.debug.assert; + const expect = std.testing.expect; var p = Point {.x = 0, .y = 0}; @field(p, "x") = 4; @field(p, "y") = @field(p, "x") + 1; - assert(@field(p, "x") == 4); - assert(@field(p, "y") == 5); + expect(@field(p, "x") == 4); + expect(@field(p, "y") == 5); } {#code_end#} @@ -7657,7 +7657,7 @@ fn func() void {

{#code_begin|test#} const std = @import("std"); -const assert = std.debug.assert; +const expect = std.testing.expect; const Foo = struct { nope: i32, @@ -7667,16 +7667,16 @@ const Foo = struct { }; test "@hasDecl" { - assert(@hasDecl(Foo, "blah")); + expect(@hasDecl(Foo, "blah")); // Even though `hi` is private, @hasDecl returns true because this test is // in the same file scope as Foo. It would return false if Foo was declared // in a different file. - assert(@hasDecl(Foo, "hi")); + expect(@hasDecl(Foo, "hi")); // @hasDecl is for declarations; not fields. - assert(!@hasDecl(Foo, "nope")); - assert(!@hasDecl(Foo, "nope1234")); + expect(!@hasDecl(Foo, "nope")); + expect(!@hasDecl(Foo, "nope1234")); } {#code_end#} {#see_also|@hasField#} @@ -7851,14 +7851,14 @@ mem.set(u8, dest, c);{#endsyntax#}
{#code_begin|test#} const std = @import("std"); const builtin = @import("builtin"); -const assert = std.debug.assert; +const expect = std.testing.expect; test "@wasmMemoryGrow" { if (builtin.arch != .wasm32) return error.SkipZigTest; var prev = @wasmMemorySize(0); - assert(prev == @wasmMemoryGrow(0, 1)); - assert(prev + 1 == @wasmMemorySize(0)); + expect(prev == @wasmMemoryGrow(0, 1)); + expect(prev + 1 == @wasmMemorySize(0)); } {#code_end#} {#see_also|@wasmMemorySize#} @@ -8194,13 +8194,13 @@ test "@setRuntimeSafety" {

{#code_begin|test#} const std = @import("std"); -const assert = std.debug.assert; +const expect = std.testing.expect; test "vector @splat" { const scalar: u32 = 5; const result = @splat(4, scalar); - comptime assert(@TypeOf(result) == std.meta.Vector(4, u32)); - assert(std.mem.eql(u32, &@as([4]u32, result), &[_]u32{ 5, 5, 5, 5 })); + comptime expect(@TypeOf(result) == std.meta.Vector(4, u32)); + expect(std.mem.eql(u32, &@as([4]u32, result), &[_]u32{ 5, 5, 5, 5 })); } {#code_end#}

@@ -8410,12 +8410,12 @@ fn doTheTest() void {

{#code_begin|test#} const std = @import("std"); -const assert = std.debug.assert; +const expect = std.testing.expect; test "@This()" { var items = [_]i32{ 1, 2, 3, 4 }; const list = List(i32){ .items = items[0..] }; - assert(list.length() == 4); + expect(list.length() == 4); } fn List(comptime T: type) type { @@ -8456,12 +8456,12 @@ test "integer cast panic" {

{#code_begin|test|truncate#} const std = @import("std"); -const assert = std.debug.assert; +const expect = std.testing.expect; test "integer truncation" { var a: u16 = 0xabcd; var b: u8 = @truncate(u8, a); - assert(b == 0xcd); + expect(b == 0xcd); } {#code_end#}

@@ -8544,13 +8544,13 @@ test "integer truncation" {

{#code_begin|test#} const std = @import("std"); -const assert = std.debug.assert; +const expect = std.testing.expect; test "no runtime side effects" { var data: i32 = 0; const T = @TypeOf(foo(i32, &data)); - comptime assert(T == i32); - assert(data == 0); + comptime expect(T == i32); + expect(data == 0); } fn foo(comptime T: type, ptr: *T) T { @@ -8853,16 +8853,16 @@ pub fn main() void { {#code_begin|test#} const std = @import("std"); -const assert = std.debug.assert; +const expect = std.testing.expect; const minInt = std.math.minInt; const maxInt = std.math.maxInt; test "wraparound addition and subtraction" { const x: i32 = maxInt(i32); const min_val = x +% 1; - assert(min_val == minInt(i32)); + expect(min_val == minInt(i32)); const max_val = min_val -% 1; - assert(max_val == maxInt(i32)); + expect(max_val == maxInt(i32)); } {#code_end#} {#header_close#} @@ -9287,13 +9287,13 @@ pub fn main() void { {#code_begin|test|allocator#} const std = @import("std"); const Allocator = std.mem.Allocator; -const assert = std.debug.assert; +const expect = std.testing.expect; test "using an allocator" { var buffer: [100]u8 = undefined; const allocator = &std.heap.FixedBufferAllocator.init(&buffer).allocator; const result = try concat(allocator, "foo", "bar"); - assert(std.mem.eql(u8, "foobar", result)); + expect(std.mem.eql(u8, "foobar", result)); } fn concat(allocator: *Allocator, a: []const u8, b: []const u8) ![]u8 { @@ -9560,10 +9560,10 @@ const separator = if (builtin.os == builtin.Os.windows) '\\' else '/'; {#code_begin|test|detect_test#} const std = @import("std"); const builtin = std.builtin; -const assert = std.debug.assert; +const expect = std.testing.expect; test "builtin.is_test" { - assert(builtin.is_test); + expect(builtin.is_test); } {#code_end#}

@@ -9613,7 +9613,7 @@ test "assert in release fast mode" { const std = @import("std"); const expect = std.testing.expect; -test "assert in release fast mode" { +test "expect in release fast mode" { expect(false); } {#code_end#}