1/* 2 * Copyright (c) 2024 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16import { describe, it } from 'mocha'; 17import { expect } from 'chai'; 18import sinon from 'sinon'; 19import proxyquire from 'proxyquire'; 20import { constants } from 'fs'; 21 22import { IOptions } from '../../../src/configs/IOptions'; 23 24const fsStub = { 25 existsSync: sinon.stub(), 26 accessSync: sinon.stub(), 27}; 28 29const fsExtraStub = { 30 readJsonSync: sinon.stub() 31}; 32 33const { FileUtils, IOptions } = proxyquire('../../../src/utils/FileUtils', { 34 'fs': fsStub, 35 'fs-extra': fsExtraStub 36}); 37 38describe('FileUtils.readFileAsJson', () => { 39 let consoleErrorStub:sinon.SinonStub; 40 beforeEach(() => { 41 consoleErrorStub = sinon.stub(console, 'error'); 42 }); 43 44 afterEach(() => { 45 sinon.restore(); 46 }); 47 48 it('should return undefined if file does not exist', () => { 49 fsStub.existsSync.returns(false); 50 const result = FileUtils.readFileAsJson('fakePath.json'); 51 expect(result).to.be.undefined; 52 expect(consoleErrorStub.calledWith('File <fakePath.json> is not found.')).to.be.true; 53 }); 54 55 it('should return undefined if readJsonSync throws an error', () => { 56 fsStub.existsSync.returns(true); 57 fsExtraStub.readJsonSync.throws(new Error('read error')); 58 const result = FileUtils.readFileAsJson('fakePath.json'); 59 expect(result).to.be.undefined; 60 expect(consoleErrorStub.calledWith('json file read error: fakePath.json')).to.be.true; 61 }); 62 63 it('should return JSON content if file exists and is valid', () => { 64 const jsonContent: IOptions = { mCompact: true }; 65 fsStub.existsSync.returns(true); 66 fsExtraStub.readJsonSync.returns(jsonContent); 67 const result = FileUtils.readFileAsJson('validPath.json'); 68 expect(result).to.deep.equal(jsonContent); 69 }); 70}); 71 72describe('FileUtils.getFileExtension', () => { 73 it('should return undefined for empty string', () => { 74 const result = FileUtils.getFileExtension(''); 75 expect(result).to.be.undefined; 76 }); 77 78 it('should return undefined for string without dot', () => { 79 const result = FileUtils.getFileExtension('filename'); 80 expect(result).to.be.undefined; 81 }); 82 83 it('should return undefined for path string without dot', () => { 84 const result = FileUtils.getFileExtension('path/to.test/filename'); 85 expect(result).to.be.undefined; 86 }); 87 88 it('should return undefined for string ending with a dot', () => { 89 const result = FileUtils.getFileExtension('filename.'); 90 expect(result).to.equal(''); 91 }); 92 93 it('should return extension for valid file path', () => { 94 const result = FileUtils.getFileExtension('/path/to/file.txt'); 95 expect(result).to.equal('txt'); 96 }); 97 98 it('should return extension for valid file name with multiple dots', () => { 99 const result = FileUtils.getFileExtension('/path/to/file.name.with.dots.txt'); 100 expect(result).to.equal('txt'); 101 }); 102}); 103 104describe('FileUtils.isRelativePath', () => { 105 it('should return true for relative paths starting with ./', () => { 106 const result = FileUtils.isRelativePath('./file.txt'); 107 expect(result).to.be.true; 108 }); 109 110 it('should return true for relative paths starting with ../', () => { 111 const result = FileUtils.isRelativePath('../file.txt'); 112 expect(result).to.be.true; 113 }); 114 115 it('should return true for relative paths starting with .\\', () => { 116 const result = FileUtils.isRelativePath('.\\file.txt'); 117 expect(result).to.be.true; 118 }); 119 120 it('should return true for relative paths starting with ..\\', () => { 121 const result = FileUtils.isRelativePath('..\\file.txt'); 122 expect(result).to.be.true; 123 }); 124 125 it('should return false for absolute paths', () => { 126 const result = FileUtils.isRelativePath('/absolute/path/to/file.txt'); 127 expect(result).to.be.false; 128 }); 129 130 it('should return false for Windows absolute paths', () => { 131 const result = FileUtils.isRelativePath('C:\\absolute\\path\\to\\file.txt'); 132 expect(result).to.be.false; 133 }); 134}); 135 136describe('FileUtils.isReadableFile', () => { 137 afterEach(() => { 138 sinon.restore(); 139 }); 140 141 it('should return true if file is readable', () => { 142 fsStub.accessSync.withArgs('readableFile.txt', constants.R_OK).returns(undefined); 143 const result = FileUtils.isReadableFile('readableFile.txt'); 144 expect(result).to.be.true; 145 }); 146 147 it('should return false if file is not readable', () => { 148 fsStub.accessSync.withArgs('unreadableFile.txt', constants.R_OK).throws(new Error('Not readable')); 149 const result = FileUtils.isReadableFile('unreadableFile.txt'); 150 expect(result).to.be.false; 151 }); 152}); 153 154describe('FileUtils.toUnixPath', () => { 155 let osStub: sinon.SinonStub; 156 let pathStub: sinon.SinonStub; 157 158 beforeEach(() => { 159 osStub = sinon.stub(require('os'), 'platform'); 160 pathStub = sinon.stub(require('path'), 'sep').value('/'); // Default to Unix-like separator 161 }); 162 163 afterEach(() => { 164 sinon.restore(); 165 }); 166 167 it('should convert Windows path to Unix path', () => { 168 osStub.returns('win32'); 169 const proxyquireUtils = proxyquire('../../../src/utils/FileUtils', { 170 'os': { 171 platform: osStub 172 }, 173 'path': { 174 sep: '\\', 175 posix: { 176 join: (...paths: string[]) => paths.join('/') 177 } 178 } 179 }); 180 const result = proxyquireUtils.FileUtils.toUnixPath('C:\\path\\to\\file.txt'); 181 expect(result).to.equal('C:/path/to/file.txt'); 182 }); 183 184 it('should return Unix path unchanged', () => { 185 osStub.returns('linux'); 186 const result = FileUtils.toUnixPath('/path/to/file.txt'); 187 expect(result).to.equal('/path/to/file.txt'); 188 }); 189}); 190 191describe('FileUtils.getAbsPathBaseConfigPath', () => { 192 it('should return absolute path', () => { 193 expect(FileUtils.getAbsPathBaseConfigPath('/abs/path/abc', 'file.txt')).to.equal('/abs/path/file.txt') 194 }); 195 196 // Return non-absolute path? May need to be fixed. 197 it('should return non-absolute path', () => { 198 expect(FileUtils.getAbsPathBaseConfigPath('not_abs/path/abc', 'file.txt')).to.equal('not_abs/path/file.txt') 199 }); 200 201 it('should handle empty paths', () => { 202 expect(FileUtils.getAbsPathBaseConfigPath('', '')).to.equal('.') 203 }); 204});