Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
hpc
gekkofs
Commits
897c31d4
Commit
897c31d4
authored
May 16, 2022
by
Ramon Nou
Committed by
Ramon Nou
Jun 21, 2022
Browse files
access and statfs coverage
SEEK CUR lseek, removed tests_example
parent
7d5d957a
Changes
11
Hide whitespace changes
Inline
Side-by-side
.gitlab-ci.yml
View file @
897c31d4
...
...
@@ -131,7 +131,7 @@ gkfs:integration:
needs
:
[
'
gkfs'
]
parallel
:
matrix
:
-
SUBTEST
:
[
data
,
directories
,
operations
,
position
,
shell
,
status
,
coverage
]
-
SUBTEST
:
[
data
,
status
,
coverage
,
directories
,
operations
,
position
,
shell
]
script
:
## run tests
...
...
tests/integration/coverage/test_error_operations.py
View file @
897c31d4
...
...
@@ -76,8 +76,52 @@ def test_open_error(gkfs_daemon, gkfs_client):
# Open unexistent file
ret
=
ret
=
gkfs_client
.
open
(
file3
,
os
.
O_WRONLY
)
ret
=
gkfs_client
.
open
(
file3
,
os
.
O_WRONLY
)
assert
ret
.
retval
==
-
1
assert
ret
.
errno
==
errno
.
ENOENT
\ No newline at end of file
def
test_access_error
(
gkfs_daemon
,
gkfs_client
):
file
=
gkfs_daemon
.
mountdir
/
"file"
file2
=
gkfs_daemon
.
mountdir
/
"file2"
ret
=
gkfs_client
.
open
(
file
,
os
.
O_CREAT
|
os
.
O_WRONLY
)
assert
ret
.
retval
==
10000
# Access, flags are not being used
ret
=
gkfs_client
.
access
(
file2
,
os
.
R_OK
)
assert
ret
.
retval
==
-
1
assert
ret
.
errno
==
errno
.
ENOENT
ret
=
gkfs_client
.
access
(
file
,
os
.
R_OK
)
assert
ret
.
retval
!=
-
1
def
test_stat_error
(
gkfs_daemon
,
gkfs_client
):
# Stat non existing file
file
=
gkfs_daemon
.
mountdir
/
"file"
ret
=
gkfs_client
.
stat
(
file
)
assert
ret
.
retval
==
-
1
assert
ret
.
errno
==
errno
.
ENOENT
# test statx on existing file
ret
=
gkfs_client
.
statx
(
0
,
file
,
0
,
0
)
assert
ret
.
retval
==
-
1
assert
ret
.
errno
==
errno
.
ENOENT
def
test_statfs
(
gkfs_daemon
,
gkfs_client
):
# Statfs check most of the outputs
ret
=
gkfs_client
.
statfs
(
gkfs_daemon
.
mountdir
)
assert
ret
.
retval
==
0
assert
ret
.
statfsbuf
.
f_type
==
0
assert
ret
.
statfsbuf
.
f_bsize
!=
0
assert
ret
.
statfsbuf
.
f_blocks
!=
0
assert
ret
.
statfsbuf
.
f_bfree
!=
0
assert
ret
.
statfsbuf
.
f_bavail
!=
0
assert
ret
.
statfsbuf
.
f_files
==
0
assert
ret
.
statfsbuf
.
f_ffree
==
0
\ No newline at end of file
tests/integration/harness/CMakeLists.txt
View file @
897c31d4
...
...
@@ -63,6 +63,8 @@ add_executable(gkfs.io
gkfs.io/symlink.cpp
gkfs.io/directory_validate.cpp
gkfs.io/unlink.cpp
gkfs.io/access.cpp
gkfs.io/statfs.cpp
)
include
(
FetchContent
)
...
...
tests/
unit/test_example_00
.cpp
→
tests/
integration/harness/gkfs.io/access
.cpp
View file @
897c31d4
...
...
@@ -26,20 +26,80 @@
SPDX-License-Identifier: GPL-3.0-or-later
*/
#include
<catch2/catch.hpp>
/* C++ includes */
#include
<CLI11/CLI11.hpp>
#include
<nlohmann/json.hpp>
#include
<memory>
#include
<fmt/format.h>
#include
<reflection.hpp>
#include
<serialize.hpp>
unsigned
int
Factorial
(
unsigned
int
number
)
{
return
number
<=
1
?
number
:
Factorial
(
number
-
1
)
*
number
;
/* C includes */
#include
<sys/types.h>
#include
<unistd.h>
using
json
=
nlohmann
::
json
;
struct
access_options
{
bool
verbose
{};
std
::
string
path
{};
int
mask
{};
REFL_DECL_STRUCT
(
access_options
,
REFL_DECL_MEMBER
(
bool
,
verbose
),
REFL_DECL_MEMBER
(
std
::
string
,
path
),
REFL_DECL_MEMBER
(
int
,
mask
));
};
struct
access_output
{
int
retval
;
int
errnum
;
REFL_DECL_STRUCT
(
access_output
,
REFL_DECL_MEMBER
(
int
,
retval
),
REFL_DECL_MEMBER
(
int
,
errnum
));
};
void
to_json
(
json
&
record
,
const
access_output
&
out
)
{
record
=
serialize
(
out
);
}
TEST_CASE
(
"Factorials are computed"
,
"[factorial]"
)
{
REQUIRE
(
Factorial
(
1
)
==
1
);
REQUIRE
(
Factorial
(
2
)
==
2
);
REQUIRE
(
Factorial
(
3
)
==
6
);
REQUIRE
(
Factorial
(
10
)
==
3628800
);
void
access_exec
(
const
access_options
&
opts
)
{
auto
rv
=
::
access
(
opts
.
path
.
c_str
(),
opts
.
mask
);
if
(
rv
==
-
1
)
{
if
(
opts
.
verbose
)
{
fmt
::
print
(
"access(path=
\"
{}
\"
, mask={}) = {}, errno: {} [{}]
\n
"
,
opts
.
path
,
opts
.
mask
,
rv
,
errno
,
::
strerror
(
errno
));
return
;
}
}
json
out
=
access_output
{
rv
,
errno
};
fmt
::
print
(
"{}
\n
"
,
out
.
dump
(
2
));
}
TEST_CASE
(
"Two and Two is Four"
,
"[2+2=4]"
)
{
REQUIRE
(
2
+
2
==
4
);
void
access_init
(
CLI
::
App
&
app
)
{
// Create the option and subcommand objects
auto
opts
=
std
::
make_shared
<
access_options
>
();
auto
*
cmd
=
app
.
add_subcommand
(
"access"
,
"Execute the access() system call"
);
// Add options to cmd, binding them to opts
cmd
->
add_flag
(
"-v,--verbose"
,
opts
->
verbose
,
"Produce human writeable output"
);
cmd
->
add_option
(
"path"
,
opts
->
path
,
"Path to file"
)
->
required
()
->
type_name
(
""
);
cmd
->
add_option
(
"mask"
,
opts
->
mask
,
"Mask to apply to the access check"
)
->
required
()
->
type_name
(
""
);
cmd
->
callback
([
opts
]()
{
access_exec
(
*
opts
);
});
}
tests/integration/harness/gkfs.io/commands.hpp
View file @
897c31d4
...
...
@@ -96,6 +96,12 @@ write_random_init(CLI::App& app);
void
truncate_init
(
CLI
::
App
&
app
);
void
access_init
(
CLI
::
App
&
app
);
void
statfs_init
(
CLI
::
App
&
app
);
// UTIL
void
file_compare_init
(
CLI
::
App
&
app
);
...
...
tests/integration/harness/gkfs.io/main.cpp
View file @
897c31d4
...
...
@@ -57,6 +57,8 @@ init_commands(CLI::App& app) {
directory_validate_init
(
app
);
write_random_init
(
app
);
truncate_init
(
app
);
access_init
(
app
);
statfs_init
(
app
);
// utils
file_compare_init
(
app
);
chdir_init
(
app
);
...
...
tests/integration/harness/gkfs.io/serialize.hpp
View file @
897c31d4
...
...
@@ -34,6 +34,7 @@
extern
"C"
{
#include
<sys/stat.h>
#include
<sys/vfs.h>
}
template
<
typename
T
>
...
...
@@ -171,6 +172,21 @@ struct adl_serializer<struct ::stat> {
}
};
// ADL specialization for struct ::statfs (not exhaustive) type
template
<
>
struct
adl_serializer
<
struct
::
statfs
>
{
static
void
to_json
(
json
&
j
,
const
struct
::
statfs
opt
)
{
j
=
json
{{
"f_type"
,
opt
.
f_type
},
{
"f_bsize"
,
opt
.
f_bsize
},
{
"f_blocks"
,
opt
.
f_blocks
},
{
"f_bfree"
,
opt
.
f_bfree
},
{
"f_bavail"
,
opt
.
f_bavail
},
{
"f_files"
,
opt
.
f_files
},
{
"f_ffree"
,
opt
.
f_ffree
}};
}
};
#ifdef STATX_TYPE
// ADL specialization for struct ::statx type
template
<
>
...
...
tests/
unit/test_example_01
.cpp
→
tests/
integration/harness/gkfs.io/statfs
.cpp
View file @
897c31d4
...
...
@@ -26,48 +26,76 @@
SPDX-License-Identifier: GPL-3.0-or-later
*/
#include
<catch2/catch.hpp>
/* C++ includes */
#include
<CLI11/CLI11.hpp>
#include
<nlohmann/json.hpp>
#include
<memory>
#include
<fmt/format.h>
#include
<commands.hpp>
#include
<reflection.hpp>
#include
<serialize.hpp>
/* C includes */
#include
<sys/types.h>
#include
<sys/vfs.h>
#include
<unistd.h>
using
json
=
nlohmann
::
json
;
struct
statfs_options
{
bool
verbose
{};
std
::
string
pathname
;
REFL_DECL_STRUCT
(
statfs_options
,
REFL_DECL_MEMBER
(
bool
,
verbose
),
REFL_DECL_MEMBER
(
std
::
string
,
pathname
));
};
struct
statfs_output
{
int
retval
;
int
errnum
;
struct
::
statfs
statfsbuf
;
REFL_DECL_STRUCT
(
statfs_output
,
REFL_DECL_MEMBER
(
int
,
retval
),
REFL_DECL_MEMBER
(
int
,
errnum
),
REFL_DECL_MEMBER
(
struct
::
statfs
,
statfsbuf
));
};
void
to_json
(
json
&
record
,
const
statfs_output
&
out
)
{
record
=
serialize
(
out
);
}
void
statfs_exec
(
const
statfs_options
&
opts
)
{
struct
::
statfs
statfsbuf
;
SCENARIO
(
"vectors can be sized and resized"
,
"[vector]"
)
{
GIVEN
(
"A vector with some items"
)
{
std
::
vector
<
int
>
v
(
5
);
REQUIRE
(
v
.
size
()
==
5
);
REQUIRE
(
v
.
capacity
()
>=
5
);
WHEN
(
"the size is increased"
)
{
v
.
resize
(
10
);
THEN
(
"the size and capacity change"
)
{
REQUIRE
(
v
.
size
()
==
10
);
REQUIRE
(
v
.
capacity
()
>=
10
);
}
}
WHEN
(
"the size is reduced"
)
{
v
.
resize
(
0
);
THEN
(
"the size changes but not capacity"
)
{
REQUIRE
(
v
.
size
()
==
0
);
REQUIRE
(
v
.
capacity
()
>=
5
);
}
}
WHEN
(
"more capacity is reserved"
)
{
v
.
reserve
(
10
);
THEN
(
"the capacity changes but not the size"
)
{
REQUIRE
(
v
.
size
()
==
5
);
REQUIRE
(
v
.
capacity
()
>=
10
);
}
}
WHEN
(
"less capacity is reserved"
)
{
v
.
reserve
(
0
);
THEN
(
"neither size nor capacity are changed"
)
{
REQUIRE
(
v
.
size
()
==
5
);
REQUIRE
(
v
.
capacity
()
>=
5
);
}
}
auto
rv
=
::
statfs
(
opts
.
pathname
.
c_str
(),
&
statfsbuf
);
if
(
opts
.
verbose
)
{
fmt
::
print
(
"statfs(pathname=
\"
{}
\"
) = {}, errno: {} [{}]
\n
"
,
opts
.
pathname
,
rv
,
errno
,
::
strerror
(
errno
));
return
;
}
json
out
=
statfs_output
{
rv
,
errno
,
statfsbuf
};
fmt
::
print
(
"{}
\n
"
,
out
.
dump
(
2
));
}
void
statfs_init
(
CLI
::
App
&
app
)
{
// Create the option and subcommand objects
auto
opts
=
std
::
make_shared
<
statfs_options
>
();
auto
*
cmd
=
app
.
add_subcommand
(
"statfs"
,
"Execute the statfs() system call"
);
// Add options to cmd, binding them to opts
cmd
->
add_flag
(
"-v,--verbose"
,
opts
->
verbose
,
"Produce human readable output"
);
cmd
->
add_option
(
"pathname"
,
opts
->
pathname
,
"Directory name"
)
->
required
()
->
type_name
(
""
);
cmd
->
callback
([
opts
]()
{
statfs_exec
(
*
opts
);
});
}
tests/integration/harness/io.py
View file @
897c31d4
...
...
@@ -83,6 +83,27 @@ class StructStatSchema(Schema):
'st_atim'
,
'st_mtim'
,
'st_ctim'
])(
**
data
)
class
StructStatfsSchema
(
Schema
):
"""Schema that deserializes a struct statfs"""
f_type
=
fields
.
Integer
(
required
=
True
)
f_bsize
=
fields
.
Integer
(
required
=
True
)
f_blocks
=
fields
.
Integer
(
required
=
True
)
f_bfree
=
fields
.
Integer
(
required
=
True
)
f_bavail
=
fields
.
Integer
(
required
=
True
)
f_files
=
fields
.
Integer
(
required
=
True
)
f_ffree
=
fields
.
Integer
(
required
=
True
)
# f_fsid = fields.Integer(required=True)
# f_namelen = fields.Integer(required=True)
# f_frsize = fields.Integer(required=True)
# f_flags = fields.Integer(required=True)
@
post_load
def
make_object
(
self
,
data
,
**
kwargs
):
return
namedtuple
(
'StructStatfs'
,
[
'f_type'
,
'f_bsize'
,
'f_blocks'
,
'f_bfree'
,
'f_bavail'
,
'f_files'
,
'f_ffree'
])(
**
data
)
class
StructStatxTimestampSchema
(
Schema
):
"""Schema that deserializes a struct timespec"""
tv_sec
=
fields
.
Integer
(
required
=
True
)
...
...
@@ -298,6 +319,16 @@ class StatxOutputSchema(Schema):
def
make_object
(
self
,
data
,
**
kwargs
):
return
namedtuple
(
'StatxReturn'
,
[
'retval'
,
'statbuf'
,
'errno'
])(
**
data
)
class
StatfsOutputSchema
(
Schema
):
"""Schema to deserialize the results of a statfs() execution"""
retval
=
fields
.
Integer
(
required
=
True
)
statfsbuf
=
fields
.
Nested
(
StructStatfsSchema
,
required
=
True
)
errno
=
Errno
(
data_key
=
'errnum'
,
required
=
True
)
@
post_load
def
make_object
(
self
,
data
,
**
kwargs
):
return
namedtuple
(
'StatfsReturn'
,
[
'retval'
,
'statfsbuf'
,
'errno'
])(
**
data
)
class
LseekOutputSchema
(
Schema
):
"""Schema to deserialize the results of an lseek() execution"""
...
...
@@ -349,6 +380,16 @@ class TruncateOutputSchema(Schema):
def
make_object
(
self
,
data
,
**
kwargs
):
return
namedtuple
(
'TruncateReturn'
,
[
'retval'
,
'errno'
])(
**
data
)
class
AccessOutputSchema
(
Schema
):
"""Schema to deserialize the results of an access() execution"""
retval
=
fields
.
Integer
(
required
=
True
)
errno
=
Errno
(
data_key
=
'errnum'
,
required
=
True
)
@
post_load
def
make_object
(
self
,
data
,
**
kwargs
):
return
namedtuple
(
'AccessReturn'
,
[
'retval'
,
'errno'
])(
**
data
)
class
ChdirOutputSchema
(
Schema
):
"""Schema to deserialize the results of an chdir() execution"""
...
...
@@ -429,6 +470,8 @@ class IOParser:
'truncate'
:
TruncateOutputSchema
(),
'directory_validate'
:
DirectoryValidateOutputSchema
(),
'unlink'
:
UnlinkOutputSchema
(),
'access'
:
AccessOutputSchema
(),
'statfs'
:
StatfsOutputSchema
(),
# UTIL
'file_compare'
:
FileCompareOutputSchema
(),
'chdir'
:
ChdirOutputSchema
(),
...
...
tests/integration/position/test_lseek.py
View file @
897c31d4
...
...
@@ -94,6 +94,9 @@ def test_lseek(gkfs_daemon, gkfs_client):
ret
=
gkfs_client
.
lseek
(
file_a
,
5
,
os
.
SEEK_SET
)
assert
ret
.
retval
==
5
ret
=
gkfs_client
.
lseek
(
file_a
,
2
,
os
.
SEEK_CUR
)
assert
ret
.
retval
==
2
# Size needs to be 0
ret
=
gkfs_client
.
stat
(
file_a
)
...
...
tests/unit/CMakeLists.txt
View file @
897c31d4
...
...
@@ -62,8 +62,6 @@ target_link_libraries(catch2_main
add_executable
(
tests
)
target_sources
(
tests
PRIVATE
${
CMAKE_CURRENT_LIST_DIR
}
/test_example_00.cpp
${
CMAKE_CURRENT_LIST_DIR
}
/test_example_01.cpp
${
CMAKE_CURRENT_LIST_DIR
}
/test_utils_arithmetic.cpp
${
CMAKE_CURRENT_LIST_DIR
}
/test_helpers.cpp
)
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment