linux-kselftest.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH linux-kselftest/test v5] ext4: add kunit test for decoding extended timestamps
@ 2019-10-16 21:29 Iurii Zaikin
  2019-10-17  0:10 ` Shuah Khan
  0 siblings, 1 reply; 7+ messages in thread
From: Iurii Zaikin @ 2019-10-16 21:29 UTC (permalink / raw)
  To: linux-kselftest, linux-ext4, skhan, tytso, adilger.kernel, Tim.Bird
  Cc: kunit-dev, brendanhiggins, Iurii Zaikin

KUnit tests for decoding extended 64 bit timestamps
that verify the seconds part of [a/c/m]
timestamps in ext4 inode structs are decoded correctly.
KUnit tests, which run on boot and output
the results to the debug log in TAP format (http://testanything.org/).
are only useful for kernel devs running KUnit test harness. Not for
inclusion into a production build.
Test data is derived from the table under
Documentation/filesystems/ext4/inodes.rst Inode Timestamps.

Signed-off-by: Iurii Zaikin <yzaikin@google.com>
Reviewed-by: Theodore Ts'o <tytso@mit.edu>
Reviewed-by: Brendan Higgins <brendanhiggins@google.com>
Tested-by: Brendan Higgins <brendanhiggins@google.com>
---
 fs/ext4/Kconfig      |  14 +++
 fs/ext4/Makefile     |   1 +
 fs/ext4/inode-test.c | 239 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 254 insertions(+)
 create mode 100644 fs/ext4/inode-test.c

diff --git a/fs/ext4/Kconfig b/fs/ext4/Kconfig
index cbb5ca830e57..f13dde8ed92b 100644
--- a/fs/ext4/Kconfig
+++ b/fs/ext4/Kconfig
@@ -106,3 +106,17 @@ config EXT4_DEBUG
 	  If you select Y here, then you will be able to turn on debugging
 	  with a command such as:
 		echo 1 > /sys/module/ext4/parameters/mballoc_debug
+
+config EXT4_KUNIT_TESTS
+	bool "KUnit tests for ext4"
+	select EXT4_FS
+	depends on KUNIT
+	help
+	  This builds the ext4 KUnit tests, which run on boot and output
+	  the results to the debug log in TAP format (http://testanything.org/).
+	  Only useful for kernel devs running KUnit test harness. Not for
+	  inclusion into a production build.
+	  For more information on KUnit and unit tests in general please refer
+	  to the KUnit documentation in Documentation/dev-tools/kunit/.
+
+	  If unsure, say N.
diff --git a/fs/ext4/Makefile b/fs/ext4/Makefile
index b17ddc229ac5..840b91d040f1 100644
--- a/fs/ext4/Makefile
+++ b/fs/ext4/Makefile
@@ -13,4 +13,5 @@ ext4-y	:= balloc.o bitmap.o block_validity.o dir.o ext4_jbd2.o extents.o \

 ext4-$(CONFIG_EXT4_FS_POSIX_ACL)	+= acl.o
 ext4-$(CONFIG_EXT4_FS_SECURITY)		+= xattr_security.o
+ext4-$(CONFIG_EXT4_KUNIT_TESTS)		+= inode-test.o
 ext4-$(CONFIG_FS_VERITY)		+= verity.o
diff --git a/fs/ext4/inode-test.c b/fs/ext4/inode-test.c
new file mode 100644
index 000000000000..1f2c486bc1c2
--- /dev/null
+++ b/fs/ext4/inode-test.c
@@ -0,0 +1,239 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * KUnit test of ext4 inode that verify the seconds part of [a/c/m]
+ * timestamps in ext4 inode structs are decoded correctly.
+ */
+
+#include <kunit/test.h>
+#include <linux/kernel.h>
+#include <linux/time64.h>
+
+#include "ext4.h"
+
+/* binary: 00000000 00000000 00000000 00000000 */
+#define LOWER_MSB_0 0L
+/* binary: 01111111 11111111 11111111 11111111 */
+#define UPPER_MSB_0 0x7fffffffL
+/* binary: 10000000 00000000 00000000 00000000 */
+#define LOWER_MSB_1 (-0x80000000L)
+/* binary: 11111111 11111111 11111111 11111111 */
+#define UPPER_MSB_1 (-1L)
+/* binary: 00111111 11111111 11111111 11111111 */
+#define MAX_NANOSECONDS ((1L << 30) - 1)
+
+#define CASE_NAME_FORMAT "%s: msb:%x lower_bound:%x extra_bits: %x"
+
+struct timestamp_expectation {
+	const char *test_case_name;
+	struct timespec64 expected;
+	u32 extra_bits;
+	bool msb_set;
+	bool lower_bound;
+};
+
+static time64_t get_32bit_time(const struct timestamp_expectation * const test)
+{
+	if (test->msb_set) {
+		if (test->lower_bound)
+			return LOWER_MSB_1;
+
+		return UPPER_MSB_1;
+	}
+
+	if (test->lower_bound)
+		return LOWER_MSB_0;
+	return UPPER_MSB_0;
+}
+
+
+/*
+ * These tests are derived from the table under
+ * Documentation/filesystems/ext4/inodes.rst Inode Timestamps
+ */
+static void inode_test_xtimestamp_decoding(struct kunit *test)
+{
+	const struct timestamp_expectation test_data[] = {
+		{
+			.test_case_name =
+		"1901-12-13 Lower bound of 32bit < 0 timestamp, no extra bits",
+			.msb_set = true,
+			.lower_bound = true,
+			.extra_bits = 0,
+			.expected = {.tv_sec = -0x80000000LL, .tv_nsec = 0L},
+		},
+
+		{
+			.test_case_name =
+		"1969-12-31 Upper bound of 32bit < 0 timestamp, no extra bits",
+			.msb_set = true,
+			.lower_bound = false,
+			.extra_bits = 0,
+			.expected = {.tv_sec = -1LL, .tv_nsec = 0L},
+		},
+
+		{
+			.test_case_name =
+		"1970-01-01 Lower bound of 32bit >=0 timestamp, no extra bits",
+			.msb_set = false,
+			.lower_bound = true,
+			.extra_bits = 0,
+			.expected = {0LL, 0L},
+		},
+
+		{
+			.test_case_name =
+		"2038-01-19 Upper bound of 32bit >=0 timestamp, no extra bits",
+			.msb_set = false,
+			.lower_bound = false,
+			.extra_bits = 0,
+			.expected = {.tv_sec = 0x7fffffffLL, .tv_nsec = 0L},
+		},
+
+		{
+			.test_case_name =
+	"2038-01-19 Lower bound of 32bit <0 timestamp, lo extra sec bit on",
+			.msb_set = true,
+			.lower_bound = true,
+			.extra_bits = 1,
+			.expected = {.tv_sec = 0x80000000LL, .tv_nsec = 0L},
+		},
+
+		{
+			.test_case_name =
+	"2106-02-07 Upper bound of 32bit <0 timestamp, lo extra sec bit on",
+			.msb_set = true,
+			.lower_bound = false,
+			.extra_bits = 1,
+			.expected = {.tv_sec = 0xffffffffLL, .tv_nsec = 0L},
+		},
+
+		{
+			.test_case_name =
+	  "2106-02-07 Lower bound of 32bit >=0 timestamp, lo extra sec bit on",
+			.msb_set = false,
+			.lower_bound = true,
+			.extra_bits = 1,
+			.expected = {.tv_sec = 0x100000000LL, .tv_nsec = 0L},
+		},
+
+		{
+			.test_case_name =
+	  "2174-02-25 Upper bound of 32bit >=0 timestamp, lo extra sec bit on",
+			.msb_set = false,
+			.lower_bound = false,
+			.extra_bits = 1,
+			.expected = {.tv_sec = 0x17fffffffLL, .tv_nsec = 0L},
+		},
+
+		{
+			.test_case_name =
+	  "2174-02-25 Lower bound of 32bit <0 timestamp, hi extra sec bit on",
+			.msb_set = true,
+			.lower_bound = true,
+			.extra_bits =  2,
+			.expected = {.tv_sec = 0x180000000LL, .tv_nsec = 0L},
+		},
+
+		{
+			.test_case_name =
+	  "2242-03-16 Upper bound of 32bit <0 timestamp, hi extra sec bit on",
+			.msb_set = true,
+			.lower_bound = false,
+			.extra_bits = 2,
+			.expected = {.tv_sec = 0x1ffffffffLL, .tv_nsec = 0L},
+		},
+
+		{
+			.test_case_name =
+	"2242-03-16 Lower bound of 32bit >=0 timestamp, hi extra sec bit on",
+			.msb_set = false,
+			.lower_bound = true,
+			.extra_bits = 2,
+			.expected = {.tv_sec = 0x200000000LL, .tv_nsec = 0L},
+		},
+
+		{
+			.test_case_name =
+	  "2310-04-04 Upper bound of 32bit >=0 timestamp, hi extra sec bit on",
+			.msb_set = false,
+			.lower_bound = false,
+			.extra_bits = 2,
+			.expected = {.tv_sec = 0x27fffffffLL, .tv_nsec = 0L},
+		},
+
+		{
+			.test_case_name =
+"2310-04-04 Upper bound of 32bit>=0 timestamp, hi extra sec bit 1. 1 ns bit 1",
+			.msb_set = false,
+			.lower_bound = false,
+			.extra_bits = 6,
+			.expected = {.tv_sec = 0x27fffffffLL, .tv_nsec = 1L},
+		},
+
+		{
+			.test_case_name =
+"2378-04-22 Lower bound of 32bit>= timestamp. Extra sec bits 1. ns bits 1",
+			.msb_set = false,
+			.lower_bound = true,
+			.extra_bits = 0xFFFFFFFF,
+			.expected = {.tv_sec = 0x300000000LL,
+				     .tv_nsec = MAX_NANOSECONDS},
+		},
+
+		{
+			.test_case_name =
+	 "2378-04-22 Lower bound of 32bit >= timestamp. All extra sec bits on",
+			.msb_set = false,
+			.lower_bound = true,
+			.extra_bits = 3,
+			.expected = {.tv_sec = 0x300000000LL, .tv_nsec = 0L},
+		},
+
+		{
+			.test_case_name =
+	"2446-05-10 Upper bound of 32bit >= timestamp. All extra sec bits on",
+			.msb_set = false,
+			.lower_bound = false,
+			.extra_bits = 3,
+			.expected = {.tv_sec = 0x37fffffffLL, .tv_nsec = 0L},
+		}
+	};
+
+	struct timespec64 timestamp;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(test_data); ++i) {
+		timestamp.tv_sec = get_32bit_time(&test_data[i]);
+		ext4_decode_extra_time(&timestamp,
+				       cpu_to_le32(test_data[i].extra_bits));
+
+		KUNIT_EXPECT_EQ_MSG(test,
+				    test_data[i].expected.tv_sec,
+				    timestamp.tv_sec,
+				    CASE_NAME_FORMAT,
+				    test_data[i].test_case_name,
+				    test_data[i].msb_set,
+				    test_data[i].lower_bound,
+				    test_data[i].extra_bits);
+		KUNIT_EXPECT_EQ_MSG(test,
+				    test_data[i].expected.tv_nsec,
+				    timestamp.tv_nsec,
+				    CASE_NAME_FORMAT,
+				    test_data[i].test_case_name,
+				    test_data[i].msb_set,
+				    test_data[i].lower_bound,
+				    test_data[i].extra_bits);
+	}
+}
+
+static struct kunit_case ext4_inode_test_cases[] = {
+	KUNIT_CASE(inode_test_xtimestamp_decoding),
+	{}
+};
+
+static struct kunit_suite ext4_inode_test_suite = {
+	.name = "ext4_inode_test",
+	.test_cases = ext4_inode_test_cases,
+};
+
+kunit_test_suite(ext4_inode_test_suite);
--
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH linux-kselftest/test v5] ext4: add kunit test for decoding extended timestamps
  2019-10-16 21:29 [PATCH linux-kselftest/test v5] ext4: add kunit test for decoding extended timestamps Iurii Zaikin
@ 2019-10-17  0:10 ` Shuah Khan
  2019-10-17 22:12   ` Iurii Zaikin
  0 siblings, 1 reply; 7+ messages in thread
From: Shuah Khan @ 2019-10-17  0:10 UTC (permalink / raw)
  To: Iurii Zaikin, linux-kselftest, linux-ext4, tytso, adilger.kernel,
	Tim.Bird
  Cc: kunit-dev, brendanhiggins, skh >> Shuah Khan

Hi Lurii,

On 10/16/19 3:29 PM, Iurii Zaikin wrote:
> KUnit tests for decoding extended 64 bit timestamps
> that verify the seconds part of [a/c/m]
> timestamps in ext4 inode structs are decoded correctly.

Add a blank line here. Also can you make these close 75 char long.
It will be easier to read the commit log.


> KUnit tests, which run on boot and output

  run during boot?

> the results to the debug log in TAP format (http://testanything.org/).

Break this sentence here.

> are only useful for kernel devs running KUnit test harness. Not for
> inclusion into a production build.

I like the way you state clearly that these aren't for production
build. Thanks for this detail.

> Test data is derived from the table under
> Documentation/filesystems/ext4/inodes.rst Inode Timestamps.

Reads a bit funny. Please rephrase.


Test data is derived from the Inode Timestamps table under
Documentation/filesystems/ext4/inodes.rst

> 
> Signed-off-by: Iurii Zaikin <yzaikin@google.com>
> Reviewed-by: Theodore Ts'o <tytso@mit.edu>
> Reviewed-by: Brendan Higgins <brendanhiggins@google.com>
> Tested-by: Brendan Higgins <brendanhiggins@google.com>
> ---
>   fs/ext4/Kconfig      |  14 +++
>   fs/ext4/Makefile     |   1 +
>   fs/ext4/inode-test.c | 239 +++++++++++++++++++++++++++++++++++++++++++
>   3 files changed, 254 insertions(+)
>   create mode 100644 fs/ext4/inode-test.c
> 
> diff --git a/fs/ext4/Kconfig b/fs/ext4/Kconfig
> index cbb5ca830e57..f13dde8ed92b 100644
> --- a/fs/ext4/Kconfig
> +++ b/fs/ext4/Kconfig
> @@ -106,3 +106,17 @@ config EXT4_DEBUG
>   	  If you select Y here, then you will be able to turn on debugging
>   	  with a command such as:
>   		echo 1 > /sys/module/ext4/parameters/mballoc_debug
> +
> +config EXT4_KUNIT_TESTS
> +	bool "KUnit tests for ext4"
> +	select EXT4_FS
> +	depends on KUNIT
> +	help
> +	  This builds the ext4 KUnit tests, which run on boot and output
> +	  the results to the debug log in TAP format (http://testanything.org/).
> +	  Only useful for kernel devs running KUnit test harness. Not for
> +	  inclusion into a production build.

Please apply the same changes you made to commit log here.

> +	  For more information on KUnit and unit tests in general please refer
> +	  to the KUnit documentation in Documentation/dev-tools/kunit/.
> +
> +	  If unsure, say N.
> diff --git a/fs/ext4/Makefile b/fs/ext4/Makefile
> index b17ddc229ac5..840b91d040f1 100644
> --- a/fs/ext4/Makefile
> +++ b/fs/ext4/Makefile
> @@ -13,4 +13,5 @@ ext4-y	:= balloc.o bitmap.o block_validity.o dir.o ext4_jbd2.o extents.o \
> 
>   ext4-$(CONFIG_EXT4_FS_POSIX_ACL)	+= acl.o
>   ext4-$(CONFIG_EXT4_FS_SECURITY)		+= xattr_security.o
> +ext4-$(CONFIG_EXT4_KUNIT_TESTS)		+= inode-test.o
>   ext4-$(CONFIG_FS_VERITY)		+= verity.o
> diff --git a/fs/ext4/inode-test.c b/fs/ext4/inode-test.c
> new file mode 100644
> index 000000000000..1f2c486bc1c2
> --- /dev/null
> +++ b/fs/ext4/inode-test.c
> @@ -0,0 +1,239 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * KUnit test of ext4 inode that verify the seconds part of [a/c/m]
> + * timestamps in ext4 inode structs are decoded correctly.
> + */
> +
> +#include <kunit/test.h>
> +#include <linux/kernel.h>
> +#include <linux/time64.h>
> +
> +#include "ext4.h"
> +

Please add a comment to say what these defines are for.

> +/* binary: 00000000 00000000 00000000 00000000 */
> +#define LOWER_MSB_0 0L
> +/* binary: 01111111 11111111 11111111 11111111 */
> +#define UPPER_MSB_0 0x7fffffffL
> +/* binary: 10000000 00000000 00000000 00000000 */
> +#define LOWER_MSB_1 (-0x80000000L)
> +/* binary: 11111111 11111111 11111111 11111111 */
> +#define UPPER_MSB_1 (-1L)
> +/* binary: 00111111 11111111 11111111 11111111 */
> +#define MAX_NANOSECONDS ((1L << 30) - 1)
> +
> +#define CASE_NAME_FORMAT "%s: msb:%x lower_bound:%x extra_bits: %x"
> +
> +struct timestamp_expectation {
> +	const char *test_case_name;
> +	struct timespec64 expected;
> +	u32 extra_bits;
> +	bool msb_set;
> +	bool lower_bound;
> +};
> +
> +static time64_t get_32bit_time(const struct timestamp_expectation * const test)
> +{
> +	if (test->msb_set) {
> +		if (test->lower_bound)
> +			return LOWER_MSB_1;
> +
> +		return UPPER_MSB_1;
> +	}
> +
> +	if (test->lower_bound)
> +		return LOWER_MSB_0;
> +	return UPPER_MSB_0;
> +}
> +
> +
> +/*
> + * These tests are derived from the table under
> + * Documentation/filesystems/ext4/inodes.rst Inode Timestamps

Rephrase this please. Reads a bit funny.

> + */
> +static void inode_test_xtimestamp_decoding(struct kunit *test)
> +{
> +	const struct timestamp_expectation test_data[] = {
> +		{
> +			.test_case_name =
> +		"1901-12-13 Lower bound of 32bit < 0 timestamp, no extra bits",

Please make these defines and use name here. Makes it easier to read
and you can also avoid this weird lining up with {


> +			.msb_set = true,
> +			.lower_bound = true,
> +			.extra_bits = 0,
> +			.expected = {.tv_sec = -0x80000000LL, .tv_nsec = 0L},
> +		},
> +
> +		{
> +			.test_case_name =
> +		"1969-12-31 Upper bound of 32bit < 0 timestamp, no extra bits",

Same here.

> +			.msb_set = true,
> +			.lower_bound = false,
> +			.extra_bits = 0,
> +			.expected = {.tv_sec = -1LL, .tv_nsec = 0L},
> +		},
> +
> +		{
> +			.test_case_name =
> +		"1970-01-01 Lower bound of 32bit >=0 timestamp, no extra bits",

Same here.

> +			.msb_set = false,
> +			.lower_bound = true,
> +			.extra_bits = 0,
> +			.expected = {0LL, 0L},
> +		},
> +
> +		{
> +			.test_case_name =
> +		"2038-01-19 Upper bound of 32bit >=0 timestamp, no extra bits",

Same here and all the strings below.

> +			.msb_set = false,
> +			.lower_bound = false,
> +			.extra_bits = 0,
> +			.expected = {.tv_sec = 0x7fffffffLL, .tv_nsec = 0L},
> +		},
> +
> +		{
> +			.test_case_name =
> +	"2038-01-19 Lower bound of 32bit <0 timestamp, lo extra sec bit on",
> +			.msb_set = true,
> +			.lower_bound = true,
> +			.extra_bits = 1,
> +			.expected = {.tv_sec = 0x80000000LL, .tv_nsec = 0L},
> +		},
> +
> +		{
> +			.test_case_name =
> +	"2106-02-07 Upper bound of 32bit <0 timestamp, lo extra sec bit on",
> +			.msb_set = true,
> +			.lower_bound = false,
> +			.extra_bits = 1,
> +			.expected = {.tv_sec = 0xffffffffLL, .tv_nsec = 0L},
> +		},
> +
> +		{
> +			.test_case_name =
> +	  "2106-02-07 Lower bound of 32bit >=0 timestamp, lo extra sec bit on",
> +			.msb_set = false,
> +			.lower_bound = true,
> +			.extra_bits = 1,
> +			.expected = {.tv_sec = 0x100000000LL, .tv_nsec = 0L},
> +		},
> +
> +		{
> +			.test_case_name =
> +	  "2174-02-25 Upper bound of 32bit >=0 timestamp, lo extra sec bit on",
> +			.msb_set = false,
> +			.lower_bound = false,
> +			.extra_bits = 1,
> +			.expected = {.tv_sec = 0x17fffffffLL, .tv_nsec = 0L},
> +		},
> +
> +		{
> +			.test_case_name =
> +	  "2174-02-25 Lower bound of 32bit <0 timestamp, hi extra sec bit on",
> +			.msb_set = true,
> +			.lower_bound = true,
> +			.extra_bits =  2,
> +			.expected = {.tv_sec = 0x180000000LL, .tv_nsec = 0L},
> +		},
> +
> +		{
> +			.test_case_name =
> +	  "2242-03-16 Upper bound of 32bit <0 timestamp, hi extra sec bit on",
> +			.msb_set = true,
> +			.lower_bound = false,
> +			.extra_bits = 2,
> +			.expected = {.tv_sec = 0x1ffffffffLL, .tv_nsec = 0L},
> +		},
> +
> +		{
> +			.test_case_name =
> +	"2242-03-16 Lower bound of 32bit >=0 timestamp, hi extra sec bit on",
> +			.msb_set = false,
> +			.lower_bound = true,
> +			.extra_bits = 2,
> +			.expected = {.tv_sec = 0x200000000LL, .tv_nsec = 0L},
> +		},
> +
> +		{
> +			.test_case_name =
> +	  "2310-04-04 Upper bound of 32bit >=0 timestamp, hi extra sec bit on",
> +			.msb_set = false,
> +			.lower_bound = false,
> +			.extra_bits = 2,
> +			.expected = {.tv_sec = 0x27fffffffLL, .tv_nsec = 0L},
> +		},
> +
> +		{
> +			.test_case_name =
> +"2310-04-04 Upper bound of 32bit>=0 timestamp, hi extra sec bit 1. 1 ns bit 1",
> +			.msb_set = false,
> +			.lower_bound = false,
> +			.extra_bits = 6,
> +			.expected = {.tv_sec = 0x27fffffffLL, .tv_nsec = 1L},
> +		},
> +
> +		{
> +			.test_case_name =
> +"2378-04-22 Lower bound of 32bit>= timestamp. Extra sec bits 1. ns bits 1",
> +			.msb_set = false,
> +			.lower_bound = true,
> +			.extra_bits = 0xFFFFFFFF,
> +			.expected = {.tv_sec = 0x300000000LL,
> +				     .tv_nsec = MAX_NANOSECONDS},
> +		},
> +
> +		{
> +			.test_case_name =
> +	 "2378-04-22 Lower bound of 32bit >= timestamp. All extra sec bits on",
> +			.msb_set = false,
> +			.lower_bound = true,
> +			.extra_bits = 3,
> +			.expected = {.tv_sec = 0x300000000LL, .tv_nsec = 0L},
> +		},
> +
> +		{
> +			.test_case_name =
> +	"2446-05-10 Upper bound of 32bit >= timestamp. All extra sec bits on",
> +			.msb_set = false,
> +			.lower_bound = false,
> +			.extra_bits = 3,
> +			.expected = {.tv_sec = 0x37fffffffLL, .tv_nsec = 0L},
> +		}
> +	};
> +
> +	struct timespec64 timestamp;
> +	int i;
> +
> +	for (i = 0; i < ARRAY_SIZE(test_data); ++i) {
> +		timestamp.tv_sec = get_32bit_time(&test_data[i]);
> +		ext4_decode_extra_time(&timestamp,
> +				       cpu_to_le32(test_data[i].extra_bits));
> +
> +		KUNIT_EXPECT_EQ_MSG(test,
> +				    test_data[i].expected.tv_sec,
> +				    timestamp.tv_sec,
> +				    CASE_NAME_FORMAT,
> +				    test_data[i].test_case_name,
> +				    test_data[i].msb_set,
> +				    test_data[i].lower_bound,
> +				    test_data[i].extra_bits);
> +		KUNIT_EXPECT_EQ_MSG(test,
> +				    test_data[i].expected.tv_nsec,
> +				    timestamp.tv_nsec,
> +				    CASE_NAME_FORMAT,
> +				    test_data[i].test_case_name,
> +				    test_data[i].msb_set,
> +				    test_data[i].lower_bound,
> +				    test_data[i].extra_bits);
> +	}
> +}
> +
> +static struct kunit_case ext4_inode_test_cases[] = {
> +	KUNIT_CASE(inode_test_xtimestamp_decoding),
> +	{}
> +};
> +
> +static struct kunit_suite ext4_inode_test_suite = {
> +	.name = "ext4_inode_test",
> +	.test_cases = ext4_inode_test_cases,
> +};
> +
> +kunit_test_suite(ext4_inode_test_suite);
> --
> 2.23.0.866.gb869b98d4c-goog
> 

thanks,
-- Shuah

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH linux-kselftest/test v5] ext4: add kunit test for decoding extended timestamps
  2019-10-17  0:10 ` Shuah Khan
@ 2019-10-17 22:12   ` Iurii Zaikin
  0 siblings, 0 replies; 7+ messages in thread
From: Iurii Zaikin @ 2019-10-17 22:12 UTC (permalink / raw)
  To: Shuah Khan
  Cc: open list:KERNEL SELFTEST FRAMEWORK, linux-ext4,
	Theodore Ts'o, adilger.kernel, Bird, Timothy,
	KUnit Development, Brendan Higgins

On Wed, Oct 16, 2019 at 5:10 PM Shuah Khan <skhan@linuxfoundation.org> wrote:
>
> Hi Lurii,
>
> On 10/16/19 3:29 PM, Iurii Zaikin wrote:
> > KUnit tests for decoding extended 64 bit timestamps
> > that verify the seconds part of [a/c/m]
> > timestamps in ext4 inode structs are decoded correctly.
>
> Add a blank line here. Also can you make these close 75 char long.
> It will be easier to read the commit log.
>
>
Done. Went with Theodore's suggestion which incorporates your feedback.
> > KUnit tests, which run on boot and output
>
>   run during boot?
>
Done
> > the results to the debug log in TAP format (http://testanything.org/).
>
> Break this sentence here.
>
Done
> > are only useful for kernel devs running KUnit test harness. Not for
> > inclusion into a production build.
>
> I like the way you state clearly that these aren't for production
> build. Thanks for this detail.
>
> > Test data is derived from the table under
> > Documentation/filesystems/ext4/inodes.rst Inode Timestamps.
>
> Reads a bit funny. Please rephrase.
>
>
> Test data is derived from the Inode Timestamps table under
> Documentation/filesystems/ext4/inodes.rst
>
Done. Went with Theordore's wording.
> >
> > Signed-off-by: Iurii Zaikin <yzaikin@google.com>
> > Reviewed-by: Theodore Ts'o <tytso@mit.edu>
> > Reviewed-by: Brendan Higgins <brendanhiggins@google.com>
> > Tested-by: Brendan Higgins <brendanhiggins@google.com>
> > ---
> >   fs/ext4/Kconfig      |  14 +++
> >   fs/ext4/Makefile     |   1 +
> >   fs/ext4/inode-test.c | 239 +++++++++++++++++++++++++++++++++++++++++++
> >   3 files changed, 254 insertions(+)
> >   create mode 100644 fs/ext4/inode-test.c
> >
> > diff --git a/fs/ext4/Kconfig b/fs/ext4/Kconfig
> > index cbb5ca830e57..f13dde8ed92b 100644
> > --- a/fs/ext4/Kconfig
> > +++ b/fs/ext4/Kconfig
> > @@ -106,3 +106,17 @@ config EXT4_DEBUG
> >         If you select Y here, then you will be able to turn on debugging
> >         with a command such as:
> >               echo 1 > /sys/module/ext4/parameters/mballoc_debug
> > +
> > +config EXT4_KUNIT_TESTS
> > +     bool "KUnit tests for ext4"
> > +     select EXT4_FS
> > +     depends on KUNIT
> > +     help
> > +       This builds the ext4 KUnit tests, which run on boot and output
> > +       the results to the debug log in TAP format (http://testanything.org/).
> > +       Only useful for kernel devs running KUnit test harness. Not for
> > +       inclusion into a production build.
>
> Please apply the same changes you made to commit log here.
>
Changed the applicable paragraphs to match description. Note that the commit
description is more specific than the config option description due to
Theodore's
preference for the single config option controlling all of ext4 tests.
> > +       For more information on KUnit and unit tests in general please refer
> > +       to the KUnit documentation in Documentation/dev-tools/kunit/.
> > +
> > +       If unsure, say N.
> > diff --git a/fs/ext4/Makefile b/fs/ext4/Makefile
> > index b17ddc229ac5..840b91d040f1 100644
> > --- a/fs/ext4/Makefile
> > +++ b/fs/ext4/Makefile
> > @@ -13,4 +13,5 @@ ext4-y      := balloc.o bitmap.o block_validity.o dir.o ext4_jbd2.o extents.o \
> >
> >   ext4-$(CONFIG_EXT4_FS_POSIX_ACL)    += acl.o
> >   ext4-$(CONFIG_EXT4_FS_SECURITY)             += xattr_security.o
> > +ext4-$(CONFIG_EXT4_KUNIT_TESTS)              += inode-test.o
> >   ext4-$(CONFIG_FS_VERITY)            += verity.o
> > diff --git a/fs/ext4/inode-test.c b/fs/ext4/inode-test.c
> > new file mode 100644
> > index 000000000000..1f2c486bc1c2
> > --- /dev/null
> > +++ b/fs/ext4/inode-test.c
> > @@ -0,0 +1,239 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * KUnit test of ext4 inode that verify the seconds part of [a/c/m]
> > + * timestamps in ext4 inode structs are decoded correctly.
> > + */
> > +
> > +#include <kunit/test.h>
> > +#include <linux/kernel.h>
> > +#include <linux/time64.h>
> > +
> > +#include "ext4.h"
> > +
>
> Please add a comment to say what these defines are for.
>
Done.
> > +/* binary: 00000000 00000000 00000000 00000000 */
> > +#define LOWER_MSB_0 0L
> > +/* binary: 01111111 11111111 11111111 11111111 */
> > +#define UPPER_MSB_0 0x7fffffffL
> > +/* binary: 10000000 00000000 00000000 00000000 */
> > +#define LOWER_MSB_1 (-0x80000000L)
> > +/* binary: 11111111 11111111 11111111 11111111 */
> > +#define UPPER_MSB_1 (-1L)
> > +/* binary: 00111111 11111111 11111111 11111111 */
> > +#define MAX_NANOSECONDS ((1L << 30) - 1)
> > +
> > +#define CASE_NAME_FORMAT "%s: msb:%x lower_bound:%x extra_bits: %x"
> > +
> > +struct timestamp_expectation {
> > +     const char *test_case_name;
> > +     struct timespec64 expected;
> > +     u32 extra_bits;
> > +     bool msb_set;
> > +     bool lower_bound;
> > +};
> > +
> > +static time64_t get_32bit_time(const struct timestamp_expectation * const test)
> > +{
> > +     if (test->msb_set) {
> > +             if (test->lower_bound)
> > +                     return LOWER_MSB_1;
> > +
> > +             return UPPER_MSB_1;
> > +     }
> > +
> > +     if (test->lower_bound)
> > +             return LOWER_MSB_0;
> > +     return UPPER_MSB_0;
> > +}
> > +
> > +
> > +/*
> > + * These tests are derived from the table under
> > + * Documentation/filesystems/ext4/inodes.rst Inode Timestamps
>
> Rephrase this please. Reads a bit funny.
>
Done.
> > + */
> > +static void inode_test_xtimestamp_decoding(struct kunit *test)
> > +{
> > +     const struct timestamp_expectation test_data[] = {
> > +             {
> > +                     .test_case_name =
> > +             "1901-12-13 Lower bound of 32bit < 0 timestamp, no extra bits",
>
> Please make these defines and use name here. Makes it easier to read
> and you can also avoid this weird lining up with {
>
Done for all test case names.
>
> > +                     .msb_set = true,
> > +                     .lower_bound = true,
> > +                     .extra_bits = 0,
> > +                     .expected = {.tv_sec = -0x80000000LL, .tv_nsec = 0L},
> > +             },
> > +
> > +             {
> > +                     .test_case_name =
> > +             "1969-12-31 Upper bound of 32bit < 0 timestamp, no extra bits",
>
> Same here.
>
> > +                     .msb_set = true,
> > +                     .lower_bound = false,
> > +                     .extra_bits = 0,
> > +                     .expected = {.tv_sec = -1LL, .tv_nsec = 0L},
> > +             },
> > +
> > +             {
> > +                     .test_case_name =
> > +             "1970-01-01 Lower bound of 32bit >=0 timestamp, no extra bits",
>
> Same here.
>
> > +                     .msb_set = false,
> > +                     .lower_bound = true,
> > +                     .extra_bits = 0,
> > +                     .expected = {0LL, 0L},
> > +             },
> > +
> > +             {
> > +                     .test_case_name =
> > +             "2038-01-19 Upper bound of 32bit >=0 timestamp, no extra bits",
>
> Same here and all the strings below.
>
> > +                     .msb_set = false,
> > +                     .lower_bound = false,
> > +                     .extra_bits = 0,
> > +                     .expected = {.tv_sec = 0x7fffffffLL, .tv_nsec = 0L},
> > +             },
> > +
> > +             {
> > +                     .test_case_name =
> > +     "2038-01-19 Lower bound of 32bit <0 timestamp, lo extra sec bit on",
> > +                     .msb_set = true,
> > +                     .lower_bound = true,
> > +                     .extra_bits = 1,
> > +                     .expected = {.tv_sec = 0x80000000LL, .tv_nsec = 0L},
> > +             },
> > +
> > +             {
> > +                     .test_case_name =
> > +     "2106-02-07 Upper bound of 32bit <0 timestamp, lo extra sec bit on",
> > +                     .msb_set = true,
> > +                     .lower_bound = false,
> > +                     .extra_bits = 1,
> > +                     .expected = {.tv_sec = 0xffffffffLL, .tv_nsec = 0L},
> > +             },
> > +
> > +             {
> > +                     .test_case_name =
> > +       "2106-02-07 Lower bound of 32bit >=0 timestamp, lo extra sec bit on",
> > +                     .msb_set = false,
> > +                     .lower_bound = true,
> > +                     .extra_bits = 1,
> > +                     .expected = {.tv_sec = 0x100000000LL, .tv_nsec = 0L},
> > +             },
> > +
> > +             {
> > +                     .test_case_name =
> > +       "2174-02-25 Upper bound of 32bit >=0 timestamp, lo extra sec bit on",
> > +                     .msb_set = false,
> > +                     .lower_bound = false,
> > +                     .extra_bits = 1,
> > +                     .expected = {.tv_sec = 0x17fffffffLL, .tv_nsec = 0L},
> > +             },
> > +
> > +             {
> > +                     .test_case_name =
> > +       "2174-02-25 Lower bound of 32bit <0 timestamp, hi extra sec bit on",
> > +                     .msb_set = true,
> > +                     .lower_bound = true,
> > +                     .extra_bits =  2,
> > +                     .expected = {.tv_sec = 0x180000000LL, .tv_nsec = 0L},
> > +             },
> > +
> > +             {
> > +                     .test_case_name =
> > +       "2242-03-16 Upper bound of 32bit <0 timestamp, hi extra sec bit on",
> > +                     .msb_set = true,
> > +                     .lower_bound = false,
> > +                     .extra_bits = 2,
> > +                     .expected = {.tv_sec = 0x1ffffffffLL, .tv_nsec = 0L},
> > +             },
> > +
> > +             {
> > +                     .test_case_name =
> > +     "2242-03-16 Lower bound of 32bit >=0 timestamp, hi extra sec bit on",
> > +                     .msb_set = false,
> > +                     .lower_bound = true,
> > +                     .extra_bits = 2,
> > +                     .expected = {.tv_sec = 0x200000000LL, .tv_nsec = 0L},
> > +             },
> > +
> > +             {
> > +                     .test_case_name =
> > +       "2310-04-04 Upper bound of 32bit >=0 timestamp, hi extra sec bit on",
> > +                     .msb_set = false,
> > +                     .lower_bound = false,
> > +                     .extra_bits = 2,
> > +                     .expected = {.tv_sec = 0x27fffffffLL, .tv_nsec = 0L},
> > +             },
> > +
> > +             {
> > +                     .test_case_name =
> > +"2310-04-04 Upper bound of 32bit>=0 timestamp, hi extra sec bit 1. 1 ns bit 1",
> > +                     .msb_set = false,
> > +                     .lower_bound = false,
> > +                     .extra_bits = 6,
> > +                     .expected = {.tv_sec = 0x27fffffffLL, .tv_nsec = 1L},
> > +             },
> > +
> > +             {
> > +                     .test_case_name =
> > +"2378-04-22 Lower bound of 32bit>= timestamp. Extra sec bits 1. ns bits 1",
> > +                     .msb_set = false,
> > +                     .lower_bound = true,
> > +                     .extra_bits = 0xFFFFFFFF,
> > +                     .expected = {.tv_sec = 0x300000000LL,
> > +                                  .tv_nsec = MAX_NANOSECONDS},
> > +             },
> > +
> > +             {
> > +                     .test_case_name =
> > +      "2378-04-22 Lower bound of 32bit >= timestamp. All extra sec bits on",
> > +                     .msb_set = false,
> > +                     .lower_bound = true,
> > +                     .extra_bits = 3,
> > +                     .expected = {.tv_sec = 0x300000000LL, .tv_nsec = 0L},
> > +             },
> > +
> > +             {
> > +                     .test_case_name =
> > +     "2446-05-10 Upper bound of 32bit >= timestamp. All extra sec bits on",
> > +                     .msb_set = false,
> > +                     .lower_bound = false,
> > +                     .extra_bits = 3,
> > +                     .expected = {.tv_sec = 0x37fffffffLL, .tv_nsec = 0L},
> > +             }
> > +     };
> > +
> > +     struct timespec64 timestamp;
> > +     int i;
> > +
> > +     for (i = 0; i < ARRAY_SIZE(test_data); ++i) {
> > +             timestamp.tv_sec = get_32bit_time(&test_data[i]);
> > +             ext4_decode_extra_time(&timestamp,
> > +                                    cpu_to_le32(test_data[i].extra_bits));
> > +
> > +             KUNIT_EXPECT_EQ_MSG(test,
> > +                                 test_data[i].expected.tv_sec,
> > +                                 timestamp.tv_sec,
> > +                                 CASE_NAME_FORMAT,
> > +                                 test_data[i].test_case_name,
> > +                                 test_data[i].msb_set,
> > +                                 test_data[i].lower_bound,
> > +                                 test_data[i].extra_bits);
> > +             KUNIT_EXPECT_EQ_MSG(test,
> > +                                 test_data[i].expected.tv_nsec,
> > +                                 timestamp.tv_nsec,
> > +                                 CASE_NAME_FORMAT,
> > +                                 test_data[i].test_case_name,
> > +                                 test_data[i].msb_set,
> > +                                 test_data[i].lower_bound,
> > +                                 test_data[i].extra_bits);
> > +     }
> > +}
> > +
> > +static struct kunit_case ext4_inode_test_cases[] = {
> > +     KUNIT_CASE(inode_test_xtimestamp_decoding),
> > +     {}
> > +};
> > +
> > +static struct kunit_suite ext4_inode_test_suite = {
> > +     .name = "ext4_inode_test",
> > +     .test_cases = ext4_inode_test_cases,
> > +};
> > +
> > +kunit_test_suite(ext4_inode_test_suite);
> > --
> > 2.23.0.866.gb869b98d4c-goog
> >
>
> thanks,
> -- Shuah

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH linux-kselftest/test v5] ext4: add kunit test for decoding extended timestamps
  2019-10-17 12:55 ` Theodore Y. Ts'o
@ 2019-10-17 13:03   ` Theodore Y. Ts'o
  0 siblings, 0 replies; 7+ messages in thread
From: Theodore Y. Ts'o @ 2019-10-17 13:03 UTC (permalink / raw)
  To: Iurii Zaikin
  Cc: linux-kselftest, linux-ext4, skhan, adilger.kernel, Tim.Bird,
	kunit-dev, brendanhiggins

On Thu, Oct 17, 2019 at 08:55:53AM -0400, Theodore Y. Ts'o wrote:
> Minor nit.  The above commit description would look nicer when looked
> at in "git log" when formatted as follows:
> 
> --- cut here ---
> 
> KUnit tests for decoding extended 64 bit timestamps that verify the
> seconds part of [a/c/m] timestamps in ext4 inode structs are decoded
> correctly.
> 
> KUnit tests, which run on boot and output the results to the debug log
> in TAP format (http://testanything.org/) are only useful for kernel
> devs running KUnit test harness and are not for inclusion into a
> production build.
> 
> Test data is derived from the table in the Inode Timestamps section of
> Documentation/filesystems/ext4/inodes.rst.
> 
> --- cut here ---

Upon rereading, swapping the 2nd and 3rd paragraphis would read
better, I think.

      	   	    	     	 - Ted
				 

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH linux-kselftest/test v5] ext4: add kunit test for decoding extended timestamps
  2019-10-16 20:58 Iurii Zaikin
  2019-10-16 21:17 ` Brendan Higgins
@ 2019-10-17 12:55 ` Theodore Y. Ts'o
  2019-10-17 13:03   ` Theodore Y. Ts'o
  1 sibling, 1 reply; 7+ messages in thread
From: Theodore Y. Ts'o @ 2019-10-17 12:55 UTC (permalink / raw)
  To: Iurii Zaikin
  Cc: linux-kselftest, linux-ext4, skhan, adilger.kernel, Tim.Bird,
	kunit-dev, brendanhiggins

On Wed, Oct 16, 2019 at 01:58:20PM -0700, Iurii Zaikin wrote:
> KUnit tests for decoding extended 64 bit timestamps
> that verify the seconds part of [a/c/m]
> timestamps in ext4 inode structs are decoded correctly.
> KUnit tests, which run on boot and output
> the results to the debug log in TAP format (http://testanything.org/).
> are only useful for kernel devs running KUnit test harness. Not for
> inclusion into a production build.
> Test data is derived from the table under
> Documentation/filesystems/ext4/inodes.rst Inode Timestamps.
> 
> Signed-off-by: Iurii Zaikin <yzaikin@google.com>

Reviewed-by: Theodore Ts'o <tytso@mit.edu>

Minor nit.  The above commit description would look nicer when looked
at in "git log" when formatted as follows:

--- cut here ---

KUnit tests for decoding extended 64 bit timestamps that verify the
seconds part of [a/c/m] timestamps in ext4 inode structs are decoded
correctly.

KUnit tests, which run on boot and output the results to the debug log
in TAP format (http://testanything.org/) are only useful for kernel
devs running KUnit test harness and are not for inclusion into a
production build.

Test data is derived from the table in the Inode Timestamps section of
Documentation/filesystems/ext4/inodes.rst.

--- cut here ---

					- Ted


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH linux-kselftest/test v5] ext4: add kunit test for decoding extended timestamps
  2019-10-16 20:58 Iurii Zaikin
@ 2019-10-16 21:17 ` Brendan Higgins
  2019-10-17 12:55 ` Theodore Y. Ts'o
  1 sibling, 0 replies; 7+ messages in thread
From: Brendan Higgins @ 2019-10-16 21:17 UTC (permalink / raw)
  To: Iurii Zaikin
  Cc: linux-kselftest, linux-ext4, skhan, tytso, adilger.kernel,
	Tim.Bird, kunit-dev

On Wed, Oct 16, 2019 at 01:58:20PM -0700, Iurii Zaikin wrote:
> KUnit tests for decoding extended 64 bit timestamps
> that verify the seconds part of [a/c/m]
> timestamps in ext4 inode structs are decoded correctly.
> KUnit tests, which run on boot and output
> the results to the debug log in TAP format (http://testanything.org/).
> are only useful for kernel devs running KUnit test harness. Not for
> inclusion into a production build.
> Test data is derived from the table under
> Documentation/filesystems/ext4/inodes.rst Inode Timestamps.
> 
> Signed-off-by: Iurii Zaikin <yzaikin@google.com>

You got Reviewed-bys from both Ted and myself. Unless you make
*substantial* changes you should generally include all Reviewed-bys,
Tested-bys, Acked-bys, etc in all future revisions.

Cheers!

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH linux-kselftest/test v5] ext4: add kunit test for decoding extended timestamps
@ 2019-10-16 20:58 Iurii Zaikin
  2019-10-16 21:17 ` Brendan Higgins
  2019-10-17 12:55 ` Theodore Y. Ts'o
  0 siblings, 2 replies; 7+ messages in thread
From: Iurii Zaikin @ 2019-10-16 20:58 UTC (permalink / raw)
  To: linux-kselftest, linux-ext4, skhan, tytso, adilger.kernel, Tim.Bird
  Cc: kunit-dev, brendanhiggins, Iurii Zaikin

KUnit tests for decoding extended 64 bit timestamps
that verify the seconds part of [a/c/m]
timestamps in ext4 inode structs are decoded correctly.
KUnit tests, which run on boot and output
the results to the debug log in TAP format (http://testanything.org/).
are only useful for kernel devs running KUnit test harness. Not for
inclusion into a production build.
Test data is derived from the table under
Documentation/filesystems/ext4/inodes.rst Inode Timestamps.

Signed-off-by: Iurii Zaikin <yzaikin@google.com>
---
 fs/ext4/Kconfig      |  14 +++
 fs/ext4/Makefile     |   1 +
 fs/ext4/inode-test.c | 239 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 254 insertions(+)
 create mode 100644 fs/ext4/inode-test.c

diff --git a/fs/ext4/Kconfig b/fs/ext4/Kconfig
index cbb5ca830e57..f13dde8ed92b 100644
--- a/fs/ext4/Kconfig
+++ b/fs/ext4/Kconfig
@@ -106,3 +106,17 @@ config EXT4_DEBUG
 	  If you select Y here, then you will be able to turn on debugging
 	  with a command such as:
 		echo 1 > /sys/module/ext4/parameters/mballoc_debug
+
+config EXT4_KUNIT_TESTS
+	bool "KUnit tests for ext4"
+	select EXT4_FS
+	depends on KUNIT
+	help
+	  This builds the ext4 KUnit tests, which run on boot and output
+	  the results to the debug log in TAP format (http://testanything.org/).
+	  Only useful for kernel devs running KUnit test harness. Not for
+	  inclusion into a production build.
+	  For more information on KUnit and unit tests in general please refer
+	  to the KUnit documentation in Documentation/dev-tools/kunit/.
+
+	  If unsure, say N.
diff --git a/fs/ext4/Makefile b/fs/ext4/Makefile
index b17ddc229ac5..840b91d040f1 100644
--- a/fs/ext4/Makefile
+++ b/fs/ext4/Makefile
@@ -13,4 +13,5 @@ ext4-y	:= balloc.o bitmap.o block_validity.o dir.o ext4_jbd2.o extents.o \

 ext4-$(CONFIG_EXT4_FS_POSIX_ACL)	+= acl.o
 ext4-$(CONFIG_EXT4_FS_SECURITY)		+= xattr_security.o
+ext4-$(CONFIG_EXT4_KUNIT_TESTS)		+= inode-test.o
 ext4-$(CONFIG_FS_VERITY)		+= verity.o
diff --git a/fs/ext4/inode-test.c b/fs/ext4/inode-test.c
new file mode 100644
index 000000000000..1f2c486bc1c2
--- /dev/null
+++ b/fs/ext4/inode-test.c
@@ -0,0 +1,239 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * KUnit test of ext4 inode that verify the seconds part of [a/c/m]
+ * timestamps in ext4 inode structs are decoded correctly.
+ */
+
+#include <kunit/test.h>
+#include <linux/kernel.h>
+#include <linux/time64.h>
+
+#include "ext4.h"
+
+/* binary: 00000000 00000000 00000000 00000000 */
+#define LOWER_MSB_0 0L
+/* binary: 01111111 11111111 11111111 11111111 */
+#define UPPER_MSB_0 0x7fffffffL
+/* binary: 10000000 00000000 00000000 00000000 */
+#define LOWER_MSB_1 (-0x80000000L)
+/* binary: 11111111 11111111 11111111 11111111 */
+#define UPPER_MSB_1 (-1L)
+/* binary: 00111111 11111111 11111111 11111111 */
+#define MAX_NANOSECONDS ((1L << 30) - 1)
+
+#define CASE_NAME_FORMAT "%s: msb:%x lower_bound:%x extra_bits: %x"
+
+struct timestamp_expectation {
+	const char *test_case_name;
+	struct timespec64 expected;
+	u32 extra_bits;
+	bool msb_set;
+	bool lower_bound;
+};
+
+static time64_t get_32bit_time(const struct timestamp_expectation * const test)
+{
+	if (test->msb_set) {
+		if (test->lower_bound)
+			return LOWER_MSB_1;
+
+		return UPPER_MSB_1;
+	}
+
+	if (test->lower_bound)
+		return LOWER_MSB_0;
+	return UPPER_MSB_0;
+}
+
+
+/*
+ * These tests are derived from the table under
+ * Documentation/filesystems/ext4/inodes.rst Inode Timestamps
+ */
+static void inode_test_xtimestamp_decoding(struct kunit *test)
+{
+	const struct timestamp_expectation test_data[] = {
+		{
+			.test_case_name =
+		"1901-12-13 Lower bound of 32bit < 0 timestamp, no extra bits",
+			.msb_set = true,
+			.lower_bound = true,
+			.extra_bits = 0,
+			.expected = {.tv_sec = -0x80000000LL, .tv_nsec = 0L},
+		},
+
+		{
+			.test_case_name =
+		"1969-12-31 Upper bound of 32bit < 0 timestamp, no extra bits",
+			.msb_set = true,
+			.lower_bound = false,
+			.extra_bits = 0,
+			.expected = {.tv_sec = -1LL, .tv_nsec = 0L},
+		},
+
+		{
+			.test_case_name =
+		"1970-01-01 Lower bound of 32bit >=0 timestamp, no extra bits",
+			.msb_set = false,
+			.lower_bound = true,
+			.extra_bits = 0,
+			.expected = {0LL, 0L},
+		},
+
+		{
+			.test_case_name =
+		"2038-01-19 Upper bound of 32bit >=0 timestamp, no extra bits",
+			.msb_set = false,
+			.lower_bound = false,
+			.extra_bits = 0,
+			.expected = {.tv_sec = 0x7fffffffLL, .tv_nsec = 0L},
+		},
+
+		{
+			.test_case_name =
+	"2038-01-19 Lower bound of 32bit <0 timestamp, lo extra sec bit on",
+			.msb_set = true,
+			.lower_bound = true,
+			.extra_bits = 1,
+			.expected = {.tv_sec = 0x80000000LL, .tv_nsec = 0L},
+		},
+
+		{
+			.test_case_name =
+	"2106-02-07 Upper bound of 32bit <0 timestamp, lo extra sec bit on",
+			.msb_set = true,
+			.lower_bound = false,
+			.extra_bits = 1,
+			.expected = {.tv_sec = 0xffffffffLL, .tv_nsec = 0L},
+		},
+
+		{
+			.test_case_name =
+	  "2106-02-07 Lower bound of 32bit >=0 timestamp, lo extra sec bit on",
+			.msb_set = false,
+			.lower_bound = true,
+			.extra_bits = 1,
+			.expected = {.tv_sec = 0x100000000LL, .tv_nsec = 0L},
+		},
+
+		{
+			.test_case_name =
+	  "2174-02-25 Upper bound of 32bit >=0 timestamp, lo extra sec bit on",
+			.msb_set = false,
+			.lower_bound = false,
+			.extra_bits = 1,
+			.expected = {.tv_sec = 0x17fffffffLL, .tv_nsec = 0L},
+		},
+
+		{
+			.test_case_name =
+	  "2174-02-25 Lower bound of 32bit <0 timestamp, hi extra sec bit on",
+			.msb_set = true,
+			.lower_bound = true,
+			.extra_bits =  2,
+			.expected = {.tv_sec = 0x180000000LL, .tv_nsec = 0L},
+		},
+
+		{
+			.test_case_name =
+	  "2242-03-16 Upper bound of 32bit <0 timestamp, hi extra sec bit on",
+			.msb_set = true,
+			.lower_bound = false,
+			.extra_bits = 2,
+			.expected = {.tv_sec = 0x1ffffffffLL, .tv_nsec = 0L},
+		},
+
+		{
+			.test_case_name =
+	"2242-03-16 Lower bound of 32bit >=0 timestamp, hi extra sec bit on",
+			.msb_set = false,
+			.lower_bound = true,
+			.extra_bits = 2,
+			.expected = {.tv_sec = 0x200000000LL, .tv_nsec = 0L},
+		},
+
+		{
+			.test_case_name =
+	  "2310-04-04 Upper bound of 32bit >=0 timestamp, hi extra sec bit on",
+			.msb_set = false,
+			.lower_bound = false,
+			.extra_bits = 2,
+			.expected = {.tv_sec = 0x27fffffffLL, .tv_nsec = 0L},
+		},
+
+		{
+			.test_case_name =
+"2310-04-04 Upper bound of 32bit>=0 timestamp, hi extra sec bit 1. 1 ns bit 1",
+			.msb_set = false,
+			.lower_bound = false,
+			.extra_bits = 6,
+			.expected = {.tv_sec = 0x27fffffffLL, .tv_nsec = 1L},
+		},
+
+		{
+			.test_case_name =
+"2378-04-22 Lower bound of 32bit>= timestamp. Extra sec bits 1. ns bits 1",
+			.msb_set = false,
+			.lower_bound = true,
+			.extra_bits = 0xFFFFFFFF,
+			.expected = {.tv_sec = 0x300000000LL,
+				     .tv_nsec = MAX_NANOSECONDS},
+		},
+
+		{
+			.test_case_name =
+	 "2378-04-22 Lower bound of 32bit >= timestamp. All extra sec bits on",
+			.msb_set = false,
+			.lower_bound = true,
+			.extra_bits = 3,
+			.expected = {.tv_sec = 0x300000000LL, .tv_nsec = 0L},
+		},
+
+		{
+			.test_case_name =
+	"2446-05-10 Upper bound of 32bit >= timestamp. All extra sec bits on",
+			.msb_set = false,
+			.lower_bound = false,
+			.extra_bits = 3,
+			.expected = {.tv_sec = 0x37fffffffLL, .tv_nsec = 0L},
+		}
+	};
+
+	struct timespec64 timestamp;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(test_data); ++i) {
+		timestamp.tv_sec = get_32bit_time(&test_data[i]);
+		ext4_decode_extra_time(&timestamp,
+				       cpu_to_le32(test_data[i].extra_bits));
+
+		KUNIT_EXPECT_EQ_MSG(test,
+				    test_data[i].expected.tv_sec,
+				    timestamp.tv_sec,
+				    CASE_NAME_FORMAT,
+				    test_data[i].test_case_name,
+				    test_data[i].msb_set,
+				    test_data[i].lower_bound,
+				    test_data[i].extra_bits);
+		KUNIT_EXPECT_EQ_MSG(test,
+				    test_data[i].expected.tv_nsec,
+				    timestamp.tv_nsec,
+				    CASE_NAME_FORMAT,
+				    test_data[i].test_case_name,
+				    test_data[i].msb_set,
+				    test_data[i].lower_bound,
+				    test_data[i].extra_bits);
+	}
+}
+
+static struct kunit_case ext4_inode_test_cases[] = {
+	KUNIT_CASE(inode_test_xtimestamp_decoding),
+	{}
+};
+
+static struct kunit_suite ext4_inode_test_suite = {
+	.name = "ext4_inode_test",
+	.test_cases = ext4_inode_test_cases,
+};
+
+kunit_test_suite(ext4_inode_test_suite);
--
2.23.0.866.gb869b98d4c-goog

^ permalink raw reply related	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2019-10-17 22:13 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-10-16 21:29 [PATCH linux-kselftest/test v5] ext4: add kunit test for decoding extended timestamps Iurii Zaikin
2019-10-17  0:10 ` Shuah Khan
2019-10-17 22:12   ` Iurii Zaikin
  -- strict thread matches above, loose matches on Subject: below --
2019-10-16 20:58 Iurii Zaikin
2019-10-16 21:17 ` Brendan Higgins
2019-10-17 12:55 ` Theodore Y. Ts'o
2019-10-17 13:03   ` Theodore Y. Ts'o

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).