Add 'mrbgems/mruby-dir/' from commit '89dceefa1250fb1ae868d4cb52498e9e24293cd1'

git-subtree-dir: mrbgems/mruby-dir
git-subtree-mainline: f2d43069f0
git-subtree-split: 89dceefa12
This commit is contained in:
Yukihiro "Matz" Matsumoto
2022-12-20 18:06:36 +09:00
10 changed files with 883 additions and 0 deletions
+5
View File
@@ -0,0 +1,5 @@
gem_*
gem-*
mrb-*.a
src/*.o
/tmp
+2
View File
@@ -0,0 +1,2 @@
script:
- "ruby run_test.rb all test"
+56
View File
@@ -0,0 +1,56 @@
mruby-dir
=========
Dir class for mruby. Supported methods are:
`.chdir`
`.delete`
`.entries`
`.exist?`
`.foreach`
`.getwd`
`.mkdir`
`.open`
`#close`
`#each`
`#read`
`#rewind`
`#seek`
`#tell`
## License
Copyright (c) 2012 Internet Initiative Japan Inc.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
- On Windows platforms, you must agree on addional license too:
Copyright Kevlin Henney, 1997, 2003, 2012. All rights reserved.
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose is hereby granted without fee, provided
that this copyright and permissions notice appear in all copies and
derivatives.
This software is supplied "as is" without express or implied warranty.
But that said, if there are any problems please get in touch.
+6
View File
@@ -0,0 +1,6 @@
MRuby::Gem::Specification.new('mruby-dir') do |spec|
spec.license = 'MIT and MIT-like license'
spec.authors = [ 'Internet Initiative Japan Inc.', 'Kevlin Henney']
spec.cc.include_paths << "#{build.root}/src"
end
+64
View File
@@ -0,0 +1,64 @@
class Dir
def each(&block)
while s = self.read
block.call(s)
end
self
end
alias pos tell
alias pos= seek
def self.entries(path)
a = []
self.open(path) { |d|
while s = d.read
a << s
end
}
a
end
def self.foreach(path, &block)
if block
self.open(path).each { |f| block.call(f) }
else
self.open(path).each
end
end
def self.open(path, &block)
if block
d = self.new(path)
begin
block.call(d)
ensure
d.close
end
else
self.new(path)
end
end
def self.chdir(path, &block)
my = self # workaround for https://github.com/mruby/mruby/issues/1579
if block
wd = self.getwd
begin
self._chdir(path)
block.call(path)
ensure
my._chdir(wd)
end
else
self._chdir(path)
end
end
class << self
alias exists? exist?
alias pwd getwd
alias rmdir delete
alias unlink delete
end
end
+27
View File
@@ -0,0 +1,27 @@
#!/usr/bin/env ruby
#
# mrbgems test runner
#
gemname = File.basename(File.dirname(File.expand_path __FILE__))
if __FILE__ == $0
repository, dir = 'https://github.com/mruby/mruby.git', 'tmp/mruby'
build_args = ARGV
build_args = ['all', 'test'] if build_args.nil? or build_args.empty?
Dir.mkdir 'tmp' unless File.exist?('tmp')
unless File.exist?(dir)
system "git clone #{repository} #{dir}"
end
exit system(%Q[cd #{dir}; MRUBY_CONFIG=#{File.expand_path __FILE__} ruby minirake #{build_args.join(' ')}])
end
MRuby::Build.new do |conf|
toolchain :gcc
conf.gembox 'default'
conf.enable_test
conf.gem File.expand_path(File.dirname(__FILE__))
end
+154
View File
@@ -0,0 +1,154 @@
/*
Implementation of POSIX directory browsing functions and types for Win32.
Author: Kevlin Henney (kevlin@acm.org, kevlin@curbralan.com)
History: Created March 1997. Updated June 2003 and July 2012.
Rights: See end of file.
*/
#include <errno.h>
#include <io.h> /* _findfirst and _findnext set errno iff they return -1 */
#include <stdlib.h>
#include <string.h>
#ifdef __cplusplus
extern "C"
{
#endif
typedef ptrdiff_t handle_type; /* C99's intptr_t not sufficiently portable */
struct dirent
{
char *d_name;
};
struct DIR
{
handle_type handle; /* -1 for failed rewind */
struct _finddata_t info;
struct dirent result; /* d_name null iff first time */
char *name; /* null-terminated char string */
};
typedef struct DIR DIR;
DIR *opendir(const char *name)
{
DIR *dir = 0;
if(name && name[0])
{
size_t base_length = strlen(name);
const char *all = /* search pattern must end with suitable wildcard */
strchr("/\\", name[base_length - 1]) ? "*" : "/*";
if((dir = (DIR *) malloc(sizeof *dir)) != 0 &&
(dir->name = (char *) malloc(base_length + strlen(all) + 1)) != 0)
{
strcat(strcpy(dir->name, name), all);
if((dir->handle =
(handle_type) _findfirst(dir->name, &dir->info)) != -1)
{
dir->result.d_name = 0;
}
else /* rollback */
{
free(dir->name);
free(dir);
dir = 0;
}
}
else /* rollback */
{
free(dir);
dir = 0;
errno = ENOMEM;
}
}
else
{
errno = EINVAL;
}
return dir;
}
int closedir(DIR *dir)
{
int result = -1;
if(dir)
{
if(dir->handle != -1)
{
result = _findclose(dir->handle);
}
free(dir->name);
free(dir);
}
if(result == -1) /* map all errors to EBADF */
{
errno = EBADF;
}
return result;
}
struct dirent *readdir(DIR *dir)
{
struct dirent *result = 0;
if(dir && dir->handle != -1)
{
if(!dir->result.d_name || _findnext(dir->handle, &dir->info) != -1)
{
result = &dir->result;
result->d_name = dir->info.name;
}
}
else
{
errno = EBADF;
}
return result;
}
void rewinddir(DIR *dir)
{
if(dir && dir->handle != -1)
{
_findclose(dir->handle);
dir->handle = (handle_type) _findfirst(dir->name, &dir->info);
dir->result.d_name = 0;
}
else
{
errno = EBADF;
}
}
#ifdef __cplusplus
}
#endif
/*
Copyright Kevlin Henney, 1997, 2003, 2012. All rights reserved.
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose is hereby granted without fee, provided
that this copyright and permissions notice appear in all copies and
derivatives.
This software is supplied "as is" without express or implied warranty.
But that said, if there are any problems please get in touch.
*/
+304
View File
@@ -0,0 +1,304 @@
/*
** dir.c - Dir
**
** See Copyright Notice in mruby.h
*/
#include "mruby.h"
#include "mruby/class.h"
#include "mruby/data.h"
#include "mruby/string.h"
#include "error.h"
#include <sys/types.h>
#if defined(_WIN32) || defined(_WIN64)
#define MAXPATHLEN 1024
#if !defined(PATH_MAX)
#define PATH_MAX MAX_PATH
#endif
#define S_ISDIR(B) ((B)&_S_IFDIR)
#include "Win/dirent.c"
#include <direct.h>
#define rmdir _rmdir
#define getcwd _getcwd
#define mkdir _mkdir
#define chdir _chdir
#else
#include <sys/param.h>
#include <dirent.h>
#include <unistd.h>
#endif
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
/* with/without IO module */
#ifdef ENABLE_IO
#include "mruby/ext/io.h"
#else
#define E_IO_ERROR E_RUNTIME_ERROR
#endif
struct mrb_dir {
DIR *dir;
};
void
mrb_dir_free(mrb_state *mrb, void *ptr)
{
struct mrb_dir *mdir = (struct mrb_dir *)ptr;
if (mdir->dir) {
closedir(mdir->dir);
mdir->dir = NULL;
}
mrb_free(mrb, mdir);
}
static struct mrb_data_type mrb_dir_type = { "DIR", mrb_dir_free };
mrb_value
mrb_dir_close(mrb_state *mrb, mrb_value self)
{
struct mrb_dir *mdir;
mdir = (struct mrb_dir *)mrb_get_datatype(mrb, self, &mrb_dir_type);
if (!mdir) return mrb_nil_value();
if (!mdir->dir) {
mrb_raise(mrb, E_IO_ERROR, "closed directory");
}
if (closedir(mdir->dir) == -1) {
mrb_sys_fail(mrb, "closedir");
}
mdir->dir = NULL;
return mrb_nil_value();
}
mrb_value
mrb_dir_init(mrb_state *mrb, mrb_value self)
{
DIR *dir;
struct mrb_dir *mdir;
mrb_value path;
char *cpath;
mdir = (struct mrb_dir *)DATA_PTR(self);
if (mdir) {
mrb_dir_free(mrb, mdir);
}
DATA_TYPE(self) = &mrb_dir_type;
DATA_PTR(self) = NULL;
mdir = (struct mrb_dir *)mrb_malloc(mrb, sizeof(*mdir));
mdir->dir = NULL;
DATA_PTR(self) = mdir;
mrb_get_args(mrb, "S", &path);
cpath = mrb_str_to_cstr(mrb, path);
if ((dir = opendir(cpath)) == NULL) {
mrb_sys_fail(mrb, cpath);
}
mdir->dir = dir;
return self;
}
mrb_value
mrb_dir_delete(mrb_state *mrb, mrb_value klass)
{
mrb_value path;
char *cpath;
mrb_get_args(mrb, "S", &path);
cpath = mrb_str_to_cstr(mrb, path);
if (rmdir(cpath) == -1) {
mrb_sys_fail(mrb, cpath);
}
return mrb_fixnum_value(0);
}
mrb_value
mrb_dir_existp(mrb_state *mrb, mrb_value klass)
{
mrb_value path;
struct stat sb;
char *cpath;
mrb_get_args(mrb, "S", &path);
cpath = mrb_str_to_cstr(mrb, path);
if (stat(cpath, &sb) == 0 && S_ISDIR(sb.st_mode)) {
return mrb_true_value();
} else {
return mrb_false_value();
}
}
mrb_value
mrb_dir_getwd(mrb_state *mrb, mrb_value klass)
{
mrb_value path;
path = mrb_str_buf_new(mrb, MAXPATHLEN);
if (getcwd(RSTRING_PTR(path), MAXPATHLEN) == NULL) {
mrb_sys_fail(mrb, "getcwd(2)");
}
mrb_str_resize(mrb, path, strlen(RSTRING_PTR(path)));
return path;
}
mrb_value
mrb_dir_mkdir(mrb_state *mrb, mrb_value klass)
{
mrb_int mode;
mrb_value spath;
char *path;
mode = 0777;
mrb_get_args(mrb, "S|i", &spath, &mode);
path = mrb_str_to_cstr(mrb, spath);
#ifndef _WIN32
if (mkdir(path, mode) == -1) {
#else
if (mkdir(path) == -1) {
#endif
mrb_sys_fail(mrb, path);
}
return mrb_fixnum_value(0);
}
mrb_value
mrb_dir_chdir(mrb_state *mrb, mrb_value klass)
{
mrb_value spath;
char *path;
mrb_get_args(mrb, "S", &spath);
path = mrb_str_to_cstr(mrb, spath);
if (chdir(path) == -1) {
mrb_sys_fail(mrb, path);
}
return mrb_fixnum_value(0);
}
mrb_value
mrb_dir_chroot(mrb_state *mrb, mrb_value self)
{
#if defined(_WIN32) || defined(_WIN64) || defined(__ANDROID__)
mrb_raise(mrb, E_NOTIMP_ERROR, "chroot() unreliable on your system");
return mrb_fixnum_value(0);
#else
mrb_value spath;
char *path;
int res;
mrb_get_args(mrb, "S", &spath);
path = mrb_str_to_cstr(mrb, spath);
res = chroot(path);
if (res == -1) {
mrb_sys_fail(mrb, path);
}
return mrb_fixnum_value(res);
#endif
}
mrb_value
mrb_dir_read(mrb_state *mrb, mrb_value self)
{
struct mrb_dir *mdir;
struct dirent *dp;
mdir = (struct mrb_dir *)mrb_get_datatype(mrb, self, &mrb_dir_type);
if (!mdir) return mrb_nil_value();
if (!mdir->dir) {
mrb_raise(mrb, E_IO_ERROR, "closed directory");
}
dp = readdir(mdir->dir);
if (dp != NULL) {
return mrb_str_new_cstr(mrb, dp->d_name);
} else {
return mrb_nil_value();
}
}
mrb_value
mrb_dir_rewind(mrb_state *mrb, mrb_value self)
{
struct mrb_dir *mdir;
mdir = (struct mrb_dir *)mrb_get_datatype(mrb, self, &mrb_dir_type);
if (!mdir) return mrb_nil_value();
if (!mdir->dir) {
mrb_raise(mrb, E_IO_ERROR, "closed directory");
}
rewinddir(mdir->dir);
return self;
}
mrb_value
mrb_dir_seek(mrb_state *mrb, mrb_value self)
{
#if defined(_WIN32) || defined(_WIN64) || defined(__ANDROID__)
mrb_raise(mrb, E_NOTIMP_ERROR, "dirseek() unreliable on your system");
return self;
#else
struct mrb_dir *mdir;
mrb_int pos;
mdir = (struct mrb_dir *)mrb_get_datatype(mrb, self, &mrb_dir_type);
if (!mdir) return mrb_nil_value();
if (!mdir->dir) {
mrb_raise(mrb, E_IO_ERROR, "closed directory");
}
mrb_get_args(mrb, "i", &pos);
seekdir(mdir->dir, (long)pos);
return self;
#endif
}
mrb_value
mrb_dir_tell(mrb_state *mrb, mrb_value self)
{
#if defined(_WIN32) || defined(_WIN64) || defined(__ANDROID__)
mrb_raise(mrb, E_NOTIMP_ERROR, "dirtell() unreliable on your system");
return mrb_fixnum_value(0);
#else
struct mrb_dir *mdir;
mrb_int pos;
mdir = (struct mrb_dir *)mrb_get_datatype(mrb, self, &mrb_dir_type);
if (!mdir) return mrb_nil_value();
if (!mdir->dir) {
mrb_raise(mrb, E_IO_ERROR, "closed directory");
}
pos = (mrb_int)telldir(mdir->dir);
return mrb_fixnum_value(pos);
#endif
}
void
mrb_mruby_dir_gem_init(mrb_state *mrb)
{
struct RClass *d;
d = mrb_define_class(mrb, "Dir", mrb->object_class);
MRB_SET_INSTANCE_TT(d, MRB_TT_DATA);
mrb_define_class_method(mrb, d, "delete", mrb_dir_delete, MRB_ARGS_REQ(1));
mrb_define_class_method(mrb, d, "exist?", mrb_dir_existp, MRB_ARGS_REQ(1));
mrb_define_class_method(mrb, d, "getwd", mrb_dir_getwd, MRB_ARGS_NONE());
mrb_define_class_method(mrb, d, "mkdir", mrb_dir_mkdir, MRB_ARGS_REQ(1)|MRB_ARGS_OPT(1));
mrb_define_class_method(mrb, d, "_chdir", mrb_dir_chdir, MRB_ARGS_REQ(1));
mrb_define_class_method(mrb, d, "chroot", mrb_dir_chroot, MRB_ARGS_REQ(1));
mrb_define_method(mrb, d, "close", mrb_dir_close, MRB_ARGS_NONE());
mrb_define_method(mrb, d, "initialize", mrb_dir_init, MRB_ARGS_REQ(1));
mrb_define_method(mrb, d, "read", mrb_dir_read, MRB_ARGS_NONE());
mrb_define_method(mrb, d, "rewind", mrb_dir_rewind, MRB_ARGS_NONE());
mrb_define_method(mrb, d, "seek", mrb_dir_seek, MRB_ARGS_REQ(1));
mrb_define_method(mrb, d, "tell", mrb_dir_tell, MRB_ARGS_NONE());
}
void
mrb_mruby_dir_gem_final(mrb_state *mrb)
{
}
+136
View File
@@ -0,0 +1,136 @@
assert('Dir') do
assert_equal(Class, Dir.class)
end
assert('DirTest.setup') do
DirTest.setup
end
assert('Dir.chdir') do
assert_equal 0, Dir.chdir(DirTest.sandbox)
end
assert('Dir.entries') do
a = Dir.entries(DirTest.sandbox)
assert_true a.include? "a"
assert_true a.include? "b"
end
assert('Dir.exist?') do
assert_true Dir.exist?(DirTest.sandbox)
assert_false Dir.exist?(DirTest.sandbox + "/nosuchdir")
end
assert('Dir.foreach') do
a = []
Dir.foreach(DirTest.sandbox) { |s| a << s }
assert_true a.include? "a"
assert_true a.include? "b"
end
assert('Dir.getwd') do
s = Dir.getwd
assert_true s.kind_of? String
end
assert('Dir.mkdir') do
m1 = DirTest.sandbox + "/mkdir1"
m2 = DirTest.sandbox + "/mkdir2"
assert_equal 0, Dir.mkdir(m1)
assert_equal 0, Dir.mkdir(m2, 0765)
end
assert('Dir.delete') do
s = DirTest.sandbox + "/delete"
Dir.mkdir(s)
assert_true Dir.exist?(s)
Dir.delete(s)
assert_false Dir.exist?(s)
end
assert('Dir.open') do
a = []
Dir.open(DirTest.sandbox) { |d|
d.each { |s| a << s }
}
assert_true a.include? "a"
assert_true a.include? "b"
end
assert('Dir#initialize and Dir#close') do
d = Dir.new(".")
assert_true d.instance_of? Dir
assert_nil d.close
end
assert('Dir#close') do
d = Dir.new(".")
end
assert('Dir#each') do
a = []
d = Dir.open(DirTest.sandbox)
d.each { |s| a << s }
d.close
assert_true a.include? "a"
assert_true a.include? "b"
end
assert('Dir#read') do
a = []
d = Dir.open(DirTest.sandbox)
while s = d.read
a << s
end
d.close
assert_true a.include? "a"
assert_true a.include? "b"
end
assert('Dir#rewind') do
d = Dir.open(DirTest.sandbox)
while d.read; end
assert_equal d, d.rewind
a = []
while s = d.read
a << s
end
d.close
assert_true a.include? "a"
assert_true a.include? "b"
end
# Note: behaviors of seekdir(3) and telldir(3) are so platform-dependent
# that we cannot write portable tests here.
assert('Dir#tell') do
n = nil
begin
Dir.open(DirTest.sandbox) { |d|
n = d.tell
}
assert_true n.is_a? Integer
rescue NotImplementedError => e
skip e.message
end
end
assert('Dir#seek') do
d1 = Dir.open(DirTest.sandbox)
d1.read
begin
n = d1.tell
d1.read
d2 = d1.seek(n)
assert_equal d1, d2
rescue NotImplementedError => e
skip e.message
end
end
assert('DirTest.teardown') do
DirTest.teardown
end
+129
View File
@@ -0,0 +1,129 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "mruby.h"
#include "mruby/string.h"
#include "mruby/variable.h"
mrb_value
mrb_dirtest_setup(mrb_state *mrb, mrb_value klass)
{
mrb_value s;
char buf[1024];
const char *aname = "a";
const char *bname = "b";
/* save current working directory */
if (getcwd(buf, sizeof(buf)) == NULL) {
mrb_raise(mrb, E_RUNTIME_ERROR, "getcwd() failed");
}
mrb_cv_set(mrb, klass, mrb_intern_cstr(mrb, "pwd"), mrb_str_new_cstr(mrb, buf));
/* create sandbox */
#if defined(_WIN32) || defined(_WIN64)
snprintf(buf, sizeof(buf), "%s\\mruby-dir-test.XXXXXX", _getcwd(NULL,0));
if ((mktemp(buf) == NULL) || mkdir(buf) != 0) {
mrb_raisef(mrb, E_RUNTIME_ERROR, "mkdtemp(%S) failed", mrb_str_new_cstr(mrb, buf));
}
#else
snprintf(buf, sizeof(buf), "%s/mruby-dir-test.XXXXXX", P_tmpdir);
if (mkdtemp(buf) == NULL) {
mrb_raisef(mrb, E_RUNTIME_ERROR, "mkdtemp(%S) failed", mrb_str_new_cstr(mrb, buf));
}
#endif
s = mrb_str_new_cstr(mrb, buf);
mrb_cv_set(mrb, klass, mrb_intern_cstr(mrb, "sandbox"), s);
/* go to sandbox */
if (chdir(buf) == -1) {
rmdir(buf);
mrb_raisef(mrb, E_RUNTIME_ERROR, "chdir(%S) failed", s);
}
/* make some directories in the sandbox */
#if defined(_WIN32) || defined(_WIN64)
if (mkdir(aname) == -1) {
#else
if (mkdir(aname, 0) == -1) {
#endif
chdir("..");
rmdir(buf);
mrb_raisef(mrb, E_RUNTIME_ERROR, "mkdir(%S) failed", mrb_str_new_cstr(mrb, aname));
}
#if defined(_WIN32) || defined(_WIN64)
if (mkdir(bname) == -1) {
#else
if (mkdir(bname, 0) == -1) {
#endif
rmdir(aname);
chdir("..");
rmdir(buf);
mrb_raisef(mrb, E_RUNTIME_ERROR, "mkdir(%S) failed", mrb_str_new_cstr(mrb, bname));
}
return mrb_true_value();
}
mrb_value
mrb_dirtest_teardown(mrb_state *mrb, mrb_value klass)
{
mrb_value d, sandbox;
DIR *dirp;
struct dirent *dp;
const char *path;
/* cleanup sandbox */
sandbox = mrb_cv_get(mrb, klass, mrb_intern_cstr(mrb, "sandbox"));
path = mrb_str_to_cstr(mrb, sandbox);
dirp = opendir(path);
while ((dp = readdir(dirp)) != NULL) {
if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0)
continue;
if (rmdir(dp->d_name) == -1) {
mrb_raisef(mrb, E_RUNTIME_ERROR, "rmdir(%S) failed", mrb_str_new_cstr(mrb, dp->d_name));
}
}
closedir(dirp);
/* back to original pwd */
d = mrb_cv_get(mrb, klass, mrb_intern_cstr(mrb, "pwd"));
path = mrb_str_to_cstr(mrb, d);
if (chdir(path) == -1) {
mrb_raisef(mrb, E_RUNTIME_ERROR, "chdir(%S) failed", d);
}
/* remove sandbox directory */
sandbox = mrb_cv_get(mrb, klass, mrb_intern_cstr(mrb, "sandbox"));
path = mrb_str_to_cstr(mrb, sandbox);
if (rmdir(path) == -1) {
mrb_raisef(mrb, E_RUNTIME_ERROR, "rmdir(%S) failed", sandbox);
}
return mrb_true_value();
}
mrb_value
mrb_dirtest_sandbox(mrb_state *mrb, mrb_value klass)
{
return mrb_cv_get(mrb, klass, mrb_intern_cstr(mrb, "sandbox"));
}
void
mrb_mruby_dir_gem_test(mrb_state *mrb)
{
struct RClass *c = mrb_define_module(mrb, "DirTest");
mrb_define_class_method(mrb, c, "sandbox", mrb_dirtest_sandbox, MRB_ARGS_NONE());
mrb_define_class_method(mrb, c, "setup", mrb_dirtest_setup, MRB_ARGS_NONE());
mrb_define_class_method(mrb, c, "teardown", mrb_dirtest_teardown, MRB_ARGS_NONE());
}