OptionsNormalizer.spec.ts 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610
  1. import 'reflect-metadata';
  2. import { ServiceIdentifiers } from '../../../src/container/ServiceIdentifiers';
  3. import { assert } from 'chai';
  4. import { TInputOptions } from '../../../src/types/options/TInputOptions';
  5. import { IInversifyContainerFacade } from '../../../src/interfaces/container/IInversifyContainerFacade';
  6. import { IOptions } from '../../../src/interfaces/options/IOptions';
  7. import { IOptionsNormalizer } from '../../../src/interfaces/options/IOptionsNormalizer';
  8. import { StringArrayEncoding } from '../../../src/enums/node-transformers/string-array-transformers/StringArrayEncoding';
  9. import { DEFAULT_PRESET } from '../../../src/options/presets/Default';
  10. import { InversifyContainerFacade } from '../../../src/container/InversifyContainerFacade';
  11. /**
  12. * @param optionsPreset
  13. * @returns {IOptions}
  14. */
  15. function getNormalizedOptions (optionsPreset: TInputOptions): TInputOptions {
  16. const inversifyContainerFacade: IInversifyContainerFacade = new InversifyContainerFacade();
  17. inversifyContainerFacade.load('', '', optionsPreset);
  18. const options: IOptions = inversifyContainerFacade
  19. .get<IOptions>(ServiceIdentifiers.IOptions);
  20. const optionsNormalizer: IOptionsNormalizer = inversifyContainerFacade
  21. .get<IOptionsNormalizer>(ServiceIdentifiers.IOptionsNormalizer);
  22. return <TInputOptions>optionsNormalizer.normalize(options);
  23. }
  24. function getDefaultOptions(): TInputOptions {
  25. return {
  26. ...DEFAULT_PRESET,
  27. seed: 1 // set `seed` to the fixed value, to prevent a new seed for the each case
  28. };
  29. }
  30. describe('OptionsNormalizer', () => {
  31. describe('normalize', () => {
  32. let optionsPreset: TInputOptions,
  33. expectedOptionsPreset: TInputOptions;
  34. describe('controlFlowFlatteningThresholdRule', () => {
  35. before(() => {
  36. optionsPreset = getNormalizedOptions({
  37. ...getDefaultOptions(),
  38. controlFlowFlattening: true,
  39. controlFlowFlatteningThreshold: 0
  40. });
  41. expectedOptionsPreset = {
  42. ...getDefaultOptions(),
  43. controlFlowFlattening: false,
  44. controlFlowFlatteningThreshold: 0
  45. };
  46. });
  47. it('should normalize options preset', () => {
  48. assert.deepEqual(optionsPreset, expectedOptionsPreset);
  49. });
  50. });
  51. describe('deadCodeInjectionRule', () => {
  52. before(() => {
  53. optionsPreset = getNormalizedOptions({
  54. ...getDefaultOptions(),
  55. deadCodeInjection: true,
  56. deadCodeInjectionThreshold: 0.4,
  57. stringArray: false,
  58. stringArrayThreshold: 0
  59. });
  60. expectedOptionsPreset = {
  61. ...getDefaultOptions(),
  62. deadCodeInjection: true,
  63. deadCodeInjectionThreshold: 0.4,
  64. stringArray: true,
  65. stringArrayThreshold: 0.75
  66. };
  67. });
  68. it('should normalize options preset', () => {
  69. assert.deepEqual(optionsPreset, expectedOptionsPreset);
  70. });
  71. });
  72. describe('deadCodeInjectionRule', () => {
  73. describe('`stringArrayThreshold` option is empty', () => {
  74. before(() => {
  75. optionsPreset = getNormalizedOptions({
  76. ...getDefaultOptions(),
  77. deadCodeInjection: true,
  78. deadCodeInjectionThreshold: 0.4,
  79. stringArray: false,
  80. stringArrayThreshold: 0
  81. });
  82. expectedOptionsPreset = {
  83. ...getDefaultOptions(),
  84. deadCodeInjection: true,
  85. deadCodeInjectionThreshold: 0.4,
  86. stringArray: true,
  87. stringArrayThreshold: 0.75
  88. };
  89. });
  90. it('should normalize options preset', () => {
  91. assert.deepEqual(optionsPreset, expectedOptionsPreset);
  92. });
  93. });
  94. describe('`stringArrayThreshold` option is not empty', () => {
  95. before(() => {
  96. optionsPreset = getNormalizedOptions({
  97. ...getDefaultOptions(),
  98. deadCodeInjection: true,
  99. deadCodeInjectionThreshold: 0.4,
  100. stringArray: false,
  101. stringArrayThreshold: 0.5
  102. });
  103. expectedOptionsPreset = {
  104. ...getDefaultOptions(),
  105. deadCodeInjection: true,
  106. deadCodeInjectionThreshold: 0.4,
  107. stringArray: true,
  108. stringArrayThreshold: 0.5
  109. };
  110. });
  111. it('should normalize options preset', () => {
  112. assert.deepEqual(optionsPreset, expectedOptionsPreset);
  113. });
  114. });
  115. });
  116. describe('deadCodeInjectionThresholdRule', () => {
  117. before(() => {
  118. optionsPreset = getNormalizedOptions({
  119. ...getDefaultOptions(),
  120. deadCodeInjection: true,
  121. deadCodeInjectionThreshold: 0
  122. });
  123. expectedOptionsPreset = {
  124. ...getDefaultOptions(),
  125. deadCodeInjection: false,
  126. deadCodeInjectionThreshold: 0
  127. };
  128. });
  129. it('should normalize options preset', () => {
  130. assert.deepEqual(optionsPreset, expectedOptionsPreset);
  131. });
  132. });
  133. describe('domainLockRule', () => {
  134. before(() => {
  135. optionsPreset = getNormalizedOptions({
  136. ...getDefaultOptions(),
  137. domainLock: [
  138. '//localhost:9000',
  139. 'https://google.ru/abc?cde=fgh'
  140. ]
  141. });
  142. expectedOptionsPreset = {
  143. ...getDefaultOptions(),
  144. domainLock: [
  145. 'localhost',
  146. 'google.ru'
  147. ]
  148. };
  149. });
  150. it('should normalize options preset', () => {
  151. assert.deepEqual(optionsPreset, expectedOptionsPreset);
  152. });
  153. });
  154. describe('inputFileNameRule', () => {
  155. describe('Variant #1: extension isn\'t set', () => {
  156. before(() => {
  157. optionsPreset = getNormalizedOptions({
  158. ...getDefaultOptions(),
  159. inputFileName: 'foo'
  160. });
  161. expectedOptionsPreset = {
  162. ...getDefaultOptions(),
  163. inputFileName: 'foo.js'
  164. };
  165. });
  166. it('should normalize options preset', () => {
  167. assert.deepEqual(optionsPreset, expectedOptionsPreset);
  168. });
  169. });
  170. describe('Variant #2: extension is set', () => {
  171. before(() => {
  172. optionsPreset = getNormalizedOptions({
  173. ...getDefaultOptions(),
  174. inputFileName: 'foo.js'
  175. });
  176. expectedOptionsPreset = {
  177. ...getDefaultOptions(),
  178. inputFileName: 'foo.js'
  179. };
  180. });
  181. it('should normalize options preset', () => {
  182. assert.deepEqual(optionsPreset, expectedOptionsPreset);
  183. });
  184. });
  185. describe('Variant #3: extension in set with `.map` postfix', () => {
  186. before(() => {
  187. optionsPreset = getNormalizedOptions({
  188. ...getDefaultOptions(),
  189. inputFileName: 'foo.map.js'
  190. });
  191. expectedOptionsPreset = {
  192. ...getDefaultOptions(),
  193. inputFileName: 'foo.map.js'
  194. };
  195. });
  196. it('should normalize options preset', () => {
  197. assert.deepEqual(optionsPreset, expectedOptionsPreset);
  198. });
  199. });
  200. describe('Variant #4: no file name', () => {
  201. before(() => {
  202. optionsPreset = getNormalizedOptions({
  203. ...getDefaultOptions(),
  204. inputFileName: ''
  205. });
  206. expectedOptionsPreset = {
  207. ...getDefaultOptions(),
  208. inputFileName: ''
  209. };
  210. });
  211. it('should normalize options preset', () => {
  212. assert.deepEqual(optionsPreset, expectedOptionsPreset);
  213. });
  214. });
  215. });
  216. describe('seedRule', () => {
  217. describe('Variant #1: seed value is string', () => {
  218. before(() => {
  219. optionsPreset = getNormalizedOptions({
  220. ...getDefaultOptions(),
  221. seed: 'abc'
  222. });
  223. expectedOptionsPreset = {
  224. ...getDefaultOptions(),
  225. seed: 'abc'
  226. };
  227. });
  228. it('should not normalize options preset', () => {
  229. assert.deepEqual(optionsPreset, expectedOptionsPreset);
  230. });
  231. });
  232. describe('Variant #2: seed value is number', () => {
  233. before(() => {
  234. optionsPreset = getNormalizedOptions({
  235. ...getDefaultOptions(),
  236. seed: 123
  237. });
  238. expectedOptionsPreset = {
  239. ...getDefaultOptions(),
  240. seed: 123
  241. };
  242. });
  243. it('should normalize options preset', () => {
  244. assert.deepEqual(optionsPreset, expectedOptionsPreset);
  245. });
  246. });
  247. describe('Variant #3: seed value is `0``', () => {
  248. let seedValue: number;
  249. before(() => {
  250. optionsPreset = getNormalizedOptions({
  251. ...getDefaultOptions(),
  252. seed: 0
  253. });
  254. seedValue = Number(optionsPreset.seed);
  255. });
  256. it('should normalize seed value', () => {
  257. assert.isAtLeast(seedValue, 0);
  258. assert.isBelow(seedValue, 999_999_999);
  259. });
  260. });
  261. });
  262. describe('selfDefendingRule', () => {
  263. before(() => {
  264. optionsPreset = getNormalizedOptions({
  265. ...getDefaultOptions(),
  266. selfDefending: true,
  267. compact: false
  268. });
  269. expectedOptionsPreset = {
  270. ...getDefaultOptions(),
  271. selfDefending: true,
  272. compact: true
  273. };
  274. });
  275. it('should normalize options preset', () => {
  276. assert.deepEqual(optionsPreset, expectedOptionsPreset);
  277. });
  278. });
  279. describe('sourceMapBaseUrlRule', () => {
  280. describe('Variant #1: only source map base url', () => {
  281. before(() => {
  282. optionsPreset = getNormalizedOptions({
  283. ...getDefaultOptions(),
  284. sourceMapBaseUrl: 'http://localhost:9000',
  285. });
  286. expectedOptionsPreset = {
  287. ...getDefaultOptions(),
  288. sourceMapBaseUrl: ''
  289. };
  290. });
  291. it('should normalize options preset', () => {
  292. assert.deepEqual(optionsPreset, expectedOptionsPreset);
  293. });
  294. });
  295. describe('Variant #2: source map base url with source map file name', () => {
  296. before(() => {
  297. optionsPreset = getNormalizedOptions({
  298. ...getDefaultOptions(),
  299. sourceMapBaseUrl: 'http://localhost:9000',
  300. sourceMapFileName: '/outputSourceMapName.map'
  301. });
  302. expectedOptionsPreset = {
  303. ...getDefaultOptions(),
  304. sourceMapBaseUrl: 'http://localhost:9000/',
  305. sourceMapFileName: 'outputSourceMapName.js.map'
  306. };
  307. });
  308. it('should normalize options preset', () => {
  309. assert.deepEqual(optionsPreset, expectedOptionsPreset);
  310. });
  311. });
  312. });
  313. describe('sourceMapFileNameRule', () => {
  314. describe('Base filename without extension', () => {
  315. before(() => {
  316. optionsPreset = getNormalizedOptions({
  317. ...getDefaultOptions(),
  318. sourceMapBaseUrl: 'http://localhost:9000',
  319. sourceMapFileName: 'outputSourceMapName'
  320. });
  321. expectedOptionsPreset = {
  322. ...getDefaultOptions(),
  323. sourceMapBaseUrl: 'http://localhost:9000/',
  324. sourceMapFileName: 'outputSourceMapName.js.map'
  325. };
  326. });
  327. it('should normalize options preset', () => {
  328. assert.deepEqual(optionsPreset, expectedOptionsPreset);
  329. });
  330. });
  331. describe('Slashes in file name', () => {
  332. before(() => {
  333. optionsPreset = getNormalizedOptions({
  334. ...getDefaultOptions(),
  335. sourceMapBaseUrl: 'http://localhost:9000',
  336. sourceMapFileName: '//outputSourceMapName'
  337. });
  338. expectedOptionsPreset = {
  339. ...getDefaultOptions(),
  340. sourceMapBaseUrl: 'http://localhost:9000/',
  341. sourceMapFileName: 'outputSourceMapName.js.map'
  342. };
  343. });
  344. it('should normalize options preset', () => {
  345. assert.deepEqual(optionsPreset, expectedOptionsPreset);
  346. });
  347. });
  348. describe('`js` file extension in file name', () => {
  349. before(() => {
  350. optionsPreset = getNormalizedOptions({
  351. ...getDefaultOptions(),
  352. sourceMapBaseUrl: 'http://localhost:9000',
  353. sourceMapFileName: 'outputSourceMapName.js'
  354. });
  355. expectedOptionsPreset = {
  356. ...getDefaultOptions(),
  357. sourceMapBaseUrl: 'http://localhost:9000/',
  358. sourceMapFileName: 'outputSourceMapName.js.map'
  359. };
  360. });
  361. it('should normalize options preset', () => {
  362. assert.deepEqual(optionsPreset, expectedOptionsPreset);
  363. });
  364. });
  365. describe('Non `js` file extension in file name', () => {
  366. before(() => {
  367. optionsPreset = getNormalizedOptions({
  368. ...getDefaultOptions(),
  369. sourceMapBaseUrl: 'http://localhost:9000',
  370. sourceMapFileName: 'outputSourceMapName.exe'
  371. });
  372. expectedOptionsPreset = {
  373. ...getDefaultOptions(),
  374. sourceMapBaseUrl: 'http://localhost:9000/',
  375. sourceMapFileName: 'outputSourceMapName.js.map'
  376. };
  377. });
  378. it('should normalize options preset', () => {
  379. assert.deepEqual(optionsPreset, expectedOptionsPreset);
  380. });
  381. });
  382. describe('File hash in file name', () => {
  383. before(() => {
  384. optionsPreset = getNormalizedOptions({
  385. ...getDefaultOptions(),
  386. sourceMapBaseUrl: 'http://localhost:9000',
  387. sourceMapFileName: 'outputSourceMapName.7e2c49a622975ebd9b7e'
  388. });
  389. expectedOptionsPreset = {
  390. ...getDefaultOptions(),
  391. sourceMapBaseUrl: 'http://localhost:9000/',
  392. sourceMapFileName: 'outputSourceMapName.7e2c49a622975ebd9b7e.js.map'
  393. };
  394. });
  395. it('should normalize options preset', () => {
  396. assert.deepEqual(optionsPreset, expectedOptionsPreset);
  397. });
  398. });
  399. describe('File hash and `js` file extension in file name #1', () => {
  400. before(() => {
  401. optionsPreset = getNormalizedOptions({
  402. ...getDefaultOptions(),
  403. sourceMapBaseUrl: 'http://localhost:9000',
  404. sourceMapFileName: 'outputSourceMapName.7e2c49a622975ebd9b7e.js'
  405. });
  406. expectedOptionsPreset = {
  407. ...getDefaultOptions(),
  408. sourceMapBaseUrl: 'http://localhost:9000/',
  409. sourceMapFileName: 'outputSourceMapName.7e2c49a622975ebd9b7e.js.map'
  410. };
  411. });
  412. it('should normalize options preset', () => {
  413. assert.deepEqual(optionsPreset, expectedOptionsPreset);
  414. });
  415. });
  416. describe('File hash and non `js` file extension in file name', () => {
  417. before(() => {
  418. optionsPreset = getNormalizedOptions({
  419. ...getDefaultOptions(),
  420. sourceMapBaseUrl: 'http://localhost:9000',
  421. sourceMapFileName: 'outputSourceMapName.7e2c49a622975ebd9b7e.exe'
  422. });
  423. expectedOptionsPreset = {
  424. ...getDefaultOptions(),
  425. sourceMapBaseUrl: 'http://localhost:9000/',
  426. sourceMapFileName: 'outputSourceMapName.7e2c49a622975ebd9b7e.js.map'
  427. };
  428. });
  429. it('should normalize options preset', () => {
  430. assert.deepEqual(optionsPreset, expectedOptionsPreset);
  431. });
  432. });
  433. });
  434. describe('splitStringsChunkLengthRule', () => {
  435. describe('`splitStringsChunkLengthRule` value is float number', () => {
  436. before(() => {
  437. optionsPreset = getNormalizedOptions({
  438. ...getDefaultOptions(),
  439. splitStrings: true,
  440. splitStringsChunkLength: 5.6
  441. });
  442. expectedOptionsPreset = {
  443. ...getDefaultOptions(),
  444. splitStrings: true,
  445. splitStringsChunkLength: 5
  446. };
  447. });
  448. it('should normalize options preset', () => {
  449. assert.deepEqual(optionsPreset, expectedOptionsPreset);
  450. });
  451. });
  452. });
  453. describe('stringArrayRule', () => {
  454. before(() => {
  455. optionsPreset = getNormalizedOptions({
  456. ...getDefaultOptions(),
  457. shuffleStringArray: true,
  458. stringArray: false,
  459. stringArrayEncoding: [StringArrayEncoding.Rc4],
  460. stringArrayWrappersChainedCalls: true,
  461. stringArrayWrappersCount: 5,
  462. stringArrayThreshold: 0.5,
  463. rotateStringArray: true
  464. });
  465. expectedOptionsPreset = {
  466. ...getDefaultOptions(),
  467. shuffleStringArray: false,
  468. stringArray: false,
  469. stringArrayEncoding: [StringArrayEncoding.None],
  470. stringArrayWrappersChainedCalls: false,
  471. stringArrayWrappersCount: 0,
  472. stringArrayThreshold: 0,
  473. rotateStringArray: false
  474. };
  475. });
  476. it('should normalize options preset', () => {
  477. assert.deepEqual(optionsPreset, expectedOptionsPreset);
  478. });
  479. });
  480. describe('stringArrayEncodingRule', () => {
  481. before(() => {
  482. optionsPreset = getNormalizedOptions({
  483. ...getDefaultOptions(),
  484. stringArrayEncoding: []
  485. });
  486. expectedOptionsPreset = {
  487. ...getDefaultOptions(),
  488. stringArrayEncoding: [
  489. StringArrayEncoding.None
  490. ]
  491. };
  492. });
  493. it('should normalize options preset', () => {
  494. assert.deepEqual(optionsPreset, expectedOptionsPreset);
  495. });
  496. });
  497. describe('stringArrayWrappersChainedCallsRule', () => {
  498. before(() => {
  499. optionsPreset = getNormalizedOptions({
  500. ...getDefaultOptions(),
  501. stringArrayWrappersChainedCalls: true,
  502. stringArrayWrappersCount: 0
  503. });
  504. expectedOptionsPreset = {
  505. ...getDefaultOptions(),
  506. stringArrayWrappersChainedCalls: false,
  507. stringArrayWrappersCount: 0
  508. };
  509. });
  510. it('should normalize options preset', () => {
  511. assert.deepEqual(optionsPreset, expectedOptionsPreset);
  512. });
  513. });
  514. });
  515. });