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'use strict'; 23const common = require('../common'); 24const assert = require('assert'); 25const path = require('path'); 26const fs = require('fs'); 27 28const tmpdir = require('../common/tmpdir'); 29 30 31const filepath = path.join(tmpdir.path, 'write_pos.txt'); 32 33 34const cb_expected = 'write open close write open close write open close '; 35let cb_occurred = ''; 36 37const fileDataInitial = 'abcdefghijklmnopqrstuvwxyz'; 38 39const fileDataExpected_1 = 'abcdefghijklmnopqrstuvwxyz'; 40const fileDataExpected_2 = 'abcdefghij123456qrstuvwxyz'; 41const fileDataExpected_3 = 'abcdefghij\u2026\u2026qrstuvwxyz'; 42 43 44process.on('exit', function() { 45 if (cb_occurred !== cb_expected) { 46 console.log(' Test callback events missing or out of order:'); 47 console.log(` expected: ${cb_expected}`); 48 console.log(` occurred: ${cb_occurred}`); 49 assert.strictEqual( 50 cb_occurred, cb_expected, 51 `events missing or out of order: "${cb_occurred}" !== "${cb_expected}"`); 52 } 53}); 54 55 56tmpdir.refresh(); 57 58 59function run_test_1() { 60 const options = {}; 61 const file = fs.createWriteStream(filepath, options); 62 console.log(' (debug: start ', file.start); 63 console.log(' (debug: pos ', file.pos); 64 65 file.on('open', function(fd) { 66 cb_occurred += 'open '; 67 }); 68 69 file.on('close', function() { 70 cb_occurred += 'close '; 71 console.log(' (debug: bytesWritten ', file.bytesWritten); 72 console.log(' (debug: start ', file.start); 73 console.log(' (debug: pos ', file.pos); 74 assert.strictEqual(file.bytesWritten, buffer.length); 75 const fileData = fs.readFileSync(filepath, 'utf8'); 76 console.log(' (debug: file data ', fileData); 77 console.log(' (debug: expected ', fileDataExpected_1); 78 assert.strictEqual(fileData, fileDataExpected_1); 79 80 run_test_2(); 81 }); 82 83 file.on('error', function(err) { 84 cb_occurred += 'error '; 85 console.log(' (debug: err event ', err); 86 throw err; 87 }); 88 89 const buffer = Buffer.from(fileDataInitial); 90 file.write(buffer); 91 cb_occurred += 'write '; 92 93 file.end(); 94} 95 96 97function run_test_2() { 98 99 const buffer = Buffer.from('123456'); 100 101 const options = { start: 10, 102 flags: 'r+' }; 103 const file = fs.createWriteStream(filepath, options); 104 console.log(' (debug: start ', file.start); 105 console.log(' (debug: pos ', file.pos); 106 107 file.on('open', function(fd) { 108 cb_occurred += 'open '; 109 }); 110 111 file.on('close', function() { 112 cb_occurred += 'close '; 113 console.log(' (debug: bytesWritten ', file.bytesWritten); 114 console.log(' (debug: start ', file.start); 115 console.log(' (debug: pos ', file.pos); 116 assert.strictEqual(file.bytesWritten, buffer.length); 117 const fileData = fs.readFileSync(filepath, 'utf8'); 118 console.log(' (debug: file data ', fileData); 119 console.log(' (debug: expected ', fileDataExpected_2); 120 assert.strictEqual(fileData, fileDataExpected_2); 121 122 run_test_3(); 123 }); 124 125 file.on('error', function(err) { 126 cb_occurred += 'error '; 127 console.log(' (debug: err event ', err); 128 throw err; 129 }); 130 131 file.write(buffer); 132 cb_occurred += 'write '; 133 134 file.end(); 135} 136 137 138function run_test_3() { 139 140 const data = '\u2026\u2026'; // 3 bytes * 2 = 6 bytes in UTF-8 141 142 const options = { start: 10, 143 flags: 'r+' }; 144 const file = fs.createWriteStream(filepath, options); 145 console.log(' (debug: start ', file.start); 146 console.log(' (debug: pos ', file.pos); 147 148 file.on('open', function(fd) { 149 cb_occurred += 'open '; 150 }); 151 152 file.on('close', function() { 153 cb_occurred += 'close '; 154 console.log(' (debug: bytesWritten ', file.bytesWritten); 155 console.log(' (debug: start ', file.start); 156 console.log(' (debug: pos ', file.pos); 157 assert.strictEqual(file.bytesWritten, data.length * 3); 158 const fileData = fs.readFileSync(filepath, 'utf8'); 159 console.log(' (debug: file data ', fileData); 160 console.log(' (debug: expected ', fileDataExpected_3); 161 assert.strictEqual(fileData, fileDataExpected_3); 162 163 run_test_4(); 164 run_test_5(); 165 }); 166 167 file.on('error', function(err) { 168 cb_occurred += 'error '; 169 console.log(' (debug: err event ', err); 170 throw err; 171 }); 172 173 file.write(data, 'utf8'); 174 cb_occurred += 'write '; 175 176 file.end(); 177} 178 179 180const run_test_4 = common.mustCall(function() { 181 // Error: start must be >= zero 182 const fn = () => { 183 fs.createWriteStream(filepath, { start: -5, flags: 'r+' }); 184 }; 185 // Verify the range of values using a common integer verifier. 186 // Limit Number.MAX_SAFE_INTEGER 187 const err = { 188 code: 'ERR_OUT_OF_RANGE', 189 message: 'The value of "start" is out of range. ' + 190 `It must be >= 0 && <= ${Number.MAX_SAFE_INTEGER}. Received -5`, 191 name: 'RangeError' 192 }; 193 assert.throws(fn, err); 194}); 195 196 197const run_test_5 = common.mustCall(function() { 198 // Error: start must be <= 2 ** 53 - 1 199 const fn = () => { 200 fs.createWriteStream(filepath, { start: 2 ** 53, flags: 'r+' }); 201 }; 202 // Verify the range of values using a common integer verifier. 203 // Limit Number.MAX_SAFE_INTEGER 204 const err = { 205 code: 'ERR_OUT_OF_RANGE', 206 message: 'The value of "start" is out of range. It must be ' + 207 `>= 0 && <= ${Number.MAX_SAFE_INTEGER}. ` + 208 'Received 9_007_199_254_740_992', 209 name: 'RangeError' 210 }; 211 assert.throws(fn, err); 212}); 213 214run_test_1(); 215