1// Copyright Joyent, Inc. and other Node contributors. 2// 3// Permission is hereby granted, free of charge, to any person obtaining a 4// copy of this software and associated documentation files (the 5// "Software"), to deal in the Software without restriction, including 6// without limitation the rights to use, copy, modify, merge, publish, 7// distribute, sublicense, and/or sell copies of the Software, and to permit 8// persons to whom the Software is furnished to do so, subject to the 9// following conditions: 10// 11// The above copyright notice and this permission notice shall be included 12// in all copies or substantial portions of the Software. 13// 14// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 17// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 18// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 19// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 20// USE OR OTHER DEALINGS IN THE SOFTWARE. 21 22// Flags: --expose_externalize_string 23'use strict'; 24const common = require('../common'); 25const assert = require('assert'); 26const path = require('path'); 27const fs = require('fs'); 28const tmpdir = require('../common/tmpdir'); 29 30tmpdir.refresh(); 31 32const fn = path.join(tmpdir.path, 'write.txt'); 33const fn2 = path.join(tmpdir.path, 'write2.txt'); 34const fn3 = path.join(tmpdir.path, 'write3.txt'); 35const fn4 = path.join(tmpdir.path, 'write4.txt'); 36const expected = 'ümlaut.'; 37const constants = fs.constants; 38 39const { externalizeString, isOneByteString } = global; 40 41// Account for extra globals exposed by --expose_externalize_string. 42common.allowGlobals(externalizeString, isOneByteString, global.x); 43 44{ 45 const expected = 'ümlaut sechzig'; // Must be a unique string. 46 externalizeString(expected); 47 assert.strictEqual(isOneByteString(expected), true); 48 const fd = fs.openSync(fn, 'w'); 49 fs.writeSync(fd, expected, 0, 'latin1'); 50 fs.closeSync(fd); 51 assert.strictEqual(fs.readFileSync(fn, 'latin1'), expected); 52} 53 54{ 55 const expected = 'ümlaut neunzig'; // Must be a unique string. 56 externalizeString(expected); 57 assert.strictEqual(isOneByteString(expected), true); 58 const fd = fs.openSync(fn, 'w'); 59 fs.writeSync(fd, expected, 0, 'utf8'); 60 fs.closeSync(fd); 61 assert.strictEqual(fs.readFileSync(fn, 'utf8'), expected); 62} 63 64{ 65 const expected = 'Zhōngwén 1'; // Must be a unique string. 66 externalizeString(expected); 67 assert.strictEqual(isOneByteString(expected), false); 68 const fd = fs.openSync(fn, 'w'); 69 fs.writeSync(fd, expected, 0, 'ucs2'); 70 fs.closeSync(fd); 71 assert.strictEqual(fs.readFileSync(fn, 'ucs2'), expected); 72} 73 74{ 75 const expected = 'Zhōngwén 2'; // Must be a unique string. 76 externalizeString(expected); 77 assert.strictEqual(isOneByteString(expected), false); 78 const fd = fs.openSync(fn, 'w'); 79 fs.writeSync(fd, expected, 0, 'utf8'); 80 fs.closeSync(fd); 81 assert.strictEqual(fs.readFileSync(fn, 'utf8'), expected); 82} 83 84fs.open(fn, 'w', 0o644, common.mustSucceed((fd) => { 85 const done = common.mustSucceed((written) => { 86 assert.strictEqual(written, Buffer.byteLength(expected)); 87 fs.closeSync(fd); 88 const found = fs.readFileSync(fn, 'utf8'); 89 fs.unlinkSync(fn); 90 assert.strictEqual(found, expected); 91 }); 92 93 const written = common.mustSucceed((written) => { 94 assert.strictEqual(written, 0); 95 fs.write(fd, expected, 0, 'utf8', done); 96 }); 97 98 fs.write(fd, '', 0, 'utf8', written); 99})); 100 101const args = constants.O_CREAT | constants.O_WRONLY | constants.O_TRUNC; 102fs.open(fn2, args, 0o644, common.mustSucceed((fd) => { 103 const done = common.mustSucceed((written) => { 104 assert.strictEqual(written, Buffer.byteLength(expected)); 105 fs.closeSync(fd); 106 const found = fs.readFileSync(fn2, 'utf8'); 107 fs.unlinkSync(fn2); 108 assert.strictEqual(found, expected); 109 }); 110 111 const written = common.mustSucceed((written) => { 112 assert.strictEqual(written, 0); 113 fs.write(fd, expected, 0, 'utf8', done); 114 }); 115 116 fs.write(fd, '', 0, 'utf8', written); 117})); 118 119fs.open(fn3, 'w', 0o644, common.mustSucceed((fd) => { 120 const done = common.mustSucceed((written) => { 121 assert.strictEqual(written, Buffer.byteLength(expected)); 122 fs.closeSync(fd); 123 }); 124 125 fs.write(fd, expected, done); 126})); 127 128fs.open(fn4, 'w', 0o644, common.mustSucceed((fd) => { 129 const done = common.mustSucceed((written) => { 130 assert.strictEqual(written, Buffer.byteLength(expected)); 131 fs.closeSync(fd); 132 }); 133 134 const data = { 135 toString() { return expected; } 136 }; 137 fs.write(fd, data, done); 138})); 139 140[false, 'test', {}, [], null, undefined].forEach((i) => { 141 assert.throws( 142 () => fs.write(i, common.mustNotCall()), 143 { 144 code: 'ERR_INVALID_ARG_TYPE', 145 name: 'TypeError' 146 } 147 ); 148 assert.throws( 149 () => fs.writeSync(i), 150 { 151 code: 'ERR_INVALID_ARG_TYPE', 152 name: 'TypeError' 153 } 154 ); 155}); 156 157[ 158 false, 5, {}, [], null, undefined, 159 new String('notPrimitive'), 160 { [Symbol.toPrimitive]: (hint) => 'amObject' }, 161].forEach((data) => { 162 assert.throws( 163 () => fs.write(1, data, common.mustNotCall()), 164 { 165 code: 'ERR_INVALID_ARG_TYPE', 166 message: /"buffer"/ 167 } 168 ); 169 assert.throws( 170 () => fs.writeSync(1, data), 171 { 172 code: 'ERR_INVALID_ARG_TYPE', 173 message: /"buffer"/ 174 } 175 ); 176}); 177