In a filesystem, there are two kinds of paths: relative paths and absolute paths. Absolute paths always point to the same target while the target of a relative path depends on the current working directory. In Matlab, paths are called "path names" and there is a third kind of path name: the partial path name. It is defined as follows:
A partial path name is the last portion of a full path name for a location on the MATLAB search path.
(The Matlab search path is similar to the environment variable PATH and is used to locate Matlab files.) In consequence of this definition, a path name may be treated by Matlab as a partial path name even if the user is unaware of them.
I have only access to Matlab on Linux but this demonstration should also work on Windows and Mac OS. I will use the UNIX path separator
/. For this demonstration, create an empty directory, start Matlab and change (cd) into this new directory. Execute the following command:
The return value of the function
exist (exist documentation) indicates if the given path name exists and whether we are dealing with files or directories. In this post, the following return values are of interest:
- 0 if the given path does not exist,
- 2 indicates a file,
- 7 indicates a directory.
Surprisingly, this call returns 7 on my system.
exist respects the Matlab search path so although there is no subdirectory
toolbox/matlab/elmat exists on the search path (type
path). That is,
toolbox/matlab/elmat is a partial path name.
isdir documentation does not mention the Matlab search path and being used to UNIX systems, one could assume
isdir searches only the current working directory if a path name is given that is not an absolute path name. On the contrary, the command above returns logical 1 on my system meaning
isdir also accepts partial path names as parameter.
Partial path names are by definition the "last portion" of an absolute path name so all of the following calls will behave as if we had used the longer partial path name
exist('matlab/elmat') exist('elmat') isdir('matlab/elmat') isdir('elmat')
The path name given to
cd (documentation) must be an absolute or a relative path name but
elmat is a partial path name. Consequently, an exception is raised.
xUnit and Partial Paths
xUnit is a unit testing framework for Matlab which was superseded by the unit testing framework integrated in Matlab since release R2013a. Given the call
runxunit(name), xUnit needs to determine if
name is the name of a package or a directory in the current working directory and call the unit tests in it (
runxunit from xUnit 4 is called
runtests in xUnit 3). To that end,
TestSuite.m, line 199) and if this call returns logical 1, xUnit calls
cd(name) afterwards (
TestComponentInDir.m:48). Obviously, if
name is a partial but not a relative path name, then calling
cd(name) will raise an exception. Note the exception will also be raised if
name is simultaneously a valid package name. The unit testing framework shipped with Matlab does not contain this bug but both xUnit 3.1.1 and xUnit 4 have it. I reported the bug.
Edit February 24, 2016: xUnit 4 was fixed (check the bug report).
How I stumbled over the xUnit Bug
In the Matlab program I used to maintain, all unit tests can be found in the package
tests and for more than two years, I was able to run these tests by calling
runtests('tests'). Recently, the system administrator updated the Matlab search path so that
tests was suddenly a partial path name. This triggered the bug and left me baffled because there were no changes to the source code, yet the unit tests had stopped working.