0001
0002
0003
0004
0005
0006
0007 #include <kunit/test.h>
0008 #include <linux/kernel.h>
0009 #include <linux/time64.h>
0010
0011 #include "ext4.h"
0012
0013
0014
0015
0016
0017 #define LOWER_MSB_0 0L
0018
0019
0020
0021
0022
0023 #define UPPER_MSB_0 0x7fffffffL
0024
0025
0026
0027
0028 #define LOWER_MSB_1 (-(UPPER_MSB_0) - 1L)
0029
0030
0031
0032
0033 #define UPPER_MSB_1 (-1L)
0034
0035
0036
0037
0038 #define MAX_NANOSECONDS ((1L << 30) - 1)
0039
0040 #define CASE_NAME_FORMAT "%s: msb:%x lower_bound:%x extra_bits: %x"
0041
0042 #define LOWER_BOUND_NEG_NO_EXTRA_BITS_CASE\
0043 "1901-12-13 Lower bound of 32bit < 0 timestamp, no extra bits"
0044 #define UPPER_BOUND_NEG_NO_EXTRA_BITS_CASE\
0045 "1969-12-31 Upper bound of 32bit < 0 timestamp, no extra bits"
0046 #define LOWER_BOUND_NONNEG_NO_EXTRA_BITS_CASE\
0047 "1970-01-01 Lower bound of 32bit >=0 timestamp, no extra bits"
0048 #define UPPER_BOUND_NONNEG_NO_EXTRA_BITS_CASE\
0049 "2038-01-19 Upper bound of 32bit >=0 timestamp, no extra bits"
0050 #define LOWER_BOUND_NEG_LO_1_CASE\
0051 "2038-01-19 Lower bound of 32bit <0 timestamp, lo extra sec bit on"
0052 #define UPPER_BOUND_NEG_LO_1_CASE\
0053 "2106-02-07 Upper bound of 32bit <0 timestamp, lo extra sec bit on"
0054 #define LOWER_BOUND_NONNEG_LO_1_CASE\
0055 "2106-02-07 Lower bound of 32bit >=0 timestamp, lo extra sec bit on"
0056 #define UPPER_BOUND_NONNEG_LO_1_CASE\
0057 "2174-02-25 Upper bound of 32bit >=0 timestamp, lo extra sec bit on"
0058 #define LOWER_BOUND_NEG_HI_1_CASE\
0059 "2174-02-25 Lower bound of 32bit <0 timestamp, hi extra sec bit on"
0060 #define UPPER_BOUND_NEG_HI_1_CASE\
0061 "2242-03-16 Upper bound of 32bit <0 timestamp, hi extra sec bit on"
0062 #define LOWER_BOUND_NONNEG_HI_1_CASE\
0063 "2242-03-16 Lower bound of 32bit >=0 timestamp, hi extra sec bit on"
0064 #define UPPER_BOUND_NONNEG_HI_1_CASE\
0065 "2310-04-04 Upper bound of 32bit >=0 timestamp, hi extra sec bit on"
0066 #define UPPER_BOUND_NONNEG_HI_1_NS_1_CASE\
0067 "2310-04-04 Upper bound of 32bit>=0 timestamp, hi extra sec bit 1. 1 ns"
0068 #define LOWER_BOUND_NONNEG_HI_1_NS_MAX_CASE\
0069 "2378-04-22 Lower bound of 32bit>= timestamp. Extra sec bits 1. Max ns"
0070 #define LOWER_BOUND_NONNEG_EXTRA_BITS_1_CASE\
0071 "2378-04-22 Lower bound of 32bit >=0 timestamp. All extra sec bits on"
0072 #define UPPER_BOUND_NONNEG_EXTRA_BITS_1_CASE\
0073 "2446-05-10 Upper bound of 32bit >=0 timestamp. All extra sec bits on"
0074
0075 struct timestamp_expectation {
0076 const char *test_case_name;
0077 struct timespec64 expected;
0078 u32 extra_bits;
0079 bool msb_set;
0080 bool lower_bound;
0081 };
0082
0083 static const struct timestamp_expectation test_data[] = {
0084 {
0085 .test_case_name = LOWER_BOUND_NEG_NO_EXTRA_BITS_CASE,
0086 .msb_set = true,
0087 .lower_bound = true,
0088 .extra_bits = 0,
0089 .expected = {.tv_sec = -0x80000000LL, .tv_nsec = 0L},
0090 },
0091
0092 {
0093 .test_case_name = UPPER_BOUND_NEG_NO_EXTRA_BITS_CASE,
0094 .msb_set = true,
0095 .lower_bound = false,
0096 .extra_bits = 0,
0097 .expected = {.tv_sec = -1LL, .tv_nsec = 0L},
0098 },
0099
0100 {
0101 .test_case_name = LOWER_BOUND_NONNEG_NO_EXTRA_BITS_CASE,
0102 .msb_set = false,
0103 .lower_bound = true,
0104 .extra_bits = 0,
0105 .expected = {0LL, 0L},
0106 },
0107
0108 {
0109 .test_case_name = UPPER_BOUND_NONNEG_NO_EXTRA_BITS_CASE,
0110 .msb_set = false,
0111 .lower_bound = false,
0112 .extra_bits = 0,
0113 .expected = {.tv_sec = 0x7fffffffLL, .tv_nsec = 0L},
0114 },
0115
0116 {
0117 .test_case_name = LOWER_BOUND_NEG_LO_1_CASE,
0118 .msb_set = true,
0119 .lower_bound = true,
0120 .extra_bits = 1,
0121 .expected = {.tv_sec = 0x80000000LL, .tv_nsec = 0L},
0122 },
0123
0124 {
0125 .test_case_name = UPPER_BOUND_NEG_LO_1_CASE,
0126 .msb_set = true,
0127 .lower_bound = false,
0128 .extra_bits = 1,
0129 .expected = {.tv_sec = 0xffffffffLL, .tv_nsec = 0L},
0130 },
0131
0132 {
0133 .test_case_name = LOWER_BOUND_NONNEG_LO_1_CASE,
0134 .msb_set = false,
0135 .lower_bound = true,
0136 .extra_bits = 1,
0137 .expected = {.tv_sec = 0x100000000LL, .tv_nsec = 0L},
0138 },
0139
0140 {
0141 .test_case_name = UPPER_BOUND_NONNEG_LO_1_CASE,
0142 .msb_set = false,
0143 .lower_bound = false,
0144 .extra_bits = 1,
0145 .expected = {.tv_sec = 0x17fffffffLL, .tv_nsec = 0L},
0146 },
0147
0148 {
0149 .test_case_name = LOWER_BOUND_NEG_HI_1_CASE,
0150 .msb_set = true,
0151 .lower_bound = true,
0152 .extra_bits = 2,
0153 .expected = {.tv_sec = 0x180000000LL, .tv_nsec = 0L},
0154 },
0155
0156 {
0157 .test_case_name = UPPER_BOUND_NEG_HI_1_CASE,
0158 .msb_set = true,
0159 .lower_bound = false,
0160 .extra_bits = 2,
0161 .expected = {.tv_sec = 0x1ffffffffLL, .tv_nsec = 0L},
0162 },
0163
0164 {
0165 .test_case_name = LOWER_BOUND_NONNEG_HI_1_CASE,
0166 .msb_set = false,
0167 .lower_bound = true,
0168 .extra_bits = 2,
0169 .expected = {.tv_sec = 0x200000000LL, .tv_nsec = 0L},
0170 },
0171
0172 {
0173 .test_case_name = UPPER_BOUND_NONNEG_HI_1_CASE,
0174 .msb_set = false,
0175 .lower_bound = false,
0176 .extra_bits = 2,
0177 .expected = {.tv_sec = 0x27fffffffLL, .tv_nsec = 0L},
0178 },
0179
0180 {
0181 .test_case_name = UPPER_BOUND_NONNEG_HI_1_NS_1_CASE,
0182 .msb_set = false,
0183 .lower_bound = false,
0184 .extra_bits = 6,
0185 .expected = {.tv_sec = 0x27fffffffLL, .tv_nsec = 1L},
0186 },
0187
0188 {
0189 .test_case_name = LOWER_BOUND_NONNEG_HI_1_NS_MAX_CASE,
0190 .msb_set = false,
0191 .lower_bound = true,
0192 .extra_bits = 0xFFFFFFFF,
0193 .expected = {.tv_sec = 0x300000000LL,
0194 .tv_nsec = MAX_NANOSECONDS},
0195 },
0196
0197 {
0198 .test_case_name = LOWER_BOUND_NONNEG_EXTRA_BITS_1_CASE,
0199 .msb_set = false,
0200 .lower_bound = true,
0201 .extra_bits = 3,
0202 .expected = {.tv_sec = 0x300000000LL, .tv_nsec = 0L},
0203 },
0204
0205 {
0206 .test_case_name = UPPER_BOUND_NONNEG_EXTRA_BITS_1_CASE,
0207 .msb_set = false,
0208 .lower_bound = false,
0209 .extra_bits = 3,
0210 .expected = {.tv_sec = 0x37fffffffLL, .tv_nsec = 0L},
0211 }
0212 };
0213
0214 static void timestamp_expectation_to_desc(const struct timestamp_expectation *t,
0215 char *desc)
0216 {
0217 strscpy(desc, t->test_case_name, KUNIT_PARAM_DESC_SIZE);
0218 }
0219
0220 KUNIT_ARRAY_PARAM(ext4_inode, test_data, timestamp_expectation_to_desc);
0221
0222 static time64_t get_32bit_time(const struct timestamp_expectation * const test)
0223 {
0224 if (test->msb_set) {
0225 if (test->lower_bound)
0226 return LOWER_MSB_1;
0227
0228 return UPPER_MSB_1;
0229 }
0230
0231 if (test->lower_bound)
0232 return LOWER_MSB_0;
0233 return UPPER_MSB_0;
0234 }
0235
0236
0237
0238
0239
0240
0241 static void inode_test_xtimestamp_decoding(struct kunit *test)
0242 {
0243 struct timespec64 timestamp;
0244
0245 struct timestamp_expectation *test_param =
0246 (struct timestamp_expectation *)(test->param_value);
0247
0248 timestamp.tv_sec = get_32bit_time(test_param);
0249 ext4_decode_extra_time(×tamp,
0250 cpu_to_le32(test_param->extra_bits));
0251
0252 KUNIT_EXPECT_EQ_MSG(test,
0253 test_param->expected.tv_sec,
0254 timestamp.tv_sec,
0255 CASE_NAME_FORMAT,
0256 test_param->test_case_name,
0257 test_param->msb_set,
0258 test_param->lower_bound,
0259 test_param->extra_bits);
0260 KUNIT_EXPECT_EQ_MSG(test,
0261 test_param->expected.tv_nsec,
0262 timestamp.tv_nsec,
0263 CASE_NAME_FORMAT,
0264 test_param->test_case_name,
0265 test_param->msb_set,
0266 test_param->lower_bound,
0267 test_param->extra_bits);
0268 }
0269
0270 static struct kunit_case ext4_inode_test_cases[] = {
0271 KUNIT_CASE_PARAM(inode_test_xtimestamp_decoding, ext4_inode_gen_params),
0272 {}
0273 };
0274
0275 static struct kunit_suite ext4_inode_test_suite = {
0276 .name = "ext4_inode_test",
0277 .test_cases = ext4_inode_test_cases,
0278 };
0279
0280 kunit_test_suites(&ext4_inode_test_suite);
0281
0282 MODULE_LICENSE("GPL v2");