Skip to content

Commit 690f956

Browse files
committed
test: Smart backend selection
1 parent 3dd1c30 commit 690f956

20 files changed

+466
-457
lines changed

+stdlib/Backend.m

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,19 +26,22 @@
2626
end
2727
end
2828

29-
if any(strlength(functionName))
29+
if strlength(functionName)
3030
self.func = self.getFunc(functionName, backendReq);
3131
end
3232
end
3333

3434

35-
function m = select(self, functionName, backendReq)
35+
function backendAvailable = select(self, functionName, backendReq, firstOnly)
3636
arguments
3737
self
3838
functionName (1,1) string
3939
backendReq (1,:) string = string.empty
40+
firstOnly (1,1) logical = false
4041
end
4142

43+
backendAvailable = string.empty;
44+
4245
if ~any(strlength(backendReq))
4346
backendReq = self.backends;
4447
end
@@ -93,13 +96,14 @@
9396
end
9497

9598
if ~isempty(which(sprintf('%s.%s.%s', self.namespace, m, functionName)))
96-
return
99+
backendAvailable(end+1) = m; %#ok<AGROW>
100+
if firstOnly
101+
return
102+
end
97103
end
98104

99105
end
100106

101-
m = string.empty;
102-
103107
end
104108

105109

@@ -113,7 +117,7 @@
113117
if isscalar(backendReq)
114118
self.backend = backendReq;
115119
else
116-
self.backend = self.select(functionName, backendReq);
120+
self.backend = self.select(functionName, backendReq, true);
117121
end
118122

119123
if isempty(self.backend)

test/TestCanonical.m

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
classdef (SharedTestFixtures={ matlab.unittest.fixtures.PathFixture("..")}, ...
2-
TestTags = {'R2019b', 'impure'}) ...
2+
TestTags = {'impure'}) ...
33
TestCanonical < matlab.unittest.TestCase
44

55
properties(TestParameter)
@@ -20,8 +20,7 @@ function test_dirs(tc)
2020
end
2121

2222

23-
methods(Test)
24-
23+
methods(Test, TestTags={'R2019b'})
2524
function test_canonical(tc, p)
2625
c = stdlib.canonical(p{1}, false);
2726
tc.verifyEqual(c, p{2})
@@ -31,8 +30,10 @@ function test_legacy_canonical(tc, p)
3130
c = stdlib.legacy.canonical(p{1}, false);
3231
tc.verifyEqual(c, p{2})
3332
end
33+
end
3434

3535

36+
methods (Test, TestTags={'R2024a'})
3637
function test_canonical_array(tc)
3738
tc.assumeFalse(stdlib.matlabOlderThan('R2024a'))
3839

@@ -42,7 +43,6 @@ function test_canonical_array(tc)
4243
exp = ["", "hi", filesep + "ok", "not-exist"];
4344
tc.verifyEqual(c, exp)
4445
end
45-
4646
end
4747

4848
end

test/TestDisk.m

Lines changed: 52 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
classdef (TestTags = {'R2019b', 'impure'}) ...
1+
classdef (SharedTestFixtures={ matlab.unittest.fixtures.PathFixture("..")}, ...
2+
TestTags = {'R2019b', 'impure'}) ...
23
TestDisk < matlab.unittest.TestCase
34

45
properties
@@ -8,24 +9,37 @@
89
properties (TestParameter)
910
Ps = {".", "", "/", getenv("SystemDrive"), "not-exist"}
1011
Po = {mfilename("fullpath") + ".m", pwd(), ".", "", "not-exist"}
11-
backend_jps = init_backend({'sys', 'java', 'python'})
12-
backend_djps = init_backend({'sys', 'dotnet', 'java', 'python'})
13-
backend_ds = init_backend({'dotnet', 'sys'})
14-
backend_ps = init_backend({'python', 'sys'})
12+
B_disk
13+
B_is_removable
14+
B_is_mount
15+
B_hard_link_count
16+
B_filesystem_type
17+
B_owner
18+
B_device
19+
end
20+
21+
methods (TestParameterDefinition, Static)
22+
function [B_disk, B_is_removable, B_is_mount, B_hard_link_count, B_filesystem_type, B_owner, B_device] = setupBackends()
23+
B_disk = init_backend("disk_available");
24+
B_is_removable = init_backend("is_removable");
25+
B_is_mount = init_backend("is_mount");
26+
B_hard_link_count = init_backend("hard_link_count");
27+
B_filesystem_type = init_backend("filesystem_type");
28+
B_owner = init_backend("get_owner");
29+
B_device = init_backend("device");
30+
end
1531
end
1632

1733
methods(TestClassSetup)
1834
function test_dirs(tc)
19-
pkg_path(tc)
20-
2135
tc.applyFixture(matlab.unittest.fixtures.WorkingFolderFixture())
2236
end
2337
end
2438

2539
methods (Test)
2640

27-
function test_disk_available(tc, Ps, backend_djps)
28-
r = stdlib.disk_available(Ps, backend_djps);
41+
function test_disk_available(tc, Ps, B_disk)
42+
r = stdlib.disk_available(Ps, B_disk);
2943

3044
tc.verifyClass(r, 'uint64')
3145

@@ -37,8 +51,8 @@ function test_disk_available(tc, Ps, backend_djps)
3751
end
3852

3953

40-
function test_disk_capacity(tc, Ps, backend_djps)
41-
r = stdlib.disk_capacity(Ps, backend_djps);
54+
function test_disk_capacity(tc, Ps, B_disk)
55+
r = stdlib.disk_capacity(Ps, B_disk);
4256

4357
tc.verifyClass(r, 'uint64')
4458

@@ -50,46 +64,42 @@ function test_disk_capacity(tc, Ps, backend_djps)
5064
end
5165

5266

53-
function test_is_removable(tc, backend_ds)
54-
y = stdlib.is_removable(pwd(), backend_ds);
67+
function test_is_removable(tc, B_is_removable)
68+
y = stdlib.is_removable(pwd(), B_is_removable);
5569
tc.verifyClass(y, 'logical')
5670
end
5771

5872

59-
function test_is_mount(tc, backend_ps)
60-
y = stdlib.is_mount(pwd(), backend_ps);
73+
function test_is_mount(tc, B_is_mount)
74+
y = stdlib.is_mount(pwd(), B_is_mount);
6175

6276
tc.verifyClass(y, 'logical')
63-
tc.verifyTrue(stdlib.is_mount("/", backend_ps))
64-
tc.verifyEmpty(stdlib.is_mount(tempname(), backend_ps))
77+
tc.verifyTrue(stdlib.is_mount("/", B_is_mount))
78+
tc.verifyEmpty(stdlib.is_mount(tempname(), B_is_mount))
6579

6680
if ispc()
6781
sd = getenv("SystemDrive");
6882
tc.assertTrue(sd == stdlib.root_name(sd), sd)
69-
tc.verifyFalse(stdlib.is_mount(sd, backend_ps), sd)
70-
tc.verifyTrue(stdlib.is_mount(sd + "/", backend_ps), sd)
71-
tc.verifyTrue(stdlib.is_mount(sd + "\", backend_ps), sd)
83+
tc.verifyFalse(stdlib.is_mount(sd, B_is_mount), sd)
84+
tc.verifyTrue(stdlib.is_mount(sd + "/", B_is_mount), sd)
85+
tc.verifyTrue(stdlib.is_mount(sd + "\", B_is_mount), sd)
7286
end
7387
end
7488

7589

76-
function test_hard_link_count(tc, backend_jps)
90+
function test_hard_link_count(tc, B_hard_link_count)
7791
P = mfilename("fullpath") + ".m";
7892

79-
r = stdlib.hard_link_count(P, backend_jps);
80-
if ispc() && backend_jps == "java"
81-
tc.verifyEmpty(r)
82-
else
83-
tc.verifyGreaterThanOrEqual(r, 1)
84-
end
93+
r = stdlib.hard_link_count(P, B_hard_link_count);
94+
tc.verifyGreaterThanOrEqual(r, 1)
8595
end
8696

8797

88-
function test_filesystem_type(tc, Ps, backend_djps)
89-
t = stdlib.filesystem_type(Ps, backend_djps);
98+
function test_filesystem_type(tc, Ps, B_filesystem_type)
99+
t = stdlib.filesystem_type(Ps, B_filesystem_type);
90100
tc.verifyClass(t, 'char')
91101

92-
if ~stdlib.exists(Ps) || (backend_djps == "python" && ~stdlib.python.has_psutil())
102+
if ~stdlib.exists(Ps)
93103
tc.verifyEmpty(t)
94104
else
95105
tc.assumeFalse(isempty(t) && tc.CI, "Some CI block viewing their filesystem type")
@@ -112,12 +122,11 @@ function test_remove_file(tc)
112122
end
113123

114124

115-
function test_device(tc, Po, backend_jps)
116-
117-
i = stdlib.device(Po, backend_jps);
125+
function test_device(tc, Po, B_device)
126+
i = stdlib.device(Po, B_device);
118127
tc.verifyClass(i, 'uint64')
119128

120-
if ispc() && backend_jps == "java" || ~stdlib.exists(Po)
129+
if ~stdlib.exists(Po)
121130
tc.verifyEmpty(i)
122131
else
123132
tc.assertNotEmpty(i)
@@ -126,12 +135,12 @@ function test_device(tc, Po, backend_jps)
126135
end
127136

128137

129-
function test_inode(tc, Po, backend_jps)
138+
function test_inode(tc, Po, B_device)
130139

131-
i = stdlib.inode(Po, backend_jps);
140+
i = stdlib.inode(Po, B_device);
132141
tc.verifyClass(i, 'uint64')
133142

134-
if ispc() && backend_jps == "java" || ~stdlib.exists(Po)
143+
if ~stdlib.exists(Po)
135144
tc.verifyEmpty(i)
136145
else
137146
tc.assertNotEmpty(i)
@@ -140,13 +149,10 @@ function test_inode(tc, Po, backend_jps)
140149
end
141150

142151

143-
function test_owner(tc, Po, backend_djps)
144-
145-
o = stdlib.get_owner(Po, backend_djps);
152+
function test_owner(tc, Po, B_owner)
153+
o = stdlib.get_owner(Po, B_owner);
146154

147-
if ~stdlib.exists(Po) || ...
148-
(backend_djps == "dotnet" && isunix()) || ...
149-
(backend_djps == "python" && ispc())
155+
if ~stdlib.exists(Po)
150156
tc.verifyEqual(o, "")
151157
else
152158
tc.verifyGreaterThan(strlength(o), 0)
@@ -155,19 +161,14 @@ function test_owner(tc, Po, backend_djps)
155161
end
156162

157163

158-
function test_owner_array(tc, backend_djps)
164+
function test_owner_array(tc, B_owner)
159165

160-
o = stdlib.get_owner([".", pwd(), "not-exist", ""], backend_djps);
166+
o = stdlib.get_owner([".", pwd(), "not-exist", ""], B_owner);
161167
L = strlength(o);
162168

163169
tc.verifyEqual(L(3:4), [0, 0])
164170

165-
if (backend_djps == "dotnet" && isunix()) || ...
166-
(backend_djps == "python" && ispc())
167-
tc.verifyEqual(L(1:2), [0, 0])
168-
else
169-
tc.verifyGreaterThan(L(1:2), 0);
170-
end
171+
tc.verifyGreaterThan(L(1:2), 0);
171172

172173
end
173174

test/TestExists.m

Lines changed: 44 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,46 @@
1-
classdef (TestTags = {'R2019b', 'impure'}) ...
1+
classdef (SharedTestFixtures={ matlab.unittest.fixtures.PathFixture("..")}, ...
2+
TestTags = {'impure'}) ...
23
TestExists < matlab.unittest.TestCase
34

45
properties(TestParameter)
5-
Ps = init_val()
6-
% on CI matlabroot can be writable!
7-
backend = init_backend({'python', 'sys'})
6+
Ps
7+
B_is_char_device
88
end
99

10+
11+
methods (TestParameterDefinition, Static)
12+
function Ps = init_val()
13+
Ps = {
14+
{pwd(), true}, ...
15+
{mfilename("fullpath") + ".m", true}, ...
16+
{fileparts(mfilename("fullpath")) + "/../Readme.md", true}, ...
17+
{tempname(), false}, ...
18+
{'', false}, ...
19+
{"", false}
20+
};
21+
if ispc()
22+
% On Windows, the root of the system drive is considered to exist
23+
systemDrive = getenv("SystemDrive");
24+
if ~isempty(systemDrive)
25+
Ps{end+1} = {systemDrive, true};
26+
end
27+
end
28+
end
29+
30+
function B_is_char_device = setupBackends()
31+
B_is_char_device = init_backend("is_char_device");
32+
end
33+
end
34+
35+
1036
methods(TestClassSetup)
1137
function test_dirs(tc)
12-
pkg_path(tc)
13-
1438
tc.applyFixture(matlab.unittest.fixtures.WorkingFolderFixture())
1539
end
1640
end
1741

18-
methods (Test)
42+
43+
methods (Test, TestTags={'R2019b'})
1944

2045
function test_exists(tc, Ps)
2146
ok = stdlib.exists(Ps{1});
@@ -34,6 +59,18 @@ function test_is_writable(tc, Ps)
3459
end
3560

3661

62+
function test_is_char_device(tc, B_is_char_device)
63+
% /dev/stdin may not be available on CI systems
64+
n = stdlib.null_file();
65+
66+
tc.verifyTrue(stdlib.is_char_device(n, B_is_char_device), n)
67+
end
68+
69+
end
70+
71+
72+
methods (Test, TestTags={'R2025a'})
73+
3774
function test_is_readable_array(tc)
3875
tc.assumeFalse(stdlib.matlabOlderThan('R2025a'))
3976
in = [".", tempname(), mfilename('fullpath') + ".m"];
@@ -53,32 +90,6 @@ function test_is_writable_array(tc)
5390
tc.verifyEqual(r, out)
5491
end
5592

56-
57-
function test_is_char_device(tc, backend)
58-
% /dev/stdin may not be available on CI systems
59-
n = stdlib.null_file();
60-
61-
tc.verifyTrue(stdlib.is_char_device(n, backend), n)
62-
end
63-
64-
end
6593
end
6694

67-
68-
function Ps = init_val()
69-
Ps = {
70-
{pwd(), true}, ...
71-
{mfilename("fullpath") + ".m", true}, ...
72-
{fileparts(mfilename("fullpath")) + "/../Readme.md", true}, ...
73-
{tempname(), false}, ...
74-
{'', false}, ...
75-
{"", false}
76-
};
77-
if ispc()
78-
% On Windows, the root of the system drive is considered to exist
79-
systemDrive = getenv("SystemDrive");
80-
if ~isempty(systemDrive)
81-
Ps{end+1} = {systemDrive, true};
82-
end
83-
end
8495
end

0 commit comments

Comments
 (0)