diff mbox series

[v2,02/10] syscalls/ioctl:add common c file for loop ioctl

Message ID 1586429086-22975-2-git-send-email-xuyang2018.jy@cn.fujitsu.com
State Accepted
Headers show
Series [v2,01/10] lapi/loop.h: Add fallback for loop ioctl and flag | expand

Commit Message

Yang Xu April 9, 2020, 10:44 a.m. UTC
Signed-off-by: Yang Xu <xuyang2018.jy@cn.fujitsu.com>
---
 testcases/kernel/syscalls/ioctl/Makefile      |  5 +++
 .../syscalls/ioctl/ioctl_loop_support.c       | 40 +++++++++++++++++++
 .../syscalls/ioctl/ioctl_loop_support.h       | 12 ++++++
 3 files changed, 57 insertions(+)
 create mode 100644 testcases/kernel/syscalls/ioctl/ioctl_loop_support.c
 create mode 100644 testcases/kernel/syscalls/ioctl/ioctl_loop_support.h

Comments

Cyril Hrubis April 17, 2020, 3:10 p.m. UTC | #1
Hi!
> +/*
> + * Copyright (c) 2020 FUJITSU LIMITED. All rights reserved.
> + * Author: Yang Xu <xuyang2018.jy@cn.fujitsu.com>
> + */
> +#define TST_NO_DEFAULT_MAIN
> +#include "ioctl_loop_support.h"
> +#include "tst_test.h"
> +
> +void check_sys_value(char *path, int setvalue)
> +{
> +	int getvalue;
> +
> +	SAFE_FILE_SCANF(path, "%d", &getvalue);
> +	if (setvalue == getvalue)
> +		tst_res(TPASS, "%s value is %d", path, setvalue);
> +	else
> +		tst_res(TFAIL, "%s value expected %d got %d", path, setvalue, getvalue);
> +}
> +
> +void check_sys_string(char *path, char *setmessage)
> +{
> +	char getmessage[1024];
> +
> +	SAFE_FILE_SCANF(path, "%s", getmessage);
> +	if (strcmp(setmessage, getmessage))
> +		tst_res(TFAIL, "%s expected %s got %s", path, setmessage, getmessage);
> +	else
> +		tst_res(TPASS, "%s string is %s", path, getmessage);
> +}

In the end I've renamed and moved these functions into the test library
because the functionality is generic enough and I doubt that these
tests would be the only one using it.
Yang Xu April 20, 2020, 2:23 a.m. UTC | #2
Hi Cyril


> Hi!
>> +/*
>> + * Copyright (c) 2020 FUJITSU LIMITED. All rights reserved.
>> + * Author: Yang Xu <xuyang2018.jy@cn.fujitsu.com>
>> + */
>> +#define TST_NO_DEFAULT_MAIN
>> +#include "ioctl_loop_support.h"
>> +#include "tst_test.h"
>> +
>> +void check_sys_value(char *path, int setvalue)
>> +{
>> +	int getvalue;
>> +
>> +	SAFE_FILE_SCANF(path, "%d", &getvalue);
>> +	if (setvalue == getvalue)
>> +		tst_res(TPASS, "%s value is %d", path, setvalue);
>> +	else
>> +		tst_res(TFAIL, "%s value expected %d got %d", path, setvalue, getvalue);
>> +}
>> +
>> +void check_sys_string(char *path, char *setmessage)
>> +{
>> +	char getmessage[1024];
>> +
>> +	SAFE_FILE_SCANF(path, "%s", getmessage);
>> +	if (strcmp(setmessage, getmessage))
>> +		tst_res(TFAIL, "%s expected %s got %s", path, setmessage, getmessage);
>> +	else
>> +		tst_res(TPASS, "%s string is %s", path, getmessage);
>> +}
> 
> In the end I've renamed and moved these functions into the test library
> because the functionality is generic enough and I doubt that these
> tests would be the only one using it.
That's great.  I remember prctl cases use this function. Also, in some 
cap cases, it needs bitwise operators(I only know prctl08.c). Maybe we 
can add TST_ASSERT_BITWISE?
>
Yang Xu April 20, 2020, 6:08 a.m. UTC | #3
Hi Cyril


> Hi Cyril
> 
> 
>> Hi!
>>> +/*
>>> + * Copyright (c) 2020 FUJITSU LIMITED. All rights reserved.
>>> + * Author: Yang Xu <xuyang2018.jy@cn.fujitsu.com>
>>> + */
>>> +#define TST_NO_DEFAULT_MAIN
>>> +#include "ioctl_loop_support.h"
>>> +#include "tst_test.h"
>>> +
>>> +void check_sys_value(char *path, int setvalue)
>>> +{
>>> +    int getvalue;
>>> +
>>> +    SAFE_FILE_SCANF(path, "%d", &getvalue);
>>> +    if (setvalue == getvalue)
>>> +        tst_res(TPASS, "%s value is %d", path, setvalue);
>>> +    else
>>> +        tst_res(TFAIL, "%s value expected %d got %d", path, 
>>> setvalue, getvalue);
>>> +}
>>> +
>>> +void check_sys_string(char *path, char *setmessage)
>>> +{
>>> +    char getmessage[1024];
>>> +
>>> +    SAFE_FILE_SCANF(path, "%s", getmessage);
>>> +    if (strcmp(setmessage, getmessage))
>>> +        tst_res(TFAIL, "%s expected %s got %s", path, setmessage, 
>>> getmessage);
>>> +    else
>>> +        tst_res(TPASS, "%s string is %s", path, getmessage);
>>> +}
>>
>> In the end I've renamed and moved these functions into the test library
>> because the functionality is generic enough and I doubt that these
>> tests would be the only one using it.
> That's great.  I remember prctl cases use this function. Also, in some 
> cap cases, it needs bitwise operators(I only know prctl08.c). Maybe we 
> can add TST_ASSERT_BITWISE?
This situation is rarely seen. I want to add two functions such as 
TST_ASSERT_FILE_STR/INT to compare file field string with expected 
string. So, I can use this api for prctl NoNewPrivs and Seccomp field in 
/proc/[pid]/status. What do you think about this?

--- a/lib/tst_assert.c
+++ b/lib/tst_assert.c
@@ -22,6 +22,20 @@ void tst_assert_int(const char *file, const int 
lineno, const char *path, int va
         tst_res_(file, lineno, TFAIL, "%s != %d got %d", path, val, 
sys_val);
  }

+void tst_assert_file_int(const char *file, const int lineno, const char 
*path, const char *buf, int val)
+{
+       int sys_val;
+
+       SAFE_FILE_LINES_SCANF(path, buf, &sys_val);
+
+       if (val == sys_val) {
+               tst_res_(file, lineno, TPASS, "%s %s field = %d", path, 
buf, sys_val);
+               return;
+       }
+
+       tst_res_(file, lineno, TFAIL, "%s %s field != %d got %d", path, 
buf, val, sys_val);
+}
+
  void tst_assert_str(const char *file, const int lineno, const char 
*path, const char *val)
  {
         char sys_val[1024];
@@ -34,3 +48,17 @@ void tst_assert_str(const char *file, const int 
lineno, const char *path, const

         tst_res_(file, lineno, TFAIL, "%s != '%s' got '%s'", path, val, 
sys_val);
  }
+
+void tst_assert_file_str(const char *file, const int lineno, const char 
*path, const char *buf, const char *val)
+{
+       char sys_val[1024];
+
+       SAFE_FILE_LINES_SCANF(path, buf, sys_val);
+
+       if (!strcmp(val, sys_val)) {
+               tst_res_(file, lineno, TPASS, "%s %s field = %s", path, 
buf, sys_val);
+               return;
+       }
+
+       tst_res_(file, lineno, TFAIL, "%s %s field != %s got %s", path, 
buf, val, sys_val);
+}


Best Regards
Yang Xu

>>
Cyril Hrubis April 20, 2020, 12:55 p.m. UTC | #4
Hi!
> > In the end I've renamed and moved these functions into the test library
> > because the functionality is generic enough and I doubt that these
> > tests would be the only one using it.
> That's great.  I remember prctl cases use this function. Also, in some 
> cap cases, it needs bitwise operators(I only know prctl08.c). Maybe we 
> can add TST_ASSERT_BITWISE?

I guess that we would need to pass to numbers to the bitwise operation,
one would be mask for which bits should be used for the comparsion and
one with the actual bits. Which tests would need that? I looked at
capset and capget tests but there does not seem to any bitwise checks on
values on proc or sys files.
Cyril Hrubis April 20, 2020, 1:01 p.m. UTC | #5
Hi!
> +void tst_assert_file_str(const char *file, const int lineno, const char 
> *path, const char *buf, const char *val)
> +{
> +       char sys_val[1024];
> +
> +       SAFE_FILE_LINES_SCANF(path, buf, sys_val);

We should call the file_lines_scanf() here and pass the filename and
lineno that this functions takes as parameter instead.

Also I'm not sure that it's a good idea to pass the fmt to this
function. I guess that it would be better to pass a prefix string such
as "foo=" and to append the "%s" in this function. That way we could
also encode the buffer length to the fmt string as well, in that case we
would append "%1024s".

> +       if (!strcmp(val, sys_val)) {
> +               tst_res_(file, lineno, TPASS, "%s %s field = %s", path, 
> buf, sys_val);
> +               return;
> +       }
> +
> +       tst_res_(file, lineno, TFAIL, "%s %s field != %s got %s", path, 
> buf, val, sys_val);
> +}
Yang Xu April 21, 2020, 6:19 a.m. UTC | #6
Hi Cyril


> Hi!
>> +void tst_assert_file_str(const char *file, const int lineno, const char
>> *path, const char *buf, const char *val)
>> +{
>> +       char sys_val[1024];
>> +
>> +       SAFE_FILE_LINES_SCANF(path, buf, sys_val);
> 
> We should call the file_lines_scanf() here and pass the filename and
> lineno that this functions takes as parameter instead.
I don't understand the meaning of adding filename and line parameter(If 
fail, it will report tst_assert.c: 29). Do you want to report the 
correct parsed filename when failed?

If so, I think lineno is meaningless and it also overides the place of 
the code meet problem . I prefer to add some path info in safe_file_ops.c.

> 
> Also I'm not sure that it's a good idea to pass the fmt to this
> function. I guess that it would be better to pass a prefix string such
> as "foo=" and to append the "%s" in this function. That way we could
> also encode the buffer length to the fmt string as well, in that case we
> would append "%1024s".
> 
Yes, it is a better way.

ps: I will send a patch about this api.

Best Regards
Yang Xu
>> +       if (!strcmp(val, sys_val)) {
>> +               tst_res_(file, lineno, TPASS, "%s %s field = %s", path,
>> buf, sys_val);
>> +               return;
>> +       }
>> +
>> +       tst_res_(file, lineno, TFAIL, "%s %s field != %s got %s", path,
>> buf, val, sys_val);
>> +}
> 
> 
>
Cyril Hrubis April 21, 2020, 8:55 a.m. UTC | #7
Hi!
> >> +void tst_assert_file_str(const char *file, const int lineno, const char
> >> *path, const char *buf, const char *val)
> >> +{
> >> +       char sys_val[1024];
> >> +
> >> +       SAFE_FILE_LINES_SCANF(path, buf, sys_val);
> > 
> > We should call the file_lines_scanf() here and pass the filename and
> > lineno that this functions takes as parameter instead.
> I don't understand the meaning of adding filename and line parameter(If 
> fail, it will report tst_assert.c: 29). Do you want to report the 
> correct parsed filename when failed?
> 
> If so, I think lineno is meaningless and it also overides the place of 
> the code meet problem . I prefer to add some path info in safe_file_ops.c.

What I want is to show the test source filename and line on failure, for
that we have to pass the lineno and file to the file_lines_scanf()
function. I think that it makes much more sense to print the line in a
test where the problem has happened rather than some location in the
library code.
Yang Xu April 21, 2020, 10:35 a.m. UTC | #8
Hi Cyril


> Hi!
>>>> +void tst_assert_file_str(const char *file, const int lineno, const char
>>>> *path, const char *buf, const char *val)
>>>> +{
>>>> +       char sys_val[1024];
>>>> +
>>>> +       SAFE_FILE_LINES_SCANF(path, buf, sys_val);
>>>
>>> We should call the file_lines_scanf() here and pass the filename and
>>> lineno that this functions takes as parameter instead.
>> I don't understand the meaning of adding filename and line parameter(If
>> fail, it will report tst_assert.c: 29). Do you want to report the
>> correct parsed filename when failed?
>>
>> If so, I think lineno is meaningless and it also overides the place of
>> the code meet problem . I prefer to add some path info in safe_file_ops.c.
> 
> What I want is to show the test source filename and line on failure, for
> that we have to pass the lineno and file to the file_lines_scanf()
> function. I think that it makes much more sense to print the line in a
> test where the problem has happened rather than some location in the
> library code.
Oh, I see. ie TST_ASSERT_INT, modify ioctl_loop01.c
TST_ASSERT_INT(__FILE__, __LINE__, partscan_path, 0);
if partscan_path doesn't exist, it will report error as below:
safe_file_ops.c:142: BROK: Failed to open FILE 
'/sys/block/loop0/loop1/partscan' for reading at ioctl_loop01.c:46: 
ENOENT (2)

--- a/lib/tst_assert.c
+++ b/lib/tst_assert.c
-void tst_assert_int(const char *file, const int lineno, const char 
*path, int val)
+void tst_assert_int(const char *file, const int lineno, const char 
*source_path,
+                   const int source_pos, const char *path, int val)
  {
         int sys_val;

-       SAFE_FILE_SCANF(path, "%d", &sys_val);
+       safe_file_scanf(source_path, source_pos, NULL, path, "%d", &sys_val

diff --git a/include/tst_assert.h b/include/tst_assert.h
index 913fff1b5..03e57bbd9 100644
--- a/include/tst_assert.h
+++ b/include/tst_assert.h
@@ -7,8 +7,8 @@
  #ifndef TST_ASSERT_H__
  #define TST_ASSERT_H__

-#define TST_ASSERT_INT(path, val) \
-       tst_assert_int(__FILE__, __LINE__, path, val)
+#define TST_ASSERT_INT(source_path, source_pos, path, val) \
+       tst_assert_int(__FILE__, __LINE__, source_path, source_pos, 
path, val)

  /*
   * Asserts that integer value stored in file pointed by path equals to the
@@ -16,6 +16,7 @@
   * values in sysfs, procfs, etc.
   */
  void tst_assert_int(const char *file, const int lineno,
+                   const char *source_path, const int source_pos,
                     const char *path, int val);

  #define TST_ASSERT_FILE_INT(path, buf, val)

>
Cyril Hrubis April 21, 2020, 12:12 p.m. UTC | #9
Hi!
> >>>> +void tst_assert_file_str(const char *file, const int lineno, const char
> >>>> *path, const char *buf, const char *val)
> >>>> +{
> >>>> +       char sys_val[1024];
> >>>> +
> >>>> +       SAFE_FILE_LINES_SCANF(path, buf, sys_val);
> >>>
> >>> We should call the file_lines_scanf() here and pass the filename and
> >>> lineno that this functions takes as parameter instead.
> >> I don't understand the meaning of adding filename and line parameter(If
> >> fail, it will report tst_assert.c: 29). Do you want to report the
> >> correct parsed filename when failed?
> >>
> >> If so, I think lineno is meaningless and it also overides the place of
> >> the code meet problem . I prefer to add some path info in safe_file_ops.c.
> > 
> > What I want is to show the test source filename and line on failure, for
> > that we have to pass the lineno and file to the file_lines_scanf()
> > function. I think that it makes much more sense to print the line in a
> > test where the problem has happened rather than some location in the
> > library code.
> Oh, I see. ie TST_ASSERT_INT, modify ioctl_loop01.c
> TST_ASSERT_INT(__FILE__, __LINE__, partscan_path, 0);
> if partscan_path doesn't exist, it will report error as below:
> safe_file_ops.c:142: BROK: Failed to open FILE 
> '/sys/block/loop0/loop1/partscan' for reading at ioctl_loop01.c:46: 
> ENOENT (2)

I still think that we are not on the same page.

The macros are to be used from tests, such as TST_ASSERT_INT() these
macros call the corresponding functions with __FILE__ and __LINE__, in
this case tst_assert_int(). From that point on anything that is called
from inside of the tst_assert_int() function should pass down the file
and lineno so that we get the filename and lineno from the line the call
has been called in the test.

So if we do TST_ASSERT_INT() in the test, we call tst_brk_() and pass
the file and lineno so that we get the correct test line in case of a
failure.

And for the same reason if we are going to get an value from a file from
inside of the assert function we have to call the safe_file_scanf() and
pass down the file and lineno so that if the call fails the test
filename and the line on which the call originated in the test is
printed.

Is it clear now?
Yang Xu April 22, 2020, 3:12 a.m. UTC | #10
Hi Cyril

> Hi!
>>>>>> +void tst_assert_file_str(const char *file, const int lineno, const char
>>>>>> *path, const char *buf, const char *val)
>>>>>> +{
>>>>>> +       char sys_val[1024];
>>>>>> +
>>>>>> +       SAFE_FILE_LINES_SCANF(path, buf, sys_val);
>>>>>
>>>>> We should call the file_lines_scanf() here and pass the filename and
>>>>> lineno that this functions takes as parameter instead.
>>>> I don't understand the meaning of adding filename and line parameter(If
>>>> fail, it will report tst_assert.c: 29). Do you want to report the
>>>> correct parsed filename when failed?
>>>>
>>>> If so, I think lineno is meaningless and it also overides the place of
>>>> the code meet problem . I prefer to add some path info in safe_file_ops.c.
>>>
>>> What I want is to show the test source filename and line on failure, for
>>> that we have to pass the lineno and file to the file_lines_scanf()
>>> function. I think that it makes much more sense to print the line in a
>>> test where the problem has happened rather than some location in the
>>> library code.
>> Oh, I see. ie TST_ASSERT_INT, modify ioctl_loop01.c
>> TST_ASSERT_INT(__FILE__, __LINE__, partscan_path, 0);
>> if partscan_path doesn't exist, it will report error as below:
>> safe_file_ops.c:142: BROK: Failed to open FILE
>> '/sys/block/loop0/loop1/partscan' for reading at ioctl_loop01.c:46:
>> ENOENT (2)
> 
> I still think that we are not on the same page.
> 
> The macros are to be used from tests, such as TST_ASSERT_INT() these
> macros call the corresponding functions with __FILE__ and __LINE__, in
> this case tst_assert_int(). From that point on anything that is called
> from inside of the tst_assert_int() function should pass down the file
> and lineno so that we get the filename and lineno from the line the call
> has been called in the test.
> 
> So if we do TST_ASSERT_INT() in the test, we call tst_brk_() and pass
> the file and lineno so that we get the correct test line in case of a
> failure.

> 
> And for the same reason if we are going to get an value from a file from
> inside of the assert function we have to call the safe_file_scanf() and
> pass down the file and lineno so that if the call fails the test
> filename and the line on which the call originated in the test is
> printed.
> 
> Is it clear now?
OK. I guess I only need to use safe_file_scanf(file, lineno, NULL, path, 
"%d", &sys_val) in tst_assert_int function as you suggested at the 
beginning.
>
diff mbox series

Patch

diff --git a/testcases/kernel/syscalls/ioctl/Makefile b/testcases/kernel/syscalls/ioctl/Makefile
index c2ff6c8e7..7bdc7daf0 100644
--- a/testcases/kernel/syscalls/ioctl/Makefile
+++ b/testcases/kernel/syscalls/ioctl/Makefile
@@ -7,6 +7,11 @@  include $(top_srcdir)/include/mk/testcases.mk
 
 INSTALL_TARGETS		+= test_ioctl
 
+FILTER_OUT_MAKE_TARGETS += ioctl_loop_support
+
+LOOP_TARGETS            := $(patsubst $(abs_srcdir)/%.c,%,$(wildcard $(abs_srcdir)/ioctl_loop[0-9]*.c))
+$(LOOP_TARGETS): %: ioctl_loop_support.o
+
 ifeq ($(ANDROID),1)
 FILTER_OUT_MAKE_TARGETS	+= ioctl02
 endif
diff --git a/testcases/kernel/syscalls/ioctl/ioctl_loop_support.c b/testcases/kernel/syscalls/ioctl/ioctl_loop_support.c
new file mode 100644
index 000000000..75c7b1b9a
--- /dev/null
+++ b/testcases/kernel/syscalls/ioctl/ioctl_loop_support.c
@@ -0,0 +1,40 @@ 
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2020 FUJITSU LIMITED. All rights reserved.
+ * Author: Yang Xu <xuyang2018.jy@cn.fujitsu.com>
+ */
+#define TST_NO_DEFAULT_MAIN
+#include "ioctl_loop_support.h"
+#include "tst_test.h"
+
+void check_sys_value(char *path, int setvalue)
+{
+	int getvalue;
+
+	SAFE_FILE_SCANF(path, "%d", &getvalue);
+	if (setvalue == getvalue)
+		tst_res(TPASS, "%s value is %d", path, setvalue);
+	else
+		tst_res(TFAIL, "%s value expected %d got %d", path, setvalue, getvalue);
+}
+
+void check_sys_string(char *path, char *setmessage)
+{
+	char getmessage[1024];
+
+	SAFE_FILE_SCANF(path, "%s", getmessage);
+	if (strcmp(setmessage, getmessage))
+		tst_res(TFAIL, "%s expected %s got %s", path, setmessage, getmessage);
+	else
+		tst_res(TPASS, "%s string is %s", path, getmessage);
+}
+
+void check_support_cmd(int dev_fd, int ioctl_flag, int value, char *message)
+{
+	int ret = 0;
+
+	ret = ioctl(dev_fd, ioctl_flag, value);
+	if (ret && errno == EINVAL)
+		tst_brk(TCONF, "Current environment doesn't support this flag(%s)",
+				message);
+}
diff --git a/testcases/kernel/syscalls/ioctl/ioctl_loop_support.h b/testcases/kernel/syscalls/ioctl/ioctl_loop_support.h
new file mode 100644
index 000000000..ade64e82e
--- /dev/null
+++ b/testcases/kernel/syscalls/ioctl/ioctl_loop_support.h
@@ -0,0 +1,12 @@ 
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2020 FUJITSU LIMITED. All rights reserved.
+ * Author: Yang Xu <xuyang2018.jy@cn.fujitsu.com>
+ */
+#ifndef IOCTL_LOOP_H
+#define IOCTL_lOOP_H
+#include <linux/loop.h>
+void check_sys_value(char *path, int setvalue);
+void check_sys_string(char *path, char *setmessage);
+void check_support_cmd(int dev_fd, int ioctl_flag, int value, char *message);
+#endif