1f08c3bdfSopenharmony_ciC Test Case Tutorial
2f08c3bdfSopenharmony_ci====================
3f08c3bdfSopenharmony_ci
4f08c3bdfSopenharmony_ciNOTE: See also
5f08c3bdfSopenharmony_ci      https://github.com/linux-test-project/ltp/wiki/Test-Writing-Guidelines[Test Writing Guidelines],
6f08c3bdfSopenharmony_ci      https://github.com/linux-test-project/ltp/wiki/C-Test-API[C Test API].
7f08c3bdfSopenharmony_ci
8f08c3bdfSopenharmony_ciThis is a step-by-step tutorial on writing a simple C LTP test, where topics
9f08c3bdfSopenharmony_ciof the LTP and Linux kernel testing will be introduced gradually using a
10f08c3bdfSopenharmony_ciconcrete example. Most sections will include exercises, some trivial and
11f08c3bdfSopenharmony_ciothers not so much. If you find an exercise is leading you off at too much of
12f08c3bdfSopenharmony_cia tangent, just leave it for later and move on.
13f08c3bdfSopenharmony_ci
14f08c3bdfSopenharmony_ciLTP tests can be written in C or Shell script. This tutorial is only for tests
15f08c3bdfSopenharmony_ciwritten in C using the new LTP test API. Note that while we go into some
16f08c3bdfSopenharmony_cidetail on using Git, this is not intended as a canonical or complete guide
17f08c3bdfSopenharmony_cifor Git.
18f08c3bdfSopenharmony_ci
19f08c3bdfSopenharmony_ci0. Assumptions & Feedback
20f08c3bdfSopenharmony_ci-------------------------
21f08c3bdfSopenharmony_ci
22f08c3bdfSopenharmony_ciWe assume the reader is familiar with C, Git and common Unix/Linux/GNU tools
23f08c3bdfSopenharmony_ciand has some general knowledge of Operating Systems. Experienced Linux
24f08c3bdfSopenharmony_cidevelopers may find it too verbose while people new to system level Linux
25f08c3bdfSopenharmony_cidevelopment may find it overwhelming.
26f08c3bdfSopenharmony_ci
27f08c3bdfSopenharmony_ciComments and feedback are welcome, please direct them to
28f08c3bdfSopenharmony_cihttps://lists.linux.it/listinfo/ltp[the mailing list].
29f08c3bdfSopenharmony_ci
30f08c3bdfSopenharmony_ci1. Getting Started
31f08c3bdfSopenharmony_ci------------------
32f08c3bdfSopenharmony_ci
33f08c3bdfSopenharmony_ciGit-clone the main LTP repository as described in
34f08c3bdfSopenharmony_cihttps://github.com/linux-test-project/ltp#quick-guide-to-running-the-tests[the +README.md+]
35f08c3bdfSopenharmony_ciand change directory to the checked-out Git repository. We recommend installing the LTP
36f08c3bdfSopenharmony_ciand running one of the tests mentioned in the Quick guide (in the +README.md+) to
37f08c3bdfSopenharmony_ciensure you are starting from a good state.
38f08c3bdfSopenharmony_ci
39f08c3bdfSopenharmony_ciWe also recommended cloning the Linux kernel repository for reference, this
40f08c3bdfSopenharmony_ciguide will refer to files and directories within the mainline kernel 4.12.
41f08c3bdfSopenharmony_ci
42f08c3bdfSopenharmony_ci[source,shell]
43f08c3bdfSopenharmony_ci------------------------------------------------------------------------------
44f08c3bdfSopenharmony_ci$ git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
45f08c3bdfSopenharmony_ci------------------------------------------------------------------------------
46f08c3bdfSopenharmony_ci
47f08c3bdfSopenharmony_ciThere are a number of other repositories which are useful for reference as
48f08c3bdfSopenharmony_ciwell, including the GNU C library +glibc+ and the alternative C library
49f08c3bdfSopenharmony_ci+musl+. Some system calls are partially or even entirely implemented in user
50f08c3bdfSopenharmony_ciland as part of the standard C library. So in these cases, the C library is an
51f08c3bdfSopenharmony_ciimportant reference. +glibc+ is the most common C library for Linux, however
52f08c3bdfSopenharmony_ci+musl+ is generally easier to understand.
53f08c3bdfSopenharmony_ci
54f08c3bdfSopenharmony_ciHow system calls are implemented varies from one architecture to another and
55f08c3bdfSopenharmony_ciacross kernel and C library versions. To find out whether a system call is
56f08c3bdfSopenharmony_ciactually accessing the kernel (whether it is actually a system call) on any
57f08c3bdfSopenharmony_cigiven machine you can use the +strace+ utility. This intercepts system calls
58f08c3bdfSopenharmony_cimade by an executable and prints them. We will use this later in the tutorial.
59f08c3bdfSopenharmony_ci
60f08c3bdfSopenharmony_ci2. Choose a System Call to test
61f08c3bdfSopenharmony_ci-------------------------------
62f08c3bdfSopenharmony_ci
63f08c3bdfSopenharmony_ciWe will use the +statx()+ system call, to provide a concrete example of a
64f08c3bdfSopenharmony_citest. At the time of writing there is no test for this call which was
65f08c3bdfSopenharmony_ciintroduced in Linux kernel version 4.11.
66f08c3bdfSopenharmony_ci
67f08c3bdfSopenharmony_ciLinux system call specific tests are primarily contained in
68f08c3bdfSopenharmony_ci+testcases/kernel/syscalls+, but you should also +git grep+ the entire LTP
69f08c3bdfSopenharmony_cirepository to check for any existing usages of a system call.
70f08c3bdfSopenharmony_ci
71f08c3bdfSopenharmony_ciOne way to find a system call which is not currently tested by the LTP is to
72f08c3bdfSopenharmony_cilook at +include/linux/syscalls.h+ in the kernel tree.
73f08c3bdfSopenharmony_ci
74f08c3bdfSopenharmony_ciSomething the LTP excels at is ensuring bug-fixes are back ported to
75f08c3bdfSopenharmony_cimaintenance releases, so targeting a specific regression is another
76f08c3bdfSopenharmony_cioption.
77f08c3bdfSopenharmony_ci
78f08c3bdfSopenharmony_ci2.1. Find an untested System call
79f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
80f08c3bdfSopenharmony_ci
81f08c3bdfSopenharmony_ciTry to find an untested system call which has a manual page (i.e. +man
82f08c3bdfSopenharmony_cisyscall+ produces a result). It is a good idea to Git-clone the latest kernel
83f08c3bdfSopenharmony_ciman-pages repository.
84f08c3bdfSopenharmony_ci
85f08c3bdfSopenharmony_ci[source,shell]
86f08c3bdfSopenharmony_ci------------------------------------------------------------------------------
87f08c3bdfSopenharmony_ci$ git clone git://git.kernel.org/pub/scm/docs/man-pages/man-pages.git
88f08c3bdfSopenharmony_ci------------------------------------------------------------------------------
89f08c3bdfSopenharmony_ci
90f08c3bdfSopenharmony_ciAt the time of writing the difference between the latest man-pages release and
91f08c3bdfSopenharmony_cithe +HEAD+ of the repository (usually the latest commit) is well over 100
92f08c3bdfSopenharmony_cicommits. This represents about 9 weeks of changes. If you are using a stable
93f08c3bdfSopenharmony_ciLinux distribution, your man-pages package may well be years old. So as with
94f08c3bdfSopenharmony_cithe kernel, it is best to have the Git repository as a reference.
95f08c3bdfSopenharmony_ci
96f08c3bdfSopenharmony_ciYou could also find a system call with untested parameters or use whatever it
97f08c3bdfSopenharmony_ciis you are planning to use the LTP for.
98f08c3bdfSopenharmony_ci
99f08c3bdfSopenharmony_ci3. Create the test skeleton
100f08c3bdfSopenharmony_ci---------------------------
101f08c3bdfSopenharmony_ci
102f08c3bdfSopenharmony_ciI shall call my test +statx01.c+, by the time you read this that file name
103f08c3bdfSopenharmony_ciwill probably be taken, so increment the number in the file name as
104f08c3bdfSopenharmony_ciappropriate or replace +statx+ with the system call chosen in exercise 2.1.
105f08c3bdfSopenharmony_ci
106f08c3bdfSopenharmony_ci[source,shell]
107f08c3bdfSopenharmony_ci------------------------------------------------------------------------------
108f08c3bdfSopenharmony_ci$ mkdir testcases/kernel/syscalls/statx
109f08c3bdfSopenharmony_ci$ cd testcases/kernel/syscalls/statx
110f08c3bdfSopenharmony_ci$ echo statx >> .gitignore
111f08c3bdfSopenharmony_ci------------------------------------------------------------------------------
112f08c3bdfSopenharmony_ci
113f08c3bdfSopenharmony_ciNext open +statx01.c+ and add the following boilerplate. Make sure to change
114f08c3bdfSopenharmony_cithe copy right notice to your name/company, correct the test name and minimum
115f08c3bdfSopenharmony_cikernel version if necessary. I will explain what the code does below.
116f08c3bdfSopenharmony_ci
117f08c3bdfSopenharmony_ci[source,c]
118f08c3bdfSopenharmony_ci------------------------------------------------------------------------------
119f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
120f08c3bdfSopenharmony_ci/*
121f08c3bdfSopenharmony_ci * Copyright (c) 2017 Instruction Ignorer <"can't"@be.bothered.com>
122f08c3bdfSopenharmony_ci */
123f08c3bdfSopenharmony_ci
124f08c3bdfSopenharmony_ci/*\
125f08c3bdfSopenharmony_ci * [Description]
126f08c3bdfSopenharmony_ci *
127f08c3bdfSopenharmony_ci * All tests should start with a description of _what_ we are testing.
128f08c3bdfSopenharmony_ci * Non-trivial explanations of _how_ the code works should also go here.
129f08c3bdfSopenharmony_ci * Include relevant links, Git commit hashes and CVE numbers.
130f08c3bdfSopenharmony_ci * Inline comments should be avoided.
131f08c3bdfSopenharmony_ci */
132f08c3bdfSopenharmony_ci
133f08c3bdfSopenharmony_ci#include "tst_test.h"
134f08c3bdfSopenharmony_ci
135f08c3bdfSopenharmony_cistatic void run(void)
136f08c3bdfSopenharmony_ci{
137f08c3bdfSopenharmony_ci	tst_res(TPASS, "Doing hardly anything is easy");
138f08c3bdfSopenharmony_ci}
139f08c3bdfSopenharmony_ci
140f08c3bdfSopenharmony_cistatic struct tst_test test = {
141f08c3bdfSopenharmony_ci	.test_all = run,
142f08c3bdfSopenharmony_ci	.min_kver = "4.11",
143f08c3bdfSopenharmony_ci};
144f08c3bdfSopenharmony_ci------------------------------------------------------------------------------
145f08c3bdfSopenharmony_ci
146f08c3bdfSopenharmony_ciStarting with the +#include+ statement we copy in the main LTP test library
147f08c3bdfSopenharmony_ciheaders. This includes the most common test API functions and the test harness
148f08c3bdfSopenharmony_ciinitialisation code. It is important to note that this is a completely
149f08c3bdfSopenharmony_ciordinary, independent C program, however +main()+ is missing because it is
150f08c3bdfSopenharmony_ciimplemented in +tst_test.h+.
151f08c3bdfSopenharmony_ci
152f08c3bdfSopenharmony_ciWe specify what code we want to run as part of the test using the +tst_test
153f08c3bdfSopenharmony_citest+ structure. Various callbacks can be set by the test writer, including
154f08c3bdfSopenharmony_ci+test.test_all+, which we have set to +run()+. The test harness will execute
155f08c3bdfSopenharmony_cithis callback in a separate process (using +fork()+), forcibly terminating it
156f08c3bdfSopenharmony_ciif it does not return after +test.timeout+ seconds.
157f08c3bdfSopenharmony_ci
158f08c3bdfSopenharmony_ciWe have also set +test.min_kver+ to the kernel version where +statx+ was
159f08c3bdfSopenharmony_ciintroduced. The test library will determine the kernel version at runtime. If
160f08c3bdfSopenharmony_cithe version is less than 4.11 then the test harness will return +TCONF+,
161f08c3bdfSopenharmony_ciindicating that this test is not suitable for the current system
162f08c3bdfSopenharmony_ciconfiguration.
163f08c3bdfSopenharmony_ci
164f08c3bdfSopenharmony_ciOccasionally features are back ported to older kernel versions, so +statx+ may
165f08c3bdfSopenharmony_ciexist on kernels with a lower version. However we don't need to worry about
166f08c3bdfSopenharmony_cithat unless there is evidence of it happening.
167f08c3bdfSopenharmony_ci
168f08c3bdfSopenharmony_ciAs mentioned in the code itself, you should specify what you are testing and
169f08c3bdfSopenharmony_cithe expected outcome, even if it is relatively simple. If your program flow is
170f08c3bdfSopenharmony_cinecessarily complex and difficult to understand (which is often the case when
171f08c3bdfSopenharmony_citrying to manipulate the kernel into doing something bad), then a detailed
172f08c3bdfSopenharmony_ciexplanation of how the code works is welcome.
173f08c3bdfSopenharmony_ci
174f08c3bdfSopenharmony_ciWhat you should not do, is use inline comments or include the same level of
175f08c3bdfSopenharmony_ciexplanation which is written here. As a general rule, if something is easy to
176f08c3bdfSopenharmony_cidocument, then the code should also be easy to read. So don't document the easy
177f08c3bdfSopenharmony_cistuff (except for the basic test specification).
178f08c3bdfSopenharmony_ci
179f08c3bdfSopenharmony_ciBefore continuing we should compile this and check that the basics work. In
180f08c3bdfSopenharmony_ciorder to compile the test we need a +Makefile+ in the same subdirectory. If
181f08c3bdfSopenharmony_cione already exists, then nothing needs to be done, otherwise add one with the
182f08c3bdfSopenharmony_cifollowing contents.
183f08c3bdfSopenharmony_ci
184f08c3bdfSopenharmony_ci[source,make]
185f08c3bdfSopenharmony_ci------------------------------------------------------------------------------
186f08c3bdfSopenharmony_ci# SPDX-License-Identifier: GPL-2.0-or-later
187f08c3bdfSopenharmony_ci# Copyright (c) 2019 Linux Test Project
188f08c3bdfSopenharmony_ci
189f08c3bdfSopenharmony_citop_srcdir		?= ../../../..
190f08c3bdfSopenharmony_ci
191f08c3bdfSopenharmony_ciinclude $(top_srcdir)/include/mk/testcases.mk
192f08c3bdfSopenharmony_ci
193f08c3bdfSopenharmony_ciinclude $(top_srcdir)/include/mk/generic_leaf_target.mk
194f08c3bdfSopenharmony_ci
195f08c3bdfSopenharmony_ci------------------------------------------------------------------------------
196f08c3bdfSopenharmony_ci
197f08c3bdfSopenharmony_ciThis will automatically add +statx01.c+ as a build target producing a
198f08c3bdfSopenharmony_ci+statx01+ executable. Unless you have heavily deviated from the tutorial, and
199f08c3bdfSopenharmony_ciprobably need to change +top_srcdir+, nothing else needs to be done.
200f08c3bdfSopenharmony_ci
201f08c3bdfSopenharmony_ciNormally, if you were starting a Makefile from scratch, then you would need to
202f08c3bdfSopenharmony_ciadd +statx01+ as a build target. Specifying that you would like to run some
203f08c3bdfSopenharmony_ciprogram (e.g. +gcc+ or +clang+) to transform +statx01.c+ into +statx01+. Here
204f08c3bdfSopenharmony_ciwe don't need to do that, but sometimes it is still necessary. For example, if
205f08c3bdfSopenharmony_ciwe needed to link to the POSIX threading library, then we could add the
206f08c3bdfSopenharmony_cifollowing line after +testcases.mk+.
207f08c3bdfSopenharmony_ci
208f08c3bdfSopenharmony_ci[source,make]
209f08c3bdfSopenharmony_ci--------------------------------------------------------------------------------
210f08c3bdfSopenharmony_cistatx01: CFLAGS += -pthread
211f08c3bdfSopenharmony_ci--------------------------------------------------------------------------------
212f08c3bdfSopenharmony_ci
213f08c3bdfSopenharmony_ciAssuming you are in the test's subdirectory +testcases/kernel/syscalls/statx+,
214f08c3bdfSopenharmony_cido
215f08c3bdfSopenharmony_ci
216f08c3bdfSopenharmony_ci[source,shell]
217f08c3bdfSopenharmony_ci--------------------------------------------------------------------------------
218f08c3bdfSopenharmony_ci$ make
219f08c3bdfSopenharmony_ci$ ./statx01
220f08c3bdfSopenharmony_ci--------------------------------------------------------------------------------
221f08c3bdfSopenharmony_ci
222f08c3bdfSopenharmony_ciThis should build the test and then run it. However, even though the test is
223f08c3bdfSopenharmony_ciin the +syscalls+ directory it won't be automatically ran as part of the
224f08c3bdfSopenharmony_ci_syscalls_ test group (remember +./runltp -f syscalls+ from the +README.md+?). For
225f08c3bdfSopenharmony_cithis we need to add it to the +runtest+ file. So open +runtest/syscalls+ and add
226f08c3bdfSopenharmony_cithe lines starting with a +++.
227f08c3bdfSopenharmony_ci
228f08c3bdfSopenharmony_ci[source,diff]
229f08c3bdfSopenharmony_ci--------------------------------------------------------------------------------
230f08c3bdfSopenharmony_ci statvfs01 statvfs01
231f08c3bdfSopenharmony_ci statvfs02 statvfs02
232f08c3bdfSopenharmony_ci
233f08c3bdfSopenharmony_ci+statx01 statx01
234f08c3bdfSopenharmony_ci+
235f08c3bdfSopenharmony_ci stime01 stime01
236f08c3bdfSopenharmony_ci stime02 stime02
237f08c3bdfSopenharmony_ci
238f08c3bdfSopenharmony_ci--------------------------------------------------------------------------------
239f08c3bdfSopenharmony_ci
240f08c3bdfSopenharmony_ciThe +runtest+ files are in a two column format. The first column is the test
241f08c3bdfSopenharmony_ciname, which is mainly used by test runners for reporting and filtering. It is
242f08c3bdfSopenharmony_cijust a single string of text with no spaces. The second column, which can
243f08c3bdfSopenharmony_cicontain spaces, is passed to the shell in order to execute the test. Often it
244f08c3bdfSopenharmony_ciis just the executable name, but some tests also take arguments (the LTP has a
245f08c3bdfSopenharmony_cilibrary for argument parsing, by the way).
246f08c3bdfSopenharmony_ci
247f08c3bdfSopenharmony_ciIf you haven't done so already, we should add all these new files to Git. It
248f08c3bdfSopenharmony_ciis vitally important that you do not make changes to the master branch. If you
249f08c3bdfSopenharmony_cido then pulling changes from upstream becomes a major issue. So first of all
250f08c3bdfSopenharmony_cicreate a new branch.
251f08c3bdfSopenharmony_ci
252f08c3bdfSopenharmony_ci[source,shell]
253f08c3bdfSopenharmony_ci--------------------------------------------------------------------------------
254f08c3bdfSopenharmony_ci$ git checkout -b statx01 master
255f08c3bdfSopenharmony_ci--------------------------------------------------------------------------------
256f08c3bdfSopenharmony_ci
257f08c3bdfSopenharmony_ciNow we want to add the files we have created or modified, but before doing a
258f08c3bdfSopenharmony_cicommit make sure you have configured Git correctly. You need to at least set
259f08c3bdfSopenharmony_ciyour Name and e-mail address in +~/.gitconfig+, but there are some other
260f08c3bdfSopenharmony_cisettings which come in handy too. My relatively simple configuration is similar to
261f08c3bdfSopenharmony_cithe below
262f08c3bdfSopenharmony_ci
263f08c3bdfSopenharmony_ci[source,conf]
264f08c3bdfSopenharmony_ci--------------------------------------------------------------------------------
265f08c3bdfSopenharmony_ci[user]
266f08c3bdfSopenharmony_ci	name = Sarah Jane
267f08c3bdfSopenharmony_ci	email = sjane@e-mail.address
268f08c3bdfSopenharmony_ci[core]
269f08c3bdfSopenharmony_ci	editor = emacs
270f08c3bdfSopenharmony_ci[sendemail]
271f08c3bdfSopenharmony_ci	smtpServer = smtp.server.address
272f08c3bdfSopenharmony_ci--------------------------------------------------------------------------------
273f08c3bdfSopenharmony_ci
274f08c3bdfSopenharmony_ciObviously you need to at least change your name and e-mail. The SMTP server is
275f08c3bdfSopenharmony_ciuseful for +git send-email+, which we will discuss later. The editor value is
276f08c3bdfSopenharmony_ciused for things like writing commits (without the +-m+ option).
277f08c3bdfSopenharmony_ci
278f08c3bdfSopenharmony_ci[source,shell]
279f08c3bdfSopenharmony_ci--------------------------------------------------------------------------------
280f08c3bdfSopenharmony_ci$ git add -v :/testcases/kernel/syscalls/statx :/runtest/syscalls
281f08c3bdfSopenharmony_ci$ git commit -m "statx01: Add new test for statx syscall"
282f08c3bdfSopenharmony_ci--------------------------------------------------------------------------------
283f08c3bdfSopenharmony_ci
284f08c3bdfSopenharmony_ciThis should add all the new files in the +statx+ directory and the +runtest+
285f08c3bdfSopenharmony_cifile. It is good practice to commit early and often. Later on we will do a
286f08c3bdfSopenharmony_ciGit-rebase, which allows us to clean up the commit history. So don't worry
287f08c3bdfSopenharmony_ciabout how presentable your commit log is for now. Also don't hesitate to
288f08c3bdfSopenharmony_cicreate a new branch when doing the exercises or experimenting. This will allow
289f08c3bdfSopenharmony_ciyou to diverge from the tutorial and then easily come back again.
290f08c3bdfSopenharmony_ci
291f08c3bdfSopenharmony_ciI can't emphasize enough that Git makes things easy through branching and that
292f08c3bdfSopenharmony_cithings quickly get complicated if you don't do it. However if you do get into
293f08c3bdfSopenharmony_cia mess, Git-reflog and Git-reset, will usually get you out of it. If you also
294f08c3bdfSopenharmony_cimess that up then it may be possible to cherry pick 'dangling' commits out of
295f08c3bdfSopenharmony_cithe database into a branch.
296f08c3bdfSopenharmony_ci
297f08c3bdfSopenharmony_ci3.1 Report TCONF instead of TPASS
298f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
299f08c3bdfSopenharmony_ci
300f08c3bdfSopenharmony_ciMaybe the test should report "TCONF: Not implemented" instead or perhaps
301f08c3bdfSopenharmony_ci+TBROK+. Try changing it do so (see +doc/test-writing-guidelines.txt+ or
302f08c3bdfSopenharmony_cihttps://github.com/linux-test-project/ltp/wiki/Test-Writing-Guidelines[the
303f08c3bdfSopenharmony_ciWiki]).
304f08c3bdfSopenharmony_ci
305f08c3bdfSopenharmony_ci3.2 Check Git ignores the executable
306f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
307f08c3bdfSopenharmony_ci
308f08c3bdfSopenharmony_ciIs your +.gitignore+ correct?
309f08c3bdfSopenharmony_ci
310f08c3bdfSopenharmony_ci3.3 Run make check
311f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~~~~~
312f08c3bdfSopenharmony_ci
313f08c3bdfSopenharmony_ciCheck coding style with `make check`
314f08c3bdfSopenharmony_ci (more in https://github.com/linux-test-project/ltp/wiki/Test-Writing-Guidelines#21-c-coding-style[C coding style])
315f08c3bdfSopenharmony_ci
316f08c3bdfSopenharmony_ci3.4 Install the LTP and run the test with runtest
317f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
318f08c3bdfSopenharmony_ci
319f08c3bdfSopenharmony_ciRun +statx01+ on its own; similar to the +madvise+ tests in the +README.md+.
320f08c3bdfSopenharmony_ci
321f08c3bdfSopenharmony_ci4. Call the system call
322f08c3bdfSopenharmony_ci-----------------------
323f08c3bdfSopenharmony_ci
324f08c3bdfSopenharmony_ciAt the time of writing +statx+ has no +glibc+ wrapper. It is also fairly common
325f08c3bdfSopenharmony_cifor a distribution's C library version to be older than its kernel or it may use a
326f08c3bdfSopenharmony_cicut down C library in comparison to the GNU one. So we must call +statx()+
327f08c3bdfSopenharmony_ciusing the general +syscall()+ interface.
328f08c3bdfSopenharmony_ci
329f08c3bdfSopenharmony_ciThe LTP contains a library for dealing with the +syscall+ interface, which is
330f08c3bdfSopenharmony_cilocated in +include/lapi+. System call numbers are listed against the relevant
331f08c3bdfSopenharmony_cicall in the +*.in+ files (e.g. +x86_64.in+) which are used to generate
332f08c3bdfSopenharmony_ci+syscalls.h+, which is the header you should include. On rare occasions you
333f08c3bdfSopenharmony_cimay find the system call number is missing from the +*.in+ files and will need
334f08c3bdfSopenharmony_cito add it (see +include/lapi/syscalls/strip_syscall.awk+).
335f08c3bdfSopenharmony_ci
336f08c3bdfSopenharmony_ciSystem call numbers vary between architectures, hence there are multiple
337f08c3bdfSopenharmony_ci+*.in+ files for each architecture. You can find the various values for the
338f08c3bdfSopenharmony_ci+statx+ system call across a number of +unistd.h+ files in the Linux kernel.
339f08c3bdfSopenharmony_ci
340f08c3bdfSopenharmony_ciNote that we don't use the system-call-identifier value available in
341f08c3bdfSopenharmony_ci+/usr/include/linux/uinstd.h+ because the kernel might be much newer than the
342f08c3bdfSopenharmony_ciuser land development packages.
343f08c3bdfSopenharmony_ci
344f08c3bdfSopenharmony_ciFor +statx+ we had to add +statx 332+ to +include/lapi/syscalls/x86_64.in+,
345f08c3bdfSopenharmony_ci+statx 383+ to +include/lapi/syscalls/powerpc.in+, etc.  Now lets look at
346f08c3bdfSopenharmony_cithe code, which I will explain in more detail further down.
347f08c3bdfSopenharmony_ci
348f08c3bdfSopenharmony_ci[source,c]
349f08c3bdfSopenharmony_ci--------------------------------------------------------------------------------
350f08c3bdfSopenharmony_ci/*
351f08c3bdfSopenharmony_ci * Test statx
352f08c3bdfSopenharmony_ci *
353f08c3bdfSopenharmony_ci * Check if statx exists and what error code it returns when we give it dodgy
354f08c3bdfSopenharmony_ci * data.
355f08c3bdfSopenharmony_ci */
356f08c3bdfSopenharmony_ci
357f08c3bdfSopenharmony_ci#include <stdint.h>
358f08c3bdfSopenharmony_ci#include "tst_test.h"
359f08c3bdfSopenharmony_ci#include "lapi/syscalls.h"
360f08c3bdfSopenharmony_ci
361f08c3bdfSopenharmony_cistruct statx_timestamp {
362f08c3bdfSopenharmony_ci	int64_t	       tv_sec;
363f08c3bdfSopenharmony_ci	uint32_t       tv_nsec;
364f08c3bdfSopenharmony_ci	int32_t	       __reserved;
365f08c3bdfSopenharmony_ci};
366f08c3bdfSopenharmony_ci
367f08c3bdfSopenharmony_cistruct statx {
368f08c3bdfSopenharmony_ci	uint32_t	stx_mask;
369f08c3bdfSopenharmony_ci	uint32_t	stx_blksize;
370f08c3bdfSopenharmony_ci	uint64_t	stx_attributes;
371f08c3bdfSopenharmony_ci	uint32_t	stx_nlink;
372f08c3bdfSopenharmony_ci	uint32_t	stx_uid;
373f08c3bdfSopenharmony_ci	uint32_t	stx_gid;
374f08c3bdfSopenharmony_ci	uint16_t	stx_mode;
375f08c3bdfSopenharmony_ci	uint16_t	__spare0[1];
376f08c3bdfSopenharmony_ci	uint64_t	stx_ino;
377f08c3bdfSopenharmony_ci	uint64_t	stx_size;
378f08c3bdfSopenharmony_ci	uint64_t	stx_blocks;
379f08c3bdfSopenharmony_ci	uint64_t	stx_attributes_mask;
380f08c3bdfSopenharmony_ci	struct statx_timestamp	stx_atime;
381f08c3bdfSopenharmony_ci	struct statx_timestamp	stx_btime;
382f08c3bdfSopenharmony_ci	struct statx_timestamp	stx_ctime;
383f08c3bdfSopenharmony_ci	struct statx_timestamp	stx_mtime;
384f08c3bdfSopenharmony_ci	uint32_t	stx_rdev_major;
385f08c3bdfSopenharmony_ci	uint32_t	stx_rdev_minor;
386f08c3bdfSopenharmony_ci	uint32_t	stx_dev_major;
387f08c3bdfSopenharmony_ci	uint32_t	stx_dev_minor;
388f08c3bdfSopenharmony_ci	uint64_t	__spare2[14];
389f08c3bdfSopenharmony_ci};
390f08c3bdfSopenharmony_ci
391f08c3bdfSopenharmony_cistatic int sys_statx(int dirfd, const char *pathname, int flags,
392f08c3bdfSopenharmony_ci		     unsigned int mask, struct statx *statxbuf)
393f08c3bdfSopenharmony_ci{
394f08c3bdfSopenharmony_ci	return tst_syscall(__NR_statx, dirfd, pathname, flags, mask, statxbuf);
395f08c3bdfSopenharmony_ci}
396f08c3bdfSopenharmony_ci
397f08c3bdfSopenharmony_ci...
398f08c3bdfSopenharmony_ci--------------------------------------------------------------------------------
399f08c3bdfSopenharmony_ci
400f08c3bdfSopenharmony_ciSo the top part of the code is now boiler plate for calling +statx+. It is
401f08c3bdfSopenharmony_cicommon for the kernel to be newer than the user land libraries and headers. So
402f08c3bdfSopenharmony_cifor new system calls like +statx+, we copy, with a few modifications, the
403f08c3bdfSopenharmony_cirelevant definitions into the LTP. This is somewhat like 'vendoring', although
404f08c3bdfSopenharmony_ciwe are usually just copying headers required for interacting with the Kernel's
405f08c3bdfSopenharmony_ciABI (Application Binary Interface), rather than internalising actual
406f08c3bdfSopenharmony_cifunctionality.
407f08c3bdfSopenharmony_ci
408f08c3bdfSopenharmony_ciSo from the top we include the +stdint.h+ library which gives us the standard
409f08c3bdfSopenharmony_ci+(u)int*_t+ type definitions. We use these in place of the Kernel type
410f08c3bdfSopenharmony_cidefinitions such as +__u64+ in +linux/types.h+. We then have a couple of
411f08c3bdfSopenharmony_cistructure definitions which form part of the +statx+ API. These were copied
412f08c3bdfSopenharmony_cifrom +include/uapi/linux/stat.h+ in the Kernel tree.
413f08c3bdfSopenharmony_ci
414f08c3bdfSopenharmony_ciAfter that, there is a wrapper function, which saves us from writing
415f08c3bdfSopenharmony_ci+tst_syscall(__NR_statx, ...+, every time we want to make a call to
416f08c3bdfSopenharmony_ci+statx+. This also provides a stub for when +statx+ is eventually integrated
417f08c3bdfSopenharmony_ciinto the LTP library and also implemented by the C library. At that point we
418f08c3bdfSopenharmony_cican switch to using the C library implementation if available or fallback to
419f08c3bdfSopenharmony_ciour own.
420f08c3bdfSopenharmony_ci
421f08c3bdfSopenharmony_ciThe advantage of using the C library implementation is that it will often be
422f08c3bdfSopenharmony_cibetter supported across multiple architectures. It will also mean we are using
423f08c3bdfSopenharmony_cithe system call in the same way most real programs would. Sometimes there are
424f08c3bdfSopenharmony_ciadvantages to bypassing the C library, but in general it should not be our
425f08c3bdfSopenharmony_cifirst choice.
426f08c3bdfSopenharmony_ci
427f08c3bdfSopenharmony_ciThe final test should do a check during configuration (i.e. when we run
428f08c3bdfSopenharmony_ci+./configure+ before building) which checks if the +statx+ system call and
429f08c3bdfSopenharmony_ciassociated structures exists. This requires writing an +m4+ file for use with
430f08c3bdfSopenharmony_ci+configure.ac+ which is processed during +make autotools+ and produces the
431f08c3bdfSopenharmony_ciconfigure script.
432f08c3bdfSopenharmony_ci
433f08c3bdfSopenharmony_ciFor the time being though we shall just ignore this. All you need to know for
434f08c3bdfSopenharmony_cinow is that this is a problem which eventually needs to be dealt with and that
435f08c3bdfSopenharmony_cithere is a system in place to handle it.
436f08c3bdfSopenharmony_ci
437f08c3bdfSopenharmony_ci[source,c]
438f08c3bdfSopenharmony_ci--------------------------------------------------------------------------------
439f08c3bdfSopenharmony_ci...
440f08c3bdfSopenharmony_ci
441f08c3bdfSopenharmony_cistatic void run(void)
442f08c3bdfSopenharmony_ci{
443f08c3bdfSopenharmony_ci	struct statx statxbuf = { 0 };
444f08c3bdfSopenharmony_ci
445f08c3bdfSopenharmony_ci	TEST(sys_statx(0, NULL, 0, 0, &statxbuf));
446f08c3bdfSopenharmony_ci
447f08c3bdfSopenharmony_ci	if (TST_RET == 0)
448f08c3bdfSopenharmony_ci		tst_res(TFAIL, "statx thinks it can stat NULL");
449f08c3bdfSopenharmony_ci	else if (TST_ERR == EFAULT)
450f08c3bdfSopenharmony_ci		tst_res(TPASS, "statx set errno to EFAULT as expected");
451f08c3bdfSopenharmony_ci	else
452f08c3bdfSopenharmony_ci		tst_res(TFAIL | TERRNO, "statx set errno to some unexpected value");
453f08c3bdfSopenharmony_ci}
454f08c3bdfSopenharmony_ci
455f08c3bdfSopenharmony_cistatic struct tst_test test = {
456f08c3bdfSopenharmony_ci	.test_all = run,
457f08c3bdfSopenharmony_ci	.min_kver = "4.11",
458f08c3bdfSopenharmony_ci};
459f08c3bdfSopenharmony_ci--------------------------------------------------------------------------------
460f08c3bdfSopenharmony_ci
461f08c3bdfSopenharmony_ciThe +TEST+ macro sets +TST_RET+ to the return value of +tst_statx()+ and
462f08c3bdfSopenharmony_ci+TST_ERR+ to the value of +errno+ immediately after the functions
463f08c3bdfSopenharmony_cireturn. This is mainly just for convenience, although it potentially could
464f08c3bdfSopenharmony_cihave other uses.
465f08c3bdfSopenharmony_ci
466f08c3bdfSopenharmony_ciWe check whether the return value indicates success and if it doesn't also
467f08c3bdfSopenharmony_cicheck the value of +errno+. The last call to +tst_res+ includes +TERRNO+,
468f08c3bdfSopenharmony_ciwhich will print the current error number and associated description in
469f08c3bdfSopenharmony_ciaddition to the message we have provided. Note that it uses the current value
470f08c3bdfSopenharmony_ciof +errno+ not +TST_ERR+.
471f08c3bdfSopenharmony_ci
472f08c3bdfSopenharmony_ciWhat we should have done in the example above is use +TTERRNO+ which takes the
473f08c3bdfSopenharmony_civalue of +TST_ERR+.
474f08c3bdfSopenharmony_ci
475f08c3bdfSopenharmony_ciIf we try to run the test on a kernel where +statx+ does not exist, then
476f08c3bdfSopenharmony_ci+tst_syscall+ will cause it to fail gracefully with +TCONF+. Where +TCONF+
477f08c3bdfSopenharmony_ciindicates the test is not applicable to our configuration.
478f08c3bdfSopenharmony_ci
479f08c3bdfSopenharmony_ciThe function +tst_syscall+ calls +tst_brk(TCONF,...)+ on failure. +tst_brk+
480f08c3bdfSopenharmony_cicauses the test to exit immediately, which prevents any further test code from
481f08c3bdfSopenharmony_cibeing run.
482f08c3bdfSopenharmony_ci
483f08c3bdfSopenharmony_ci4.1 What are the differences between tst_brk and tst_res?
484f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
485f08c3bdfSopenharmony_ci
486f08c3bdfSopenharmony_ciSee +include/tst_test.h+ and the
487f08c3bdfSopenharmony_cihttps://github.com/linux-test-project/ltp/wiki/Test-Writing-Guidelines[test
488f08c3bdfSopenharmony_ciwriting guide]. Also what do they have in common?
489f08c3bdfSopenharmony_ci
490f08c3bdfSopenharmony_ci4.2 What happens if you call tst_res(TINFO, ...) after sys_statx?
491f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
492f08c3bdfSopenharmony_ci
493f08c3bdfSopenharmony_ciDoes the test still function correctly?
494f08c3bdfSopenharmony_ci
495f08c3bdfSopenharmony_ci4.3 Extend the test to handle other basic error conditions.
496f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
497f08c3bdfSopenharmony_ci
498f08c3bdfSopenharmony_ciFor example, see if you can trigger +ENOENT+ instead. You shouldn't
499f08c3bdfSopenharmony_cihave to create any files, which is discussed in the next section.
500f08c3bdfSopenharmony_ci
501f08c3bdfSopenharmony_ci5. Setup, Cleanup and files
502f08c3bdfSopenharmony_ci---------------------------
503f08c3bdfSopenharmony_ci
504f08c3bdfSopenharmony_ciSome tests require resources to be allocated, or system settings to be
505f08c3bdfSopenharmony_cichanged, before the test begins. This 'setup' only has to be done once at the
506f08c3bdfSopenharmony_cibeginning and at the end of the test needs to be removed or reverted. The
507f08c3bdfSopenharmony_ci'cleanup' also has to be done regardless of whether the test breaks.
508f08c3bdfSopenharmony_ci
509f08c3bdfSopenharmony_ciFortunately, like most test libraries, we have setup and cleanup (teardown)
510f08c3bdfSopenharmony_cicallbacks. +setup+ is called once before +run+ and +cleanup+ is called once
511f08c3bdfSopenharmony_ciafterwards. Note that +run+ itself can be called multiple times by the test
512f08c3bdfSopenharmony_ciharness, but that +setup+ and +cleanup+ are only called once.
513f08c3bdfSopenharmony_ci
514f08c3bdfSopenharmony_ciIf either your code, a +SAFE_*+ macro or a library function such as
515f08c3bdfSopenharmony_ci+tst_syscall+ call +tst_brk+, then +run+ will exit immediately and the
516f08c3bdfSopenharmony_ci+cleanup+ function is then called. Once 'cleanup' is completed, the test
517f08c3bdfSopenharmony_ciexecutable will then exit altogether abandoning any remaining iterations of
518f08c3bdfSopenharmony_ci+run+.
519f08c3bdfSopenharmony_ci
520f08c3bdfSopenharmony_ciFor +statx+ we would like to create some files or file like objects which we
521f08c3bdfSopenharmony_cihave control over. Deciding where to create the files is easy, we just create
522f08c3bdfSopenharmony_ciit in the current working directory and let the LTP test harness handle where
523f08c3bdfSopenharmony_cithat should be by setting +.needs_tmpdir = 1+.
524f08c3bdfSopenharmony_ci
525f08c3bdfSopenharmony_ci[source,c]
526f08c3bdfSopenharmony_ci--------------------------------------------------------------------------------
527f08c3bdfSopenharmony_ci/*
528f08c3bdfSopenharmony_ci * Test statx
529f08c3bdfSopenharmony_ci *
530f08c3bdfSopenharmony_ci * Check if statx exists and what error code it returns when we give it dodgy
531f08c3bdfSopenharmony_ci * data. Then stat a file and check it returns success.
532f08c3bdfSopenharmony_ci */
533f08c3bdfSopenharmony_ci
534f08c3bdfSopenharmony_ci#include <stdint.h>
535f08c3bdfSopenharmony_ci#include "tst_test.h"
536f08c3bdfSopenharmony_ci#include "lapi/syscalls.h"
537f08c3bdfSopenharmony_ci#include "lapi/fcntl.h"
538f08c3bdfSopenharmony_ci
539f08c3bdfSopenharmony_ci#define FNAME "file_to_stat"
540f08c3bdfSopenharmony_ci#define STATX_BASIC_STATS 0x000007ffU
541f08c3bdfSopenharmony_ci
542f08c3bdfSopenharmony_ci/*************** statx structure and wrapper goes here ! ***************/
543f08c3bdfSopenharmony_ci
544f08c3bdfSopenharmony_ci...
545f08c3bdfSopenharmony_ci--------------------------------------------------------------------------------
546f08c3bdfSopenharmony_ci
547f08c3bdfSopenharmony_ciWe have added an extra include +lapi/fcntl.h+ which wraps the system header by
548f08c3bdfSopenharmony_cithe same name (+#include <fcntl.h>+). This header ensures we have definitions
549f08c3bdfSopenharmony_cifor recently added macros such as +AT_FDCWD+ by providing fall backs if the
550f08c3bdfSopenharmony_cisystem header does not have them. The +lapi+ directory contains a number of
551f08c3bdfSopenharmony_ciheaders like this.
552f08c3bdfSopenharmony_ci
553f08c3bdfSopenharmony_ciAt some point we may wish to add +lapi/stat.h+ to provide a fall back for
554f08c3bdfSopenharmony_cimacros such as +STATX_BASIC_STATS+. However for the time being we have just
555f08c3bdfSopenharmony_cidefined it in the test.
556f08c3bdfSopenharmony_ci
557f08c3bdfSopenharmony_ci[source,c]
558f08c3bdfSopenharmony_ci--------------------------------------------------------------------------------
559f08c3bdfSopenharmony_ci...
560f08c3bdfSopenharmony_ci
561f08c3bdfSopenharmony_cistatic void setup(void)
562f08c3bdfSopenharmony_ci{
563f08c3bdfSopenharmony_ci	SAFE_TOUCH(FNAME, 0777, NULL);
564f08c3bdfSopenharmony_ci}
565f08c3bdfSopenharmony_ci
566f08c3bdfSopenharmony_cistatic void run(void)
567f08c3bdfSopenharmony_ci{
568f08c3bdfSopenharmony_ci	struct statx statxbuf = { 0 };
569f08c3bdfSopenharmony_ci
570f08c3bdfSopenharmony_ci	TEST(sys_statx(0, NULL, 0, 0, &statxbuf));
571f08c3bdfSopenharmony_ci	if (TST_RET == 0)
572f08c3bdfSopenharmony_ci		tst_res(TFAIL, "statx thinks it can stat NULL");
573f08c3bdfSopenharmony_ci	else if (TST_ERR == EFAULT)
574f08c3bdfSopenharmony_ci		tst_res(TPASS, "statx set errno to EFAULT as expected");
575f08c3bdfSopenharmony_ci	else
576f08c3bdfSopenharmony_ci		tst_res(TFAIL | TERRNO, "statx set errno to some unexpected value");
577f08c3bdfSopenharmony_ci
578f08c3bdfSopenharmony_ci	TEST(sys_statx(AT_FDCWD, FNAME, 0, STATX_BASIC_STATS, &statxbuf));
579f08c3bdfSopenharmony_ci	if (TST_RET == 0)
580f08c3bdfSopenharmony_ci		tst_res(TPASS, "It returned zero so it must have worked!");
581f08c3bdfSopenharmony_ci	else
582f08c3bdfSopenharmony_ci		tst_res(TFAIL | TERRNO, "statx can not stat a basic file");
583f08c3bdfSopenharmony_ci}
584f08c3bdfSopenharmony_ci
585f08c3bdfSopenharmony_cistatic struct tst_test test = {
586f08c3bdfSopenharmony_ci	.setup = setup,
587f08c3bdfSopenharmony_ci	.test_all = run,
588f08c3bdfSopenharmony_ci	.min_kver = "4.11",
589f08c3bdfSopenharmony_ci	.needs_tmpdir = 1
590f08c3bdfSopenharmony_ci};
591f08c3bdfSopenharmony_ci--------------------------------------------------------------------------------
592f08c3bdfSopenharmony_ci
593f08c3bdfSopenharmony_ciThe +setup+ callback uses one of the LTP's +SAFE+ functions to create an empty
594f08c3bdfSopenharmony_cifile +file_to_stat+. Because we have set +.needs_tmpdir+, we can just create
595f08c3bdfSopenharmony_cithis file in the present working directory. We don't need to create a
596f08c3bdfSopenharmony_ci+cleanup+ callback yet because the LTP test harness will recursively delete
597f08c3bdfSopenharmony_cithe temporary directory and its contents.
598f08c3bdfSopenharmony_ci
599f08c3bdfSopenharmony_ciThe +run+ function can be called multiple times by the test harness, however
600f08c3bdfSopenharmony_ci+setup+ and +cleanup+ callbacks will only be ran once.
601f08c3bdfSopenharmony_ci
602f08c3bdfSopenharmony_ci[WARNING]
603f08c3bdfSopenharmony_ciBy this point you may have begun to explore the LTP library headers or older
604f08c3bdfSopenharmony_citests. In which case you will have come across functions from the old API such
605f08c3bdfSopenharmony_cias +tst_brkm+. The old API is being phased out, so you should not use these
606f08c3bdfSopenharmony_cifunctions.
607f08c3bdfSopenharmony_ci
608f08c3bdfSopenharmony_ciSo far we haven't had to do any clean up. So our example doesn't answer the
609f08c3bdfSopenharmony_ciquestion "what happens if part of the clean up fails?". To answer this we are
610f08c3bdfSopenharmony_cigoing to modify the test to ask the (highly contrived) question "What happens
611f08c3bdfSopenharmony_ciif I create and open a file, then create a hard-link to it, then call open
612f08c3bdfSopenharmony_ciagain on the hard-link, then 'stat' the file".
613f08c3bdfSopenharmony_ci
614f08c3bdfSopenharmony_ci[source,c]
615f08c3bdfSopenharmony_ci--------------------------------------------------------------------------------
616f08c3bdfSopenharmony_ci#define LNAME "file_to_stat_link"
617f08c3bdfSopenharmony_ci
618f08c3bdfSopenharmony_ci...
619f08c3bdfSopenharmony_ci
620f08c3bdfSopenharmony_cistatic void setup(void)
621f08c3bdfSopenharmony_ci{
622f08c3bdfSopenharmony_ci	fd = SAFE_OPEN(FNAME, O_CREAT, 0777);
623f08c3bdfSopenharmony_ci	SAFE_LINK(FNAME, LNAME);
624f08c3bdfSopenharmony_ci	lfd = SAFE_OPEN(LNAME, 0);
625f08c3bdfSopenharmony_ci}
626f08c3bdfSopenharmony_ci
627f08c3bdfSopenharmony_cistatic void cleanup(void)
628f08c3bdfSopenharmony_ci{
629f08c3bdfSopenharmony_ci	if (lfd != 0)
630f08c3bdfSopenharmony_ci		SAFE_CLOSE(lfd);
631f08c3bdfSopenharmony_ci
632f08c3bdfSopenharmony_ci	if (fd != 0)
633f08c3bdfSopenharmony_ci		SAFE_CLOSE(fd);
634f08c3bdfSopenharmony_ci}
635f08c3bdfSopenharmony_ci
636f08c3bdfSopenharmony_cistatic void run(void)
637f08c3bdfSopenharmony_ci{
638f08c3bdfSopenharmony_ci        ...
639f08c3bdfSopenharmony_ci
640f08c3bdfSopenharmony_ci	TEST(sys_statx(AT_FDCWD, LNAME, 0, STATX_BASIC_STATS, &statxbuf));
641f08c3bdfSopenharmony_ci	if (TST_RET == 0)
642f08c3bdfSopenharmony_ci		tst_res(TPASS, "It returned zero so it must have worked!");
643f08c3bdfSopenharmony_ci	else
644f08c3bdfSopenharmony_ci		tst_res(TFAIL | TERRNO, "statx can not stat a basic file");
645f08c3bdfSopenharmony_ci}
646f08c3bdfSopenharmony_ci
647f08c3bdfSopenharmony_cistatic struct tst_test test = {
648f08c3bdfSopenharmony_ci	.setup = setup,
649f08c3bdfSopenharmony_ci	.cleanup = cleanup,
650f08c3bdfSopenharmony_ci	.test_all = run,
651f08c3bdfSopenharmony_ci	.tcnt = 2,
652f08c3bdfSopenharmony_ci	.min_kver = "4.11",
653f08c3bdfSopenharmony_ci	.needs_tmpdir = 1
654f08c3bdfSopenharmony_ci};
655f08c3bdfSopenharmony_ci--------------------------------------------------------------------------------
656f08c3bdfSopenharmony_ci
657f08c3bdfSopenharmony_ciBecause we are now opening a file, we need a +cleanup+ function to close the
658f08c3bdfSopenharmony_cifile descriptors. We have to manually close the files to ensure the temporary
659f08c3bdfSopenharmony_cidirectory is deleted by the test harness (see the
660f08c3bdfSopenharmony_cihttps://github.com/linux-test-project/ltp/wiki/Test-Writing-Guidelines[test
661f08c3bdfSopenharmony_ciwriting guidelines] for details).
662f08c3bdfSopenharmony_ci
663f08c3bdfSopenharmony_ciAs a matter of good practice, the file descriptors are closed in reverse
664f08c3bdfSopenharmony_ciorder. In some circumstances the order in which clean up is performed is
665f08c3bdfSopenharmony_cisignificant. In that case resources created towards the end of 'setup' are
666f08c3bdfSopenharmony_cidependent on ones near the beginning. So during 'cleanup' we remove the
667f08c3bdfSopenharmony_cidependants before their dependencies.
668f08c3bdfSopenharmony_ci
669f08c3bdfSopenharmony_ciIf, for some reason, the file descriptor +lfd+ became invalid during the test,
670f08c3bdfSopenharmony_cibut +fd+ was still open, we do not want +SAFE_CLOSE(lfd)+ to cause the
671f08c3bdfSopenharmony_ci+cleanup+ function to exit prematurely. If it did, then +fd+ would remain open
672f08c3bdfSopenharmony_ciwhich would cause problems on some file systems.
673f08c3bdfSopenharmony_ci
674f08c3bdfSopenharmony_ciNor do we want to call +cleanup+ recursively. So during 'cleanup' +tst_brk+,
675f08c3bdfSopenharmony_ciand consequently the +SAFE+ functions, do not cause the test to exit with
676f08c3bdfSopenharmony_ci+TBROK+. Instead they just print an error message with +TWARN+.
677f08c3bdfSopenharmony_ci
678f08c3bdfSopenharmony_ciIt is not entirely necessary to check if the file descriptors have a none zero
679f08c3bdfSopenharmony_civalue before attempting to close them. However it avoids a bunch of spurious
680f08c3bdfSopenharmony_ciwarning messages if we fail to open +file_to_stat+. Test case failures can be
681f08c3bdfSopenharmony_cidifficult to interpret at the best of times, so avoid filling the log with
682f08c3bdfSopenharmony_cinoise.
683f08c3bdfSopenharmony_ci
684f08c3bdfSopenharmony_ci5.1 Check statx returns the correct number of hard links
685f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
686f08c3bdfSopenharmony_ci
687f08c3bdfSopenharmony_ciThe field +statx.stx_nlink+ should be equal to 2, right?
688f08c3bdfSopenharmony_ci
689f08c3bdfSopenharmony_ci5.2 Git-branch
690f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~
691f08c3bdfSopenharmony_ci
692f08c3bdfSopenharmony_ciWe are about to make some organisational changes to the test, so now would be
693f08c3bdfSopenharmony_cia good time to branch. Then we can switch between the old and new versions, to
694f08c3bdfSopenharmony_cicheck the behavior has not been changed by accident.
695f08c3bdfSopenharmony_ci
696f08c3bdfSopenharmony_ci6. Split the test
697f08c3bdfSopenharmony_ci-----------------
698f08c3bdfSopenharmony_ci
699f08c3bdfSopenharmony_ciIn our current test, we have essentially rolled two different test cases into
700f08c3bdfSopenharmony_cione. Firstly we check if an error is returned when bad arguments are provided
701f08c3bdfSopenharmony_ciand secondly we check what happens when we stat an actual file. Quite often it
702f08c3bdfSopenharmony_cimakes sense to call +tst_res+ multiple times in a single test case because we
703f08c3bdfSopenharmony_ciare checking different properties of the same result, but here we are clearly
704f08c3bdfSopenharmony_citesting two different scenarios.
705f08c3bdfSopenharmony_ci
706f08c3bdfSopenharmony_ciSo we should split the test in two. One obvious way to do this is to create
707f08c3bdfSopenharmony_ci+statx02.c+, but that seems like overkill in order to separate two simple test
708f08c3bdfSopenharmony_cicases. So, for now at least, we are going to do it a different way.
709f08c3bdfSopenharmony_ci
710f08c3bdfSopenharmony_ci[source,c]
711f08c3bdfSopenharmony_ci--------------------------------------------------------------------------------
712f08c3bdfSopenharmony_ci...
713f08c3bdfSopenharmony_ci
714f08c3bdfSopenharmony_cistatic void run_stat_null(void)
715f08c3bdfSopenharmony_ci{
716f08c3bdfSopenharmony_ci	struct statx statxbuf = { 0 };
717f08c3bdfSopenharmony_ci
718f08c3bdfSopenharmony_ci	TEST(sys_statx(0, NULL, 0, 0, &statxbuf));
719f08c3bdfSopenharmony_ci	if (TST_RET == 0)
720f08c3bdfSopenharmony_ci		tst_res(TFAIL, "statx thinks it can stat NULL");
721f08c3bdfSopenharmony_ci	else if (TST_ERR == EFAULT)
722f08c3bdfSopenharmony_ci		tst_res(TPASS, "statx set errno to EFAULT as expected");
723f08c3bdfSopenharmony_ci	else
724f08c3bdfSopenharmony_ci		tst_res(TFAIL | TERRNO, "statx set errno to some unexpected value");
725f08c3bdfSopenharmony_ci}
726f08c3bdfSopenharmony_ci
727f08c3bdfSopenharmony_cistatic void run_stat_symlink(void)
728f08c3bdfSopenharmony_ci{
729f08c3bdfSopenharmony_ci	struct statx statxbuf = { 0 };
730f08c3bdfSopenharmony_ci
731f08c3bdfSopenharmony_ci	TEST(sys_statx(AT_FDCWD, LNAME, 0, STATX_BASIC_STATS, &statxbuf));
732f08c3bdfSopenharmony_ci	if (TST_RET == 0)
733f08c3bdfSopenharmony_ci		tst_res(TPASS, "It returned zero so it must have worked!");
734f08c3bdfSopenharmony_ci	else
735f08c3bdfSopenharmony_ci		tst_res(TFAIL | TERRNO, "statx can not stat a basic file");
736f08c3bdfSopenharmony_ci}
737f08c3bdfSopenharmony_ci
738f08c3bdfSopenharmony_cistatic void run(unsigned int i)
739f08c3bdfSopenharmony_ci{
740f08c3bdfSopenharmony_ci	switch(i) {
741f08c3bdfSopenharmony_ci	case 0: run_stat_null();
742f08c3bdfSopenharmony_ci	case 1: run_stat_symlink();
743f08c3bdfSopenharmony_ci	}
744f08c3bdfSopenharmony_ci}
745f08c3bdfSopenharmony_ci
746f08c3bdfSopenharmony_cistatic struct tst_test test = {
747f08c3bdfSopenharmony_ci	.setup = setup,
748f08c3bdfSopenharmony_ci	.cleanup = cleanup,
749f08c3bdfSopenharmony_ci	.test = run,
750f08c3bdfSopenharmony_ci	.tcnt = 2,
751f08c3bdfSopenharmony_ci	.min_kver = "4.11",
752f08c3bdfSopenharmony_ci	.needs_tmpdir = 1
753f08c3bdfSopenharmony_ci};
754f08c3bdfSopenharmony_ci--------------------------------------------------------------------------------
755f08c3bdfSopenharmony_ci
756f08c3bdfSopenharmony_ciSo we have used an alternative form of the +test+ or +run+ callback which
757f08c3bdfSopenharmony_ciaccepts an index. Some tests use this index with an array of parameters and
758f08c3bdfSopenharmony_ciexpected return values. Others do something similar to the above. The index
759f08c3bdfSopenharmony_cican be used how you want so long as each iteration calls +tst_res+ in a
760f08c3bdfSopenharmony_cimeaningful way.
761f08c3bdfSopenharmony_ci
762f08c3bdfSopenharmony_ciIf an iteration fails to return a result (i.e. call +tst_res+ with a value
763f08c3bdfSopenharmony_ciother than +TINFO+) then the test harness will report +TBROK+ and print the
764f08c3bdfSopenharmony_ciiteration which failed. This prevents a scenario in your test from silently
765f08c3bdfSopenharmony_cifailing due to some faulty logic.
766f08c3bdfSopenharmony_ci
767f08c3bdfSopenharmony_ci6.1 What is wrong with the switch statement?
768f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
769f08c3bdfSopenharmony_ci
770f08c3bdfSopenharmony_ciWere you paying attention? Also see the output of +make check+.
771f08c3bdfSopenharmony_ci
772f08c3bdfSopenharmony_ci6.2 Test a feature unique to statx
773f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
774f08c3bdfSopenharmony_ci
775f08c3bdfSopenharmony_ciSo far we have not tested anything which is unique to +statx+. So, for
776f08c3bdfSopenharmony_ciexample, you could check stx_btime is correct (possibly only to within a
777f08c3bdfSopenharmony_cimargin of error) and that it differs from +stx_mtime+ after writing to the
778f08c3bdfSopenharmony_cifile.
779f08c3bdfSopenharmony_ci
780f08c3bdfSopenharmony_ciAlternatively you could check that +stx_dev_major+ and +stx_dev_minor+ are set
781f08c3bdfSopenharmony_cicorrectly. Note that the LTP has helper functions for creating devices and
782f08c3bdfSopenharmony_cifile systems (see
783f08c3bdfSopenharmony_cihttps://github.com/linux-test-project/ltp/wiki/Test-Writing-Guidelines#2214-testing-with-a-block-device[section
784f08c3bdfSopenharmony_ci2.2.14] of the Test Writing Guidelines).
785f08c3bdfSopenharmony_ci
786f08c3bdfSopenharmony_ciThis could be quite a challenging exercise. You may wish to tackle an
787f08c3bdfSopenharmony_cialtogether different test scenario instead. If you get stuck just move onto
788f08c3bdfSopenharmony_cithe next section and come back later.
789f08c3bdfSopenharmony_ci
790f08c3bdfSopenharmony_ci7. Submitting the test for review
791f08c3bdfSopenharmony_ci---------------------------------
792f08c3bdfSopenharmony_ci
793f08c3bdfSopenharmony_ciIgnoring the fact we should probably create +lapi/stat.h+ along with a bunch
794f08c3bdfSopenharmony_ciof fallback logic in the build system. We can now get our test ready for
795f08c3bdfSopenharmony_cisubmission.
796f08c3bdfSopenharmony_ci
797f08c3bdfSopenharmony_ciThe first thing you need to do before considering submitting your test is run
798f08c3bdfSopenharmony_ci+make check-statx01+ or + make check+ in the test's directory. Again, we use
799f08c3bdfSopenharmony_cithe kernel style guidelines where possible. Next you should create a new
800f08c3bdfSopenharmony_cibranch, this will allow you to reshape your commit history without fear.
801f08c3bdfSopenharmony_ci
802f08c3bdfSopenharmony_ciAfter that we have the pleasure of doing an interactive 'rebase' to clean up
803f08c3bdfSopenharmony_ciour commit history. In its current form the test only really needs a single
804f08c3bdfSopenharmony_cicommit, but if you have been using Git correctly then you should have
805f08c3bdfSopenharmony_cimany. The main reason we want to compress it to a single commit, is to make
806f08c3bdfSopenharmony_cithe LTP's Git-log readable. It also allows us to write a coherent description
807f08c3bdfSopenharmony_ciof the work as a whole in retrospective. Although, when adding a new test, the
808f08c3bdfSopenharmony_citest description in the code will probably make the commit message redundant.
809f08c3bdfSopenharmony_ci
810f08c3bdfSopenharmony_ciAnyway, as an example, we shall look at my personal commit history from this
811f08c3bdfSopenharmony_citutorial and 'rebase' it. You should try following along with your own
812f08c3bdfSopenharmony_cirepository. First lets look at the commit history since we branched from
813f08c3bdfSopenharmony_cimaster.
814f08c3bdfSopenharmony_ci
815f08c3bdfSopenharmony_ci[source,shell]
816f08c3bdfSopenharmony_ci--------------------------------------------------------------------------------
817f08c3bdfSopenharmony_ci$ git log --oneline master..HEAD
818f08c3bdfSopenharmony_ci152d39fe7 (HEAD -> tutorial-rebase2, tutorial-rebase) tutorial: Start Submitting patch section
819f08c3bdfSopenharmony_ci70f7ce7ce statx01: Stop checkpatch from complaining
820f08c3bdfSopenharmony_cibb0332bd7 tutorial: Fix review problems
821f08c3bdfSopenharmony_ci6a87a084a statx01: Fix review problems
822f08c3bdfSopenharmony_cid784b1e85 test-writing-guidelines: Remove old API argument
823f08c3bdfSopenharmony_cic26e1be7a fixup! tutorial
824f08c3bdfSopenharmony_ci1e24a5fb5 (me/tutorial-rebase) fixup! tutorial
825f08c3bdfSopenharmony_ci568a3f7be fixup! tutorial
826f08c3bdfSopenharmony_ci09dd2c829 statx: stage 6
827f08c3bdfSopenharmony_cibfeef7902 statx: stage 5b
828f08c3bdfSopenharmony_ci76e03d714 statx: stage 5a
829f08c3bdfSopenharmony_ci98f5bc7ac statx: stage 4
830f08c3bdfSopenharmony_ci6f8c16438 statx: stage 3 (Add statx01)
831f08c3bdfSopenharmony_ci5d93b84d8 Add statx and other syscall numbers
832f08c3bdfSopenharmony_ci5ca627b78 tutorial: Add a step-by-step C test tutorial
833f08c3bdfSopenharmony_ci--------------------------------------------------------------------------------
834f08c3bdfSopenharmony_ci
835f08c3bdfSopenharmony_ciSo we have told git to show all the commits which don't exist in 'master', but
836f08c3bdfSopenharmony_ciare in +HEAD+, where +HEAD+ is the top of the current branch. The current
837f08c3bdfSopenharmony_cibranch is +tutorial-rebase2+ which I just created. I have already done one
838f08c3bdfSopenharmony_ci'rebase' and submitted a patch for review, so my original branch was just called
839f08c3bdfSopenharmony_ci+tutorial+.
840f08c3bdfSopenharmony_ci
841f08c3bdfSopenharmony_ciAs usual my commit history is starting to look like a bit of mess! There is
842f08c3bdfSopenharmony_cieven a commit in there which should not be in the this branch (Remove old API
843f08c3bdfSopenharmony_ciargument), however it can be ignored for now and 'cherry picked' into a new branch
844f08c3bdfSopenharmony_cilater.
845f08c3bdfSopenharmony_ci
846f08c3bdfSopenharmony_ciFor my patch I actually need at least two commits, one which contains the
847f08c3bdfSopenharmony_citutorial text and one which contains the test and associated files. So first
848f08c3bdfSopenharmony_ciof all I want to 'squash' (amalgamate) all the commits appended with
849f08c3bdfSopenharmony_ci+tutorial:+ into the bottom commit.
850f08c3bdfSopenharmony_ci
851f08c3bdfSopenharmony_ci[source,shell]
852f08c3bdfSopenharmony_ci--------------------------------------------------------------------------------
853f08c3bdfSopenharmony_ci$ git rebase -i 5ca627b78\^
854f08c3bdfSopenharmony_ci...
855f08c3bdfSopenharmony_ci--------------------------------------------------------------------------------
856f08c3bdfSopenharmony_ci
857f08c3bdfSopenharmony_ciThis begins an interactive 'rebase' where commit 5ca6427b78 is the earliest
858f08c3bdfSopenharmony_cicommit we want to edit. The +^+ symbol after the commit hash, specifies the
859f08c3bdfSopenharmony_cicommit before this one. The interactive 'rebase' command takes the last commit
860f08c3bdfSopenharmony_ciwe want to keep unaltered as it's argument (in other words it takes a
861f08c3bdfSopenharmony_cinon-inclusive range).
862f08c3bdfSopenharmony_ci
863f08c3bdfSopenharmony_ciUpon entering a similar command you will be presented with a text file
864f08c3bdfSopenharmony_cisimilar to the following. The file should be displayed in your text editor of
865f08c3bdfSopenharmony_cichoice, if it doesn't, then you may change the editor variable in +.gitconfig+
866f08c3bdfSopenharmony_ciwhich was shown in section 3.
867f08c3bdfSopenharmony_ci
868f08c3bdfSopenharmony_ci[source,rebase]
869f08c3bdfSopenharmony_ci--------------------------------------------------------------------------------
870f08c3bdfSopenharmony_cipick 5ca627b78 tutorial: Add a step-by-step C test tutorial
871f08c3bdfSopenharmony_cipick 5d93b84d8 Add statx and other syscall numbers
872f08c3bdfSopenharmony_cipick 6f8c16438 statx: stage 3 (Add statx01)
873f08c3bdfSopenharmony_cipick 98f5bc7ac statx: stage 4
874f08c3bdfSopenharmony_cipick 76e03d714 statx: stage 5a
875f08c3bdfSopenharmony_cipick bfeef7902 statx: stage 5b
876f08c3bdfSopenharmony_cipick 09dd2c829 statx: stage 6
877f08c3bdfSopenharmony_cipick 568a3f7be fixup! tutorial
878f08c3bdfSopenharmony_cipick 1e24a5fb5 fixup! tutorial
879f08c3bdfSopenharmony_cipick c26e1be7a fixup! tutorial
880f08c3bdfSopenharmony_cipick d784b1e85 test-writing-guidelines: Remove old API argument
881f08c3bdfSopenharmony_cipick 6a87a084a statx01: Fix review problems
882f08c3bdfSopenharmony_cipick bb0332bd7 tutorial: Fix review problems
883f08c3bdfSopenharmony_cipick 70f7ce7ce statx01: Stop checkpatch from complaining
884f08c3bdfSopenharmony_cipick 152d39fe7 tutorial: Start Submitting patch section
885f08c3bdfSopenharmony_ci--------------------------------------------------------------------------------
886f08c3bdfSopenharmony_ci
887f08c3bdfSopenharmony_ciThe last commit from Git-log is shown at the top. The left hand column
888f08c3bdfSopenharmony_cicontains the commands we want to run on each commit. +pick+ just means we
889f08c3bdfSopenharmony_cire-apply the commit as-is. We can reorder the lines to apply the commits in a
890f08c3bdfSopenharmony_cidifferent order, but we need to be careful when reordering commits to the same
891f08c3bdfSopenharmony_cifile. If your 'rebase' results in a merge conflict, then you have probably
892f08c3bdfSopenharmony_cireordered some commits which contained changes to the same piece of code.
893f08c3bdfSopenharmony_ci
894f08c3bdfSopenharmony_ciPerhaps a better name for the interactive 'rebase' command would be 'replay'. As
895f08c3bdfSopenharmony_ciwe pick a point in the commit history, undo all those commits before that
896f08c3bdfSopenharmony_cipoint, then reapply them one at a time. During the replay we can reorder the
897f08c3bdfSopenharmony_cicommits, drop, merge, split and edit them, creating a new history.
898f08c3bdfSopenharmony_ci
899f08c3bdfSopenharmony_ciThe commands I am going to use are +reword+ and +fixup+. The +reword+ command
900f08c3bdfSopenharmony_ciallows you to edit a single commit's message. The 'fixup' command 'squashes' a
901f08c3bdfSopenharmony_cicommit into the commit above/preceding it, merging the two commits into
902f08c3bdfSopenharmony_cione. The commit which has +fixup+ applied has its commit message deleted. If
903f08c3bdfSopenharmony_ciyou think a commit might have something useful in its message then you can use
904f08c3bdfSopenharmony_ci+squash+ instead.
905f08c3bdfSopenharmony_ci
906f08c3bdfSopenharmony_ci[source,rebase]
907f08c3bdfSopenharmony_ci--------------------------------------------------------------------------------
908f08c3bdfSopenharmony_cireword 5ca627b78 tutorial: Add a step-by-step C test tutorial
909f08c3bdfSopenharmony_cifixup 568a3f7be fixup! tutorial
910f08c3bdfSopenharmony_cifixup 1e24a5fb5 fixup! tutorial
911f08c3bdfSopenharmony_cifixup c26e1be7a fixup! tutorial
912f08c3bdfSopenharmony_cifixup bb0332bd7 tutorial: Fix review problems
913f08c3bdfSopenharmony_cifixup 152d39fe7 tutorial: Start Submitting patch section
914f08c3bdfSopenharmony_cifixup 276edecab tutorial: Save changes before rebase
915f08c3bdfSopenharmony_cipick 5d93b84d8 Add statx and other syscall numbers
916f08c3bdfSopenharmony_cipick 6f8c16438 statx: stage 3 (Add statx01)
917f08c3bdfSopenharmony_cipick 98f5bc7ac statx: stage 4
918f08c3bdfSopenharmony_cipick 76e03d714 statx: stage 5a
919f08c3bdfSopenharmony_cipick bfeef7902 statx: stage 5b
920f08c3bdfSopenharmony_cipick 09dd2c829 statx: stage 6
921f08c3bdfSopenharmony_cipick d784b1e85 test-writing-guidelines: Remove old API argument
922f08c3bdfSopenharmony_cipick 6a87a084a statx01: Fix review problems
923f08c3bdfSopenharmony_ci--------------------------------------------------------------------------------
924f08c3bdfSopenharmony_ci
925f08c3bdfSopenharmony_ciSo all the commits marked with +fixup+ will be re-played by Git immediately
926f08c3bdfSopenharmony_ciafter 5ca62 at the top. A new commit will then be created with the amalgamated
927f08c3bdfSopenharmony_cichanges of all the commits and 5ca62's log message. It turns out that I didn't
928f08c3bdfSopenharmony_cineed to reword anything, but there is no harm in checking. It is easy to
929f08c3bdfSopenharmony_ciforget the +Signed-off-by:+ line.
930f08c3bdfSopenharmony_ci
931f08c3bdfSopenharmony_ciI could now do the same for the commits to the +statx+ test, making the commit
932f08c3bdfSopenharmony_cimessage prefixes consistent. However I am not actually going to submit the
933f08c3bdfSopenharmony_citest (yet).
934f08c3bdfSopenharmony_ci
935f08c3bdfSopenharmony_ciI won't attempt to show you this, but if you need to do the opposite and split
936f08c3bdfSopenharmony_ciapart a commit. It is also possible using Git-rebase by marking a line with
937f08c3bdfSopenharmony_ci+edit+. This will pause Git just after replaying the marked commit. You can
938f08c3bdfSopenharmony_cithen use a 'soft' Git-reset to bring the selected commit's changes back into
939f08c3bdfSopenharmony_cithe 'index' where you are then able to un-stage some parts before
940f08c3bdfSopenharmony_cire-committing.
941f08c3bdfSopenharmony_ci
942f08c3bdfSopenharmony_ciYou can also use +edit+ and +git commit --amend+ together to change a commit
943f08c3bdfSopenharmony_cideep in your history, but without resetting the 'index'. The 'index' contains
944f08c3bdfSopenharmony_cichanges which you have staged with +git add+, but not yet committed.
945f08c3bdfSopenharmony_ci
946f08c3bdfSopenharmony_ciSo now that the commit history has been cleaned up, we need to submit a patch
947f08c3bdfSopenharmony_cito the mailing list or make a pull request on GitHub. The mailing list is the
948f08c3bdfSopenharmony_cipreferred place to make submissions and is more difficult for most people, so
949f08c3bdfSopenharmony_ciI will only cover that method.
950f08c3bdfSopenharmony_ci
951f08c3bdfSopenharmony_ciJust before we create the patch, we need to check that our changes will still
952f08c3bdfSopenharmony_ciapply to the master branch without problems. To do this we can use another
953f08c3bdfSopenharmony_citype of 'rebase' and then try rebuilding and running the test.
954f08c3bdfSopenharmony_ci
955f08c3bdfSopenharmony_ci[source,shell]
956f08c3bdfSopenharmony_ci--------------------------------------------------------------------------------
957f08c3bdfSopenharmony_ci$ git checkout master
958f08c3bdfSopenharmony_ci$ git pull origin
959f08c3bdfSopenharmony_ci$ git checkout tutorial-rebase2
960f08c3bdfSopenharmony_ci$ git rebase master
961f08c3bdfSopenharmony_ci--------------------------------------------------------------------------------
962f08c3bdfSopenharmony_ci
963f08c3bdfSopenharmony_ciAbove, I update the master branch and then replay our changes onto it using
964f08c3bdfSopenharmony_ci+git rebase master+. You may find that after the rebase there is a merge
965f08c3bdfSopenharmony_ciconflict. This will result in something which looks like the following (taken
966f08c3bdfSopenharmony_cifrom a Makefile conflict which was caused by reordering commits in a 'rebase').
967f08c3bdfSopenharmony_ci
968f08c3bdfSopenharmony_ci[source,diff]
969f08c3bdfSopenharmony_ci--------------------------------------------------------------------------------
970f08c3bdfSopenharmony_ci<<<<<<< HEAD
971f08c3bdfSopenharmony_cicve-2016-7117:	LDFLAGS += -lpthread
972f08c3bdfSopenharmony_ci=======
973f08c3bdfSopenharmony_cicve-2014-0196:	LDFLAGS += -lpthread -lutil -lrt
974f08c3bdfSopenharmony_cicve-2016-7117:	LDFLAGS += -lpthread -lrt
975f08c3bdfSopenharmony_ci>>>>>>> 4dbfb8e79... Add -lrt
976f08c3bdfSopenharmony_ci--------------------------------------------------------------------------------
977f08c3bdfSopenharmony_ci
978f08c3bdfSopenharmony_ciThe first line tells us this is the beginning of a conflict. The third line
979f08c3bdfSopenharmony_ciseparates the two conflicting pieces of content and the last line is the end
980f08c3bdfSopenharmony_ciof the conflict. Usually, all you need to do is remove the lines you don't
981f08c3bdfSopenharmony_ciwant, stage the changes and continue the 'rebase' with +git rebase
982f08c3bdfSopenharmony_ci--continue+.
983f08c3bdfSopenharmony_ci
984f08c3bdfSopenharmony_ciIn order to create a patch e-mail we use https://git-scm.com/docs/git-format-patch[+git format-patch+],
985f08c3bdfSopenharmony_ciwe can then send that e-mail using https://git-scm.com/docs/git-send-email[+git send-email+].
986f08c3bdfSopenharmony_ciIt is also possible to import the patch (+mbox+) file into a number of e-mail programs.
987f08c3bdfSopenharmony_ci
988f08c3bdfSopenharmony_ci[source,shell]
989f08c3bdfSopenharmony_ci--------------------------------------------------------------------------------
990f08c3bdfSopenharmony_ci$ git format-patch -1 -v 2 -o output --to ltp@lists.linux.it fd3cc8596
991f08c3bdfSopenharmony_cioutput/v2-0001-tutorial-Add-a-step-by-step-C-test-tutorial.patch
992f08c3bdfSopenharmony_ci--------------------------------------------------------------------------------
993f08c3bdfSopenharmony_ci
994f08c3bdfSopenharmony_ciThe first argument +-1+ specifies we want one commit from fd3cc8596
995f08c3bdfSopenharmony_cionwards. If we wanted this commit and the one after it we could specify +-2+
996f08c3bdfSopenharmony_ciinstead.
997f08c3bdfSopenharmony_ci
998f08c3bdfSopenharmony_ciThis is my second patch submission so I have used +-v 2+, which indicates this
999f08c3bdfSopenharmony_ciis the second version of a patch set. The +-o+ option specifies the output
1000f08c3bdfSopenharmony_cidirectory (literally called +output+). The +--to+ option adds the +To:+ e-mail
1001f08c3bdfSopenharmony_ciheader, which I have set to the LTP mailing list.
1002f08c3bdfSopenharmony_ci
1003f08c3bdfSopenharmony_ciWe can then send this patch with the following command sans +--dry-run+.
1004f08c3bdfSopenharmony_ci
1005f08c3bdfSopenharmony_ci[source,shell]
1006f08c3bdfSopenharmony_ci--------------------------------------------------------------------------------
1007f08c3bdfSopenharmony_ci$ git send-email --dry-run output/v2-0001-tutorial-Add-a-step-by-step-C-test-tutorial.patch
1008f08c3bdfSopenharmony_ci--------------------------------------------------------------------------------
1009f08c3bdfSopenharmony_ci
1010f08c3bdfSopenharmony_ciGit will ask some questions (which you can ignore) and then tell you what it
1011f08c3bdfSopenharmony_ciwould do if this weren't a dry-run. In order for this to work you have to have
1012f08c3bdfSopenharmony_cia valid SMTP server set in +.gitconfig+ and also be signed up to the LTP
1013f08c3bdfSopenharmony_cimailing list under the same e-mail address you have configured in Git. You can
1014f08c3bdfSopenharmony_cisign up at https://lists.linux.it/listinfo/ltp.
1015f08c3bdfSopenharmony_ci
1016f08c3bdfSopenharmony_ci8. Doing code review
1017f08c3bdfSopenharmony_ci--------------------
1018f08c3bdfSopenharmony_ci
1019f08c3bdfSopenharmony_ciWhile waiting for your test to be reviewed, you are invited and encouraged to
1020f08c3bdfSopenharmony_cireview other contributors' code. This may seem bizarre when you are completely
1021f08c3bdfSopenharmony_cinew to the project, but there are two important ways in which you can
1022f08c3bdfSopenharmony_cicontribute here:
1023f08c3bdfSopenharmony_ci
1024f08c3bdfSopenharmony_ciA.   Point out logical errors in the code.
1025f08c3bdfSopenharmony_ciB.   Improve your own understanding
1026f08c3bdfSopenharmony_ci
1027f08c3bdfSopenharmony_ciIt doesn't matter whether you know the canonical way of writing an LTP test in
1028f08c3bdfSopenharmony_ciC. An error of logic, when properly explained, is usually indisputable. These
1029f08c3bdfSopenharmony_ciare the most important errors to find as they always result in false test
1030f08c3bdfSopenharmony_ciresults. Once someone points out such an error it is usually obvious to
1031f08c3bdfSopenharmony_cieveryone that it is a bug and needs to be fixed.
1032f08c3bdfSopenharmony_ci
1033f08c3bdfSopenharmony_ciObviously testing the patch is one way of finding errors. You can apply
1034f08c3bdfSopenharmony_cipatches using +git am+. Then it is just a case of compiling and running the
1035f08c3bdfSopenharmony_citests.
1036f08c3bdfSopenharmony_ci
1037f08c3bdfSopenharmony_ciFinally, reading and attempting to comment on other peoples patches, gives
1038f08c3bdfSopenharmony_ciyou a better understanding of the reviewers perspective. This is better for
1039f08c3bdfSopenharmony_cithe project and for you.
1040f08c3bdfSopenharmony_ci
1041f08c3bdfSopenharmony_ciStyle and organisational issues are best left to after you have found logical
1042f08c3bdfSopenharmony_cierrors.
1043f08c3bdfSopenharmony_ci
1044f08c3bdfSopenharmony_ci9. Final notes
1045f08c3bdfSopenharmony_ci--------------
1046f08c3bdfSopenharmony_ci
1047f08c3bdfSopenharmony_ciHopefully you can now grasp the structure of an LTP test and have some idea of
1048f08c3bdfSopenharmony_ciwhat is available in the LTP test library. There are a vast number of library
1049f08c3bdfSopenharmony_cifunctions available (mainly located in include and lib), some of which are
1050f08c3bdfSopenharmony_cidocumented in the test writing guidelines and many of which are not.
1051f08c3bdfSopenharmony_ci
1052f08c3bdfSopenharmony_ciWe have only scratched the surface of the immense technical complexity of
1053f08c3bdfSopenharmony_cisystems programming across multiple Kernel and C lib versions as well as
1054f08c3bdfSopenharmony_cidifferent hardware architectures. The important thing to take away from this
1055f08c3bdfSopenharmony_ciis that you have to be conscientious of what will happen on systems different
1056f08c3bdfSopenharmony_cifrom yours. The LTP has a huge and varied user base, so situations you may
1057f08c3bdfSopenharmony_cithink are unlikely can and do happen to somebody.
1058f08c3bdfSopenharmony_ci
1059f08c3bdfSopenharmony_ciOf course you don't want to spend time allowing for situations which may never
1060f08c3bdfSopenharmony_ciarise either, so you have to do your research and think about each situation
1061f08c3bdfSopenharmony_cicritically. The more systems you can test on before submitting your changes,
1062f08c3bdfSopenharmony_cithe better, although we understand not everyone has access to a lab.
1063f08c3bdfSopenharmony_ci
1064f08c3bdfSopenharmony_ciOne important topic which has not been covered by this tutorial, is
1065f08c3bdfSopenharmony_cimulti-process or multi-threaded testing. The LTP library functions work inside
1066f08c3bdfSopenharmony_cichild processes and threads, but their semantics change slightly. There are
1067f08c3bdfSopenharmony_cialso various helper functions for synchronising and forking processes. For
1068f08c3bdfSopenharmony_cimore information see
1069f08c3bdfSopenharmony_cihttps://github.com/linux-test-project/ltp/wiki/C-Test-API[C Test API],
1070f08c3bdfSopenharmony_ciin particular sections
1071f08c3bdfSopenharmony_cihttps://github.com/linux-test-project/ltp/wiki/C-Test-API#17-fork-ing[1.7 Fork()-ing] to
1072f08c3bdfSopenharmony_cihttps://github.com/linux-test-project/ltp/wiki/C-Test-API#110-signals-and-signal-handlers[1.10 Signals and signal handlers] and
1073f08c3bdfSopenharmony_cihttps://github.com/linux-test-project/ltp/wiki/C-Test-API#114-thread-safety-in-the-ltp-library[1.14 Thread-safety in the LTP library].
1074f08c3bdfSopenharmony_ci
1075f08c3bdfSopenharmony_ciWhen it comes time to submit a test, the preferred way to do it is on the
1076f08c3bdfSopenharmony_cimailing list although you can also use GitHub. The LTP follows similar rules
1077f08c3bdfSopenharmony_cito the kernel for formatting and submitting patches. Generally speaking the
1078f08c3bdfSopenharmony_cireview cycle is easier for small patches, so try to make small changes or
1079f08c3bdfSopenharmony_ciadditions where possible.
1080