diff options
author | Chin Huang <chhuang@us.ibm.com> | 2018-03-21 11:07:23 -0700 |
---|---|---|
committer | James M Snell <jasnell@gmail.com> | 2018-04-14 12:45:25 -0700 |
commit | 09c63460ebda30c7d5e7f40532a311fb2139803a (patch) | |
tree | 42c971e8c15751ffef0c7567b86a6904194bce79 | |
parent | c1a05e5c26492a2107d49cbc3ef86baece578a79 (diff) | |
download | android-node-v8-09c63460ebda30c7d5e7f40532a311fb2139803a.tar.gz android-node-v8-09c63460ebda30c7d5e7f40532a311fb2139803a.tar.bz2 android-node-v8-09c63460ebda30c7d5e7f40532a311fb2139803a.zip |
src: add sync trace to fs
Add sync trace to fs operations which
is enabled by the node.fs.sync trace event
category. Also add a general test js file
to verify all operations.
PR-URL: https://github.com/nodejs/node/pull/19649
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com>
-rw-r--r-- | src/node_file.cc | 77 | ||||
-rw-r--r-- | src/tracing/trace_event_common.h | 6 | ||||
-rw-r--r-- | test/parallel/test-trace-events-fs-sync.js | 162 |
3 files changed, 244 insertions, 1 deletions
diff --git a/src/node_file.cc b/src/node_file.cc index 14d908cd6f..28a128b89c 100644 --- a/src/node_file.cc +++ b/src/node_file.cc @@ -24,6 +24,7 @@ #include "node_internals.h" #include "node_stat_watcher.h" #include "node_file.h" +#include "tracing/trace_event.h" #include "req_wrap-inl.h" #include "stream_base-inl.h" @@ -75,6 +76,18 @@ using v8::Value; #endif #define GET_OFFSET(a) ((a)->IsNumber() ? (a).As<Integer>()->Value() : -1) +#define TRACE_NAME(name) "fs.sync." #name +#define GET_TRACE_ENABLED \ + (*TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED \ + (TRACING_CATEGORY_NODE2(fs, sync)) != 0) +#define FS_SYNC_TRACE_BEGIN(syscall, ...) \ + if (GET_TRACE_ENABLED) \ + TRACE_EVENT_BEGIN(TRACING_CATEGORY_NODE2(fs, sync), TRACE_NAME(syscall), \ + ##__VA_ARGS__); +#define FS_SYNC_TRACE_END(syscall, ...) \ + if (GET_TRACE_ENABLED) \ + TRACE_EVENT_END(TRACING_CATEGORY_NODE2(fs, sync), TRACE_NAME(syscall), \ + ##__VA_ARGS__); // The FileHandle object wraps a file descriptor and will close it on garbage // collection if necessary. If that happens, a process warning will be @@ -316,7 +329,7 @@ int FileHandle::ReadStart() { // ReadStart() checks whether current_read_ is set to determine whether // a read is in progress. Moving it into a local variable makes sure that - // the ReadStart() call below doesn’t think we’re still actively reading. + // the ReadStart() call below doesn't think we're still actively reading. std::unique_ptr<FileHandleReadWrap> read_wrap = std::move(handle->current_read_); @@ -683,7 +696,9 @@ void Access(const FunctionCallbackInfo<Value>& args) { } else { // access(path, mode, undefined, ctx) CHECK_EQ(argc, 4); FSReqWrapSync req_wrap_sync; + FS_SYNC_TRACE_BEGIN(access); SyncCall(env, args[3], &req_wrap_sync, "access", uv_fs_access, *path, mode); + FS_SYNC_TRACE_END(access); } } @@ -704,7 +719,9 @@ void Close(const FunctionCallbackInfo<Value>& args) { } else { // close(fd, undefined, ctx) CHECK_EQ(argc, 3); FSReqWrapSync req_wrap_sync; + FS_SYNC_TRACE_BEGIN(close); SyncCall(env, args[2], &req_wrap_sync, "close", uv_fs_close, fd); + FS_SYNC_TRACE_END(close); } } @@ -812,7 +829,9 @@ static void Stat(const FunctionCallbackInfo<Value>& args) { } else { // stat(path, undefined, ctx) CHECK_EQ(argc, 3); FSReqWrapSync req_wrap_sync; + FS_SYNC_TRACE_BEGIN(stat); int err = SyncCall(env, args[2], &req_wrap_sync, "stat", uv_fs_stat, *path); + FS_SYNC_TRACE_END(stat); if (err == 0) { node::FillGlobalStatsArray(env, static_cast<const uv_stat_t*>(req_wrap_sync.req.ptr)); @@ -836,8 +855,10 @@ static void LStat(const FunctionCallbackInfo<Value>& args) { } else { // lstat(path, undefined, ctx) CHECK_EQ(argc, 3); FSReqWrapSync req_wrap_sync; + FS_SYNC_TRACE_BEGIN(lstat); int err = SyncCall(env, args[2], &req_wrap_sync, "lstat", uv_fs_lstat, *path); + FS_SYNC_TRACE_END(lstat); if (err == 0) { node::FillGlobalStatsArray(env, static_cast<const uv_stat_t*>(req_wrap_sync.req.ptr)); @@ -861,7 +882,9 @@ static void FStat(const FunctionCallbackInfo<Value>& args) { } else { // fstat(fd, undefined, ctx) CHECK_EQ(argc, 3); FSReqWrapSync req_wrap_sync; + FS_SYNC_TRACE_BEGIN(fstat); int err = SyncCall(env, args[2], &req_wrap_sync, "fstat", uv_fs_fstat, fd); + FS_SYNC_TRACE_END(fstat); if (err == 0) { node::FillGlobalStatsArray(env, static_cast<const uv_stat_t*>(req_wrap_sync.req.ptr)); @@ -890,8 +913,10 @@ static void Symlink(const FunctionCallbackInfo<Value>& args) { } else { // symlink(target, path, flags, undefinec, ctx) CHECK_EQ(argc, 5); FSReqWrapSync req_wrap_sync; + FS_SYNC_TRACE_BEGIN(symlink); SyncCall(env, args[4], &req_wrap_sync, "symlink", uv_fs_symlink, *target, *path, flags); + FS_SYNC_TRACE_END(symlink); } } @@ -914,8 +939,10 @@ static void Link(const FunctionCallbackInfo<Value>& args) { } else { // link(src, dest) CHECK_EQ(argc, 4); FSReqWrapSync req_wrap_sync; + FS_SYNC_TRACE_BEGIN(link); SyncCall(env, args[3], &req_wrap_sync, "link", uv_fs_link, *src, *dest); + FS_SYNC_TRACE_END(link); } } @@ -937,8 +964,10 @@ static void ReadLink(const FunctionCallbackInfo<Value>& args) { } else { CHECK_EQ(argc, 4); FSReqWrapSync req_wrap_sync; + FS_SYNC_TRACE_BEGIN(readlink); int err = SyncCall(env, args[3], &req_wrap_sync, "readlink", uv_fs_readlink, *path); + FS_SYNC_TRACE_END(readlink); if (err < 0) { return; // syscall failed, no need to continue, error info is in ctx } @@ -978,8 +1007,10 @@ static void Rename(const FunctionCallbackInfo<Value>& args) { } else { CHECK_EQ(argc, 4); FSReqWrapSync req_wrap_sync; + FS_SYNC_TRACE_BEGIN(rename); SyncCall(env, args[3], &req_wrap_sync, "rename", uv_fs_rename, *old_path, *new_path); + FS_SYNC_TRACE_END(rename); } } @@ -1002,8 +1033,10 @@ static void FTruncate(const FunctionCallbackInfo<Value>& args) { } else { CHECK_EQ(argc, 4); FSReqWrapSync req_wrap_sync; + FS_SYNC_TRACE_BEGIN(ftruncate); SyncCall(env, args[3], &req_wrap_sync, "ftruncate", uv_fs_ftruncate, fd, len); + FS_SYNC_TRACE_END(ftruncate); } } @@ -1023,7 +1056,9 @@ static void Fdatasync(const FunctionCallbackInfo<Value>& args) { } else { CHECK_EQ(argc, 3); FSReqWrapSync req_wrap_sync; + FS_SYNC_TRACE_BEGIN(fdatasync); SyncCall(env, args[2], &req_wrap_sync, "fdatasync", uv_fs_fdatasync, fd); + FS_SYNC_TRACE_END(fdatasync); } } @@ -1043,7 +1078,9 @@ static void Fsync(const FunctionCallbackInfo<Value>& args) { } else { CHECK_EQ(argc, 3); FSReqWrapSync req_wrap_sync; + FS_SYNC_TRACE_BEGIN(fsync); SyncCall(env, args[2], &req_wrap_sync, "fsync", uv_fs_fsync, fd); + FS_SYNC_TRACE_END(fsync); } } @@ -1063,7 +1100,9 @@ static void Unlink(const FunctionCallbackInfo<Value>& args) { } else { CHECK_EQ(argc, 3); FSReqWrapSync req_wrap_sync; + FS_SYNC_TRACE_BEGIN(unlink); SyncCall(env, args[2], &req_wrap_sync, "unlink", uv_fs_unlink, *path); + FS_SYNC_TRACE_END(unlink); } } @@ -1083,8 +1122,10 @@ static void RMDir(const FunctionCallbackInfo<Value>& args) { } else { // rmdir(path, undefined, ctx) CHECK_EQ(argc, 3); FSReqWrapSync req_wrap_sync; + FS_SYNC_TRACE_BEGIN(rmdir); SyncCall(env, args[2], &req_wrap_sync, "rmdir", uv_fs_rmdir, *path); + FS_SYNC_TRACE_END(rmdir); } } @@ -1107,8 +1148,10 @@ static void MKDir(const FunctionCallbackInfo<Value>& args) { } else { // mkdir(path, mode, undefined, ctx) CHECK_EQ(argc, 4); FSReqWrapSync req_wrap_sync; + FS_SYNC_TRACE_BEGIN(mkdir); SyncCall(env, args[3], &req_wrap_sync, "mkdir", uv_fs_mkdir, *path, mode); + FS_SYNC_TRACE_END(mkdir); } } @@ -1130,8 +1173,10 @@ static void RealPath(const FunctionCallbackInfo<Value>& args) { } else { // realpath(path, encoding, undefined, ctx) CHECK_EQ(argc, 4); FSReqWrapSync req_wrap_sync; + FS_SYNC_TRACE_BEGIN(realpath); int err = SyncCall(env, args[3], &req_wrap_sync, "realpath", uv_fs_realpath, *path); + FS_SYNC_TRACE_END(realpath); if (err < 0) { return; // syscall failed, no need to continue, error info is in ctx } @@ -1171,8 +1216,10 @@ static void ReadDir(const FunctionCallbackInfo<Value>& args) { } else { // readdir(path, encoding, undefined, ctx) CHECK_EQ(argc, 4); FSReqWrapSync req_wrap_sync; + FS_SYNC_TRACE_BEGIN(readdir); int err = SyncCall(env, args[3], &req_wrap_sync, "scandir", uv_fs_scandir, *path, 0 /*flags*/); + FS_SYNC_TRACE_END(readdir); if (err < 0) { return; // syscall failed, no need to continue, error info is in ctx } @@ -1255,8 +1302,10 @@ static void Open(const FunctionCallbackInfo<Value>& args) { } else { // open(path, flags, mode, undefined, ctx) CHECK_EQ(argc, 5); FSReqWrapSync req_wrap_sync; + FS_SYNC_TRACE_BEGIN(open); int result = SyncCall(env, args[4], &req_wrap_sync, "open", uv_fs_open, *path, flags, mode); + FS_SYNC_TRACE_END(open); args.GetReturnValue().Set(result); } } @@ -1283,8 +1332,10 @@ static void OpenFileHandle(const FunctionCallbackInfo<Value>& args) { } else { // openFileHandle(path, flags, mode, undefined, ctx) CHECK_EQ(argc, 5); FSReqWrapSync req_wrap_sync; + FS_SYNC_TRACE_BEGIN(open); int result = SyncCall(env, args[4], &req_wrap_sync, "open", uv_fs_open, *path, flags, mode); + FS_SYNC_TRACE_END(open); if (result < 0) { return; // syscall failed, no need to continue, error info is in ctx } @@ -1317,8 +1368,10 @@ static void CopyFile(const FunctionCallbackInfo<Value>& args) { } else { // copyFile(src, dest, flags, undefined, ctx) CHECK_EQ(argc, 5); FSReqWrapSync req_wrap_sync; + FS_SYNC_TRACE_BEGIN(copyfile); SyncCall(env, args[4], &req_wrap_sync, "copyfile", uv_fs_copyfile, *src, *dest, flags); + FS_SYNC_TRACE_END(copyfile); } } @@ -1368,8 +1421,10 @@ static void WriteBuffer(const FunctionCallbackInfo<Value>& args) { } else { // write(fd, buffer, off, len, pos, undefined, ctx) CHECK_EQ(argc, 7); FSReqWrapSync req_wrap_sync; + FS_SYNC_TRACE_BEGIN(write); int bytesWritten = SyncCall(env, args[6], &req_wrap_sync, "write", uv_fs_write, fd, &uvbuf, 1, pos); + FS_SYNC_TRACE_END(write, "bytesWritten", bytesWritten); args.GetReturnValue().Set(bytesWritten); } } @@ -1411,8 +1466,10 @@ static void WriteBuffers(const FunctionCallbackInfo<Value>& args) { } else { // writeBuffers(fd, chunks, pos, undefined, ctx) CHECK_EQ(argc, 5); FSReqWrapSync req_wrap_sync; + FS_SYNC_TRACE_BEGIN(write); int bytesWritten = SyncCall(env, args[4], &req_wrap_sync, "write", uv_fs_write, fd, *iovs, iovs.length(), pos); + FS_SYNC_TRACE_END(write, "bytesWritten", bytesWritten); args.GetReturnValue().Set(bytesWritten); } } @@ -1503,8 +1560,10 @@ static void WriteString(const FunctionCallbackInfo<Value>& args) { buf = *stack_buffer; } uv_buf_t uvbuf = uv_buf_init(buf, len); + FS_SYNC_TRACE_BEGIN(write); int bytesWritten = SyncCall(env, args[5], &req_wrap_sync, "write", uv_fs_write, fd, &uvbuf, 1, pos); + FS_SYNC_TRACE_END(write, "bytesWritten", bytesWritten); args.GetReturnValue().Set(bytesWritten); } } @@ -1556,8 +1615,10 @@ static void Read(const FunctionCallbackInfo<Value>& args) { } else { // read(fd, buffer, offset, len, pos, undefined, ctx) CHECK_EQ(argc, 7); FSReqWrapSync req_wrap_sync; + FS_SYNC_TRACE_BEGIN(read); const int bytesRead = SyncCall(env, args[6], &req_wrap_sync, "read", uv_fs_read, fd, &uvbuf, 1, pos); + FS_SYNC_TRACE_END(read, "bytesRead", bytesRead); args.GetReturnValue().Set(bytesRead); } } @@ -1585,8 +1646,10 @@ static void Chmod(const FunctionCallbackInfo<Value>& args) { } else { // chmod(path, mode, undefined, ctx) CHECK_EQ(argc, 4); FSReqWrapSync req_wrap_sync; + FS_SYNC_TRACE_BEGIN(chmod); SyncCall(env, args[3], &req_wrap_sync, "chmod", uv_fs_chmod, *path, mode); + FS_SYNC_TRACE_END(chmod); } } @@ -1613,8 +1676,10 @@ static void FChmod(const FunctionCallbackInfo<Value>& args) { } else { // fchmod(fd, mode, undefined, ctx) CHECK_EQ(argc, 4); FSReqWrapSync req_wrap_sync; + FS_SYNC_TRACE_BEGIN(fchmod); SyncCall(env, args[3], &req_wrap_sync, "fchmod", uv_fs_fchmod, fd, mode); + FS_SYNC_TRACE_END(fchmod); } } @@ -1644,8 +1709,10 @@ static void Chown(const FunctionCallbackInfo<Value>& args) { } else { // chown(path, uid, gid, undefined, ctx) CHECK_EQ(argc, 5); FSReqWrapSync req_wrap_sync; + FS_SYNC_TRACE_BEGIN(chown); SyncCall(env, args[4], &req_wrap_sync, "chown", uv_fs_chown, *path, uid, gid); + FS_SYNC_TRACE_END(chown); } } @@ -1675,8 +1742,10 @@ static void FChown(const FunctionCallbackInfo<Value>& args) { } else { // fchown(fd, uid, gid, undefined, ctx) CHECK_EQ(argc, 5); FSReqWrapSync req_wrap_sync; + FS_SYNC_TRACE_BEGIN(fchown); SyncCall(env, args[4], &req_wrap_sync, "fchown", uv_fs_fchown, fd, uid, gid); + FS_SYNC_TRACE_END(fchown); } } @@ -1703,8 +1772,10 @@ static void UTimes(const FunctionCallbackInfo<Value>& args) { } else { // utimes(path, atime, mtime, undefined, ctx) CHECK_EQ(argc, 5); FSReqWrapSync req_wrap_sync; + FS_SYNC_TRACE_BEGIN(utimes); SyncCall(env, args[4], &req_wrap_sync, "utime", uv_fs_utime, *path, atime, mtime); + FS_SYNC_TRACE_END(utimes); } } @@ -1730,8 +1801,10 @@ static void FUTimes(const FunctionCallbackInfo<Value>& args) { } else { // futimes(fd, atime, mtime, undefined, ctx) CHECK_EQ(argc, 5); FSReqWrapSync req_wrap_sync; + FS_SYNC_TRACE_BEGIN(futimes); SyncCall(env, args[4], &req_wrap_sync, "futime", uv_fs_futime, fd, atime, mtime); + FS_SYNC_TRACE_END(futimes); } } @@ -1753,8 +1826,10 @@ static void Mkdtemp(const FunctionCallbackInfo<Value>& args) { } else { // mkdtemp(tmpl, encoding, undefined, ctx) CHECK_EQ(argc, 4); FSReqWrapSync req_wrap_sync; + FS_SYNC_TRACE_BEGIN(mkdtemp); SyncCall(env, args[3], &req_wrap_sync, "mkdtemp", uv_fs_mkdtemp, *tmpl); + FS_SYNC_TRACE_END(mkdtemp); const char* path = static_cast<const char*>(req_wrap_sync.req.path); Local<Value> error; diff --git a/src/tracing/trace_event_common.h b/src/tracing/trace_event_common.h index 51869ee952..18dd6ec18b 100644 --- a/src/tracing/trace_event_common.h +++ b/src/tracing/trace_event_common.h @@ -271,6 +271,9 @@ // does nothing. // - category and name strings must have application lifetime (statics or // literals). They may not include " chars. +#define TRACE_EVENT_BEGIN(category_group, name, ...) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, category_group, name, \ + TRACE_EVENT_FLAG_NONE, ##__VA_ARGS__) #define TRACE_EVENT_BEGIN0(category_group, name) \ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, category_group, name, \ TRACE_EVENT_FLAG_NONE) @@ -327,6 +330,9 @@ // is not enabled, then this does nothing. // - category and name strings must have application lifetime (statics or // literals). They may not include " chars. +#define TRACE_EVENT_END(category_group, name, ...) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, category_group, name, \ + TRACE_EVENT_FLAG_NONE, ##__VA_ARGS__) #define TRACE_EVENT_END0(category_group, name) \ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, category_group, name, \ TRACE_EVENT_FLAG_NONE) diff --git a/test/parallel/test-trace-events-fs-sync.js b/test/parallel/test-trace-events-fs-sync.js new file mode 100644 index 0000000000..5bd9b99ba3 --- /dev/null +++ b/test/parallel/test-trace-events-fs-sync.js @@ -0,0 +1,162 @@ +'use strict'; +const common = require('../common'); +const assert = require('assert'); +const cp = require('child_process'); +const fs = require('fs'); + +const tests = new Array(); +const traceFile = 'node_trace.1.log'; + +let gid = 1; +let uid = 1; +let skipSymlinks = false; + +// On Windows, creating symlinks requires admin privileges. +// We'll check if we have enough privileges. +if (common.isWindows) { + try { + const o = cp.execSync('whoami /priv'); + if (!o.includes('SeCreateSymbolicLinkPrivilege')) { + skipSymlinks = true; + } + } catch (er) { + // better safe than sorry + skipSymlinks = true; + } +} else { + gid = process.getgid(); + uid = process.getuid(); +} + +tests['fs.sync.access'] = 'fs.writeFileSync("fs.txt", "123", "utf8");' + + 'fs.accessSync("fs.txt");' + + 'fs.unlinkSync("fs.txt")'; +tests['fs.sync.chmod'] = 'fs.writeFileSync("fs.txt", "123", "utf8");' + + 'fs.chmodSync("fs.txt",100);' + + 'fs.unlinkSync("fs.txt")'; +tests['fs.sync.chown'] = 'fs.writeFileSync("fs.txt", "123", "utf8");' + + 'fs.chownSync("fs.txt",' + uid + ',' + gid + ');' + + 'fs.unlinkSync("fs.txt")'; +tests['fs.sync.close'] = 'fs.writeFileSync("fs.txt", "123", "utf8");' + + 'fs.unlinkSync("fs.txt")'; +tests['fs.sync.copyfile'] = 'fs.writeFileSync("fs.txt", "123", "utf8");' + + 'fs.copyFileSync("fs.txt","a.txt");' + + 'fs.unlinkSync("fs.txt")'; +tests['fs.sync.fchmod'] = 'fs.writeFileSync("fs.txt", "123", "utf8");' + + 'const fd = fs.openSync("fs.txt", "r+");' + + 'fs.fchmodSync(fd,100);' + + 'fs.unlinkSync("fs.txt")'; +tests['fs.sync.fchown'] = 'fs.writeFileSync("fs.txt", "123", "utf8");' + + 'const fd = fs.openSync("fs.txt", "r+");' + + 'fs.fchownSync(fd,' + uid + ',' + gid + ');' + + 'fs.unlinkSync("fs.txt")'; +tests['fs.sync.fdatasync'] = 'fs.writeFileSync("fs.txt", "123", "utf8");' + + 'const fd = fs.openSync("fs.txt", "r+");' + + 'fs.fdatasyncSync(fd);' + + 'fs.unlinkSync("fs.txt")'; +tests['fs.sync.fstat'] = 'fs.writeFileSync("fs.txt", "123", "utf8");' + + 'fs.readFileSync("fs.txt");' + + 'fs.unlinkSync("fs.txt")'; +tests['fs.sync.fsync'] = 'fs.writeFileSync("fs.txt", "123", "utf8");' + + 'const fd = fs.openSync("fs.txt", "r+");' + + 'fs.fsyncSync(fd);' + + 'fs.unlinkSync("fs.txt")'; +tests['fs.sync.ftruncate'] = 'fs.writeFileSync("fs.txt", "123", "utf8");' + + 'const fd = fs.openSync("fs.txt", "r+");' + + 'fs.ftruncateSync(fd, 1);' + + 'fs.unlinkSync("fs.txt")'; +tests['fs.sync.futimes'] = 'fs.writeFileSync("fs.txt", "123", "utf8");' + + 'const fd = fs.openSync("fs.txt", "r+");' + + 'fs.futimesSync(fd,1,1);' + + 'fs.unlinkSync("fs.txt")'; +tests['fs.sync.link'] = 'fs.writeFileSync("fs.txt", "123", "utf8");' + + 'fs.linkSync("fs.txt", "linkx");' + + 'fs.unlinkSync("linkx");' + + 'fs.unlinkSync("fs.txt")'; +tests['fs.sync.lstat'] = 'fs.writeFileSync("fs.txt", "123", "utf8");' + + 'fs.lstatSync("fs.txt");' + + 'fs.unlinkSync("fs.txt")'; +tests['fs.sync.mkdir'] = 'fs.mkdirSync("fstemp");' + + 'fs.rmdirSync("fstemp")'; +tests['fs.sync.mkdtemp'] = 'const fp = fs.mkdtempSync("fstest");' + + 'fs.rmdirSync(fp)'; +tests['fs.sync.open'] = 'fs.writeFileSync("fs.txt", "123", "utf8");' + + 'fs.unlinkSync("fs.txt")'; +tests['fs.sync.read'] = 'fs.writeFileSync("fs.txt", "123", "utf8");' + + 'fs.readFileSync("fs.txt");' + + 'fs.unlinkSync("fs.txt")'; +tests['fs.sync.readdir'] = 'fs.readdirSync("./")'; +tests['fs.sync.realpath'] = 'fs.writeFileSync("fs.txt", "123", "utf8");' + + 'fs.linkSync("fs.txt", "linkx");' + + 'fs.realpathSync.native("linkx");' + + 'fs.unlinkSync("linkx");' + + 'fs.unlinkSync("fs.txt")'; +tests['fs.sync.rename'] = 'fs.writeFileSync("fs.txt", "123", "utf8");' + + 'fs.renameSync("fs.txt","xyz.txt"); ' + + 'fs.unlinkSync("xyz.txt")'; +tests['fs.sync.rmdir'] = 'fs.mkdirSync("fstemp");' + + 'fs.rmdirSync("fstemp")'; +tests['fs.sync.stat'] = 'fs.writeFileSync("fs.txt", "123", "utf8");' + + 'fs.statSync("fs.txt");' + + 'fs.unlinkSync("fs.txt")'; +tests['fs.sync.unlink'] = 'fs.writeFileSync("fs.txt", "123", "utf8");' + + 'fs.linkSync("fs.txt", "linkx");' + + 'fs.unlinkSync("linkx");' + + 'fs.unlinkSync("fs.txt")'; +tests['fs.sync.utimes'] = 'fs.writeFileSync("fs.txt", "123", "utf8");' + + 'fs.utimesSync("fs.txt",1,1);' + + 'fs.unlinkSync("fs.txt")'; +tests['fs.sync.write'] = 'fs.writeFileSync("fs.txt", "123", "utf8");' + + 'fs.unlinkSync("fs.txt")'; + +// On windows, we need permissions to test symlink and readlink. +// We'll only try to run these tests if we have enough privileges. +if (!skipSymlinks) { + tests['fs.sync.symlink'] = 'fs.writeFileSync("fs.txt", "123", "utf8");' + + 'fs.symlinkSync("fs.txt", "linkx");' + + 'fs.unlinkSync("linkx");' + + 'fs.unlinkSync("fs.txt")'; + tests['fs.sync.readlink'] = 'fs.writeFileSync("fs.txt", "123", "utf8");' + + 'fs.symlinkSync("fs.txt", "linkx");' + + 'fs.readlinkSync("linkx");' + + 'fs.unlinkSync("linkx");' + + 'fs.unlinkSync("fs.txt")'; +} + +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); +process.chdir(tmpdir.path); + +for (const tr in tests) { + const proc = cp.spawnSync(process.execPath, + [ '--trace-events-enabled', + '--trace-event-categories', 'node.fs.sync', + '-e', tests[tr] ]); + // Some AIX versions don't support futimes or utimes, so skip. + if (common.isAIX && proc.status !== 0 && tr === 'fs.sync.futimes') { + continue; + } + if (common.isAIX && proc.status !== 0 && tr === 'fs.sync.utimes') { + continue; + } + + // Make sure the operation is successful. + assert.strictEqual(proc.status, 0, tr + ': ' + proc.stderr); + + // Confirm that trace log file is created. + assert(common.fileExists(traceFile)); + const data = fs.readFileSync(traceFile); + const traces = JSON.parse(data.toString()).traceEvents; + assert(traces.length > 0); + + // C++ fs sync trace events should be generated. + assert(traces.some((trace) => { + if (trace.pid !== proc.pid) + return false; + if (trace.cat !== 'node,node.fs,node.fs.sync') + return false; + if (trace.name !== tr) + return false; + return true; + })); +} |