Testing cstrings returned from C code

Some points:

  1. Use defer to clean up.
  2. Use expectEqual instead of expect, it gives much better error messages displaying the expected and the actual value. The expected value is the first parameter and the actual is the second (last) parameter.
  3. Use slices to hold strings in zig. Slices are fat pointers with pointers and length. Use zero terminated slices when you want to pass the slices to C functions.
  4. Use .ptr to get the pointer from the slice and std.mem.span to convert a zero terminated pointer to a slice (see: Convert []const u8 to [*:0]const u8 - #2 by dimdin)
  5. Use expectEqualStrings to compare the contents of two slices.
test "kvstore: put and get a value" {
    const store = ckvstore.create_kv_store(1);
    try std.testing.expect(store != null);
    defer ckvstore.free_kv_store(store);

    const key  = "key";
    const value: [:0]const u8 = "value";

    const result = ckvstore.kv_store_put(store, key, value.ptr);
    try std.testing.expectEqual(0, result);

    const retrieved_value = ckvstore.kv_store_get(store, key);
    try std.testing.expectEqualStrings(value, std.mem.span(retrieved_value));
}

Extra points for replacing the store C API with a zig API:

  • Use slices instead of C strings.
  • create_kv_store must not return a nullable store. If there is a need to represent failure you can return an error union of store !Store and call using const store = try ckvstore.create_kv_store(1);
  • kv_store_get must return an optional value to denote that a key might not be in the store. Call using:
    if (ckvstore.kv_store_get(store, key)) |retrieved_value| {
        try std.testing.expectEqualStrings(value, retrieved_value);
    }
    
1 Like