evaluator_spec.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. /* Copyright 2017 Mozilla Foundation
  2. *
  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. 'use strict';
  16. var _primitives = require('../../core/primitives');
  17. var _evaluator = require('../../core/evaluator');
  18. var _stream = require('../../core/stream');
  19. var _util = require('../../shared/util');
  20. var _worker = require('../../core/worker');
  21. describe('evaluator', function () {
  22. function XrefMock(queue) {
  23. this.queue = queue || [];
  24. }
  25. XrefMock.prototype = {
  26. fetchIfRef: function fetchIfRef() {
  27. return this.queue.shift();
  28. }
  29. };
  30. function HandlerMock() {
  31. this.inputs = [];
  32. }
  33. HandlerMock.prototype = {
  34. send: function send(name, data) {
  35. this.inputs.push({
  36. name: name,
  37. data: data
  38. });
  39. }
  40. };
  41. function ResourcesMock() {}
  42. ResourcesMock.prototype = {
  43. get: function get(name) {
  44. return this[name];
  45. }
  46. };
  47. function PdfManagerMock() {}
  48. function runOperatorListCheck(evaluator, stream, resources, callback) {
  49. var result = new _evaluator.OperatorList();
  50. var task = new _worker.WorkerTask('OperatorListCheck');
  51. evaluator.getOperatorList(stream, task, resources, result).then(function () {
  52. callback(result);
  53. });
  54. }
  55. describe('splitCombinedOperations', function () {
  56. it('should reject unknown operations', function (done) {
  57. var evaluator = new _evaluator.PartialEvaluator(new PdfManagerMock(), new XrefMock(), new HandlerMock(), 'prefix');
  58. var stream = new _stream.StringStream('fTT');
  59. runOperatorListCheck(evaluator, stream, new ResourcesMock(), function (result) {
  60. expect(!!result.fnArray && !!result.argsArray).toEqual(true);
  61. expect(result.fnArray.length).toEqual(1);
  62. expect(result.fnArray[0]).toEqual(_util.OPS.fill);
  63. expect(result.argsArray[0]).toEqual(null);
  64. done();
  65. });
  66. });
  67. it('should handle one operations', function (done) {
  68. var evaluator = new _evaluator.PartialEvaluator(new PdfManagerMock(), new XrefMock(), new HandlerMock(), 'prefix');
  69. var stream = new _stream.StringStream('Q');
  70. runOperatorListCheck(evaluator, stream, new ResourcesMock(), function (result) {
  71. expect(!!result.fnArray && !!result.argsArray).toEqual(true);
  72. expect(result.fnArray.length).toEqual(1);
  73. expect(result.fnArray[0]).toEqual(_util.OPS.restore);
  74. done();
  75. });
  76. });
  77. it('should handle two glued operations', function (done) {
  78. var evaluator = new _evaluator.PartialEvaluator(new PdfManagerMock(), new XrefMock(), new HandlerMock(), 'prefix');
  79. var resources = new ResourcesMock();
  80. resources.Res1 = {};
  81. var stream = new _stream.StringStream('/Res1 DoQ');
  82. runOperatorListCheck(evaluator, stream, resources, function (result) {
  83. expect(!!result.fnArray && !!result.argsArray).toEqual(true);
  84. expect(result.fnArray.length).toEqual(2);
  85. expect(result.fnArray[0]).toEqual(_util.OPS.paintXObject);
  86. expect(result.fnArray[1]).toEqual(_util.OPS.restore);
  87. done();
  88. });
  89. });
  90. it('should handle tree glued operations', function (done) {
  91. var evaluator = new _evaluator.PartialEvaluator(new PdfManagerMock(), new XrefMock(), new HandlerMock(), 'prefix');
  92. var stream = new _stream.StringStream('fff');
  93. runOperatorListCheck(evaluator, stream, new ResourcesMock(), function (result) {
  94. expect(!!result.fnArray && !!result.argsArray).toEqual(true);
  95. expect(result.fnArray.length).toEqual(3);
  96. expect(result.fnArray[0]).toEqual(_util.OPS.fill);
  97. expect(result.fnArray[1]).toEqual(_util.OPS.fill);
  98. expect(result.fnArray[2]).toEqual(_util.OPS.fill);
  99. done();
  100. });
  101. });
  102. it('should handle three glued operations #2', function (done) {
  103. var evaluator = new _evaluator.PartialEvaluator(new PdfManagerMock(), new XrefMock(), new HandlerMock(), 'prefix');
  104. var resources = new ResourcesMock();
  105. resources.Res1 = {};
  106. var stream = new _stream.StringStream('B*Bf*');
  107. runOperatorListCheck(evaluator, stream, resources, function (result) {
  108. expect(!!result.fnArray && !!result.argsArray).toEqual(true);
  109. expect(result.fnArray.length).toEqual(3);
  110. expect(result.fnArray[0]).toEqual(_util.OPS.eoFillStroke);
  111. expect(result.fnArray[1]).toEqual(_util.OPS.fillStroke);
  112. expect(result.fnArray[2]).toEqual(_util.OPS.eoFill);
  113. done();
  114. });
  115. });
  116. it('should handle glued operations and operands', function (done) {
  117. var evaluator = new _evaluator.PartialEvaluator(new PdfManagerMock(), new XrefMock(), new HandlerMock(), 'prefix');
  118. var stream = new _stream.StringStream('f5 Ts');
  119. runOperatorListCheck(evaluator, stream, new ResourcesMock(), function (result) {
  120. expect(!!result.fnArray && !!result.argsArray).toEqual(true);
  121. expect(result.fnArray.length).toEqual(2);
  122. expect(result.fnArray[0]).toEqual(_util.OPS.fill);
  123. expect(result.fnArray[1]).toEqual(_util.OPS.setTextRise);
  124. expect(result.argsArray.length).toEqual(2);
  125. expect(result.argsArray[1].length).toEqual(1);
  126. expect(result.argsArray[1][0]).toEqual(5);
  127. done();
  128. });
  129. });
  130. it('should handle glued operations and literals', function (done) {
  131. var evaluator = new _evaluator.PartialEvaluator(new PdfManagerMock(), new XrefMock(), new HandlerMock(), 'prefix');
  132. var stream = new _stream.StringStream('trueifalserinulln');
  133. runOperatorListCheck(evaluator, stream, new ResourcesMock(), function (result) {
  134. expect(!!result.fnArray && !!result.argsArray).toEqual(true);
  135. expect(result.fnArray.length).toEqual(3);
  136. expect(result.fnArray[0]).toEqual(_util.OPS.setFlatness);
  137. expect(result.fnArray[1]).toEqual(_util.OPS.setRenderingIntent);
  138. expect(result.fnArray[2]).toEqual(_util.OPS.endPath);
  139. expect(result.argsArray.length).toEqual(3);
  140. expect(result.argsArray[0].length).toEqual(1);
  141. expect(result.argsArray[0][0]).toEqual(true);
  142. expect(result.argsArray[1].length).toEqual(1);
  143. expect(result.argsArray[1][0]).toEqual(false);
  144. expect(result.argsArray[2]).toEqual(null);
  145. done();
  146. });
  147. });
  148. });
  149. describe('validateNumberOfArgs', function () {
  150. it('should execute if correct number of arguments', function (done) {
  151. var evaluator = new _evaluator.PartialEvaluator(new PdfManagerMock(), new XrefMock(), new HandlerMock(), 'prefix');
  152. var stream = new _stream.StringStream('5 1 d0');
  153. runOperatorListCheck(evaluator, stream, new ResourcesMock(), function (result) {
  154. expect(result.argsArray[0][0]).toEqual(5);
  155. expect(result.argsArray[0][1]).toEqual(1);
  156. expect(result.fnArray[0]).toEqual(_util.OPS.setCharWidth);
  157. done();
  158. });
  159. });
  160. it('should execute if too many arguments', function (done) {
  161. var evaluator = new _evaluator.PartialEvaluator(new PdfManagerMock(), new XrefMock(), new HandlerMock(), 'prefix');
  162. var stream = new _stream.StringStream('5 1 4 d0');
  163. runOperatorListCheck(evaluator, stream, new ResourcesMock(), function (result) {
  164. expect(result.argsArray[0][0]).toEqual(1);
  165. expect(result.argsArray[0][1]).toEqual(4);
  166. expect(result.fnArray[0]).toEqual(_util.OPS.setCharWidth);
  167. done();
  168. });
  169. });
  170. it('should execute if nested commands', function (done) {
  171. var evaluator = new _evaluator.PartialEvaluator(new PdfManagerMock(), new XrefMock(), new HandlerMock(), 'prefix');
  172. var stream = new _stream.StringStream('/F2 /GS2 gs 5.711 Tf');
  173. runOperatorListCheck(evaluator, stream, new ResourcesMock(), function (result) {
  174. expect(result.fnArray.length).toEqual(3);
  175. expect(result.fnArray[0]).toEqual(_util.OPS.setGState);
  176. expect(result.fnArray[1]).toEqual(_util.OPS.dependency);
  177. expect(result.fnArray[2]).toEqual(_util.OPS.setFont);
  178. expect(result.argsArray.length).toEqual(3);
  179. expect(result.argsArray[0].length).toEqual(1);
  180. expect(result.argsArray[1].length).toEqual(1);
  181. expect(result.argsArray[2].length).toEqual(2);
  182. done();
  183. });
  184. });
  185. it('should skip if too few arguments', function (done) {
  186. var evaluator = new _evaluator.PartialEvaluator(new PdfManagerMock(), new XrefMock(), new HandlerMock(), 'prefix');
  187. var stream = new _stream.StringStream('5 d0');
  188. runOperatorListCheck(evaluator, stream, new ResourcesMock(), function (result) {
  189. expect(result.argsArray).toEqual([]);
  190. expect(result.fnArray).toEqual([]);
  191. done();
  192. });
  193. });
  194. it('should close opened saves', function (done) {
  195. var evaluator = new _evaluator.PartialEvaluator(new PdfManagerMock(), new XrefMock(), new HandlerMock(), 'prefix');
  196. var stream = new _stream.StringStream('qq');
  197. runOperatorListCheck(evaluator, stream, new ResourcesMock(), function (result) {
  198. expect(!!result.fnArray && !!result.argsArray).toEqual(true);
  199. expect(result.fnArray.length).toEqual(4);
  200. expect(result.fnArray[0]).toEqual(_util.OPS.save);
  201. expect(result.fnArray[1]).toEqual(_util.OPS.save);
  202. expect(result.fnArray[2]).toEqual(_util.OPS.restore);
  203. expect(result.fnArray[3]).toEqual(_util.OPS.restore);
  204. done();
  205. });
  206. });
  207. it('should skip paintXObject if name is missing', function (done) {
  208. var evaluator = new _evaluator.PartialEvaluator(new PdfManagerMock(), new XrefMock(), new HandlerMock(), 'prefix');
  209. var stream = new _stream.StringStream('/ Do');
  210. runOperatorListCheck(evaluator, stream, new ResourcesMock(), function (result) {
  211. expect(result.argsArray).toEqual([]);
  212. expect(result.fnArray).toEqual([]);
  213. done();
  214. });
  215. });
  216. it('should skip paintXObject if subtype is PS', function (done) {
  217. var evaluator = new _evaluator.PartialEvaluator(new PdfManagerMock(), new XrefMock(), new HandlerMock(), 'prefix');
  218. var xobjStreamDict = new _primitives.Dict();
  219. xobjStreamDict.set('Subtype', _primitives.Name.get('PS'));
  220. var xobjStream = new _stream.Stream([], 0, 0, xobjStreamDict);
  221. var xobjs = new _primitives.Dict();
  222. xobjs.set('Res1', xobjStream);
  223. var resources = new _primitives.Dict();
  224. resources.set('XObject', xobjs);
  225. var stream = new _stream.StringStream('/Res1 Do');
  226. runOperatorListCheck(evaluator, stream, resources, function (result) {
  227. expect(result.argsArray).toEqual([]);
  228. expect(result.fnArray).toEqual([]);
  229. done();
  230. });
  231. });
  232. });
  233. describe('thread control', function () {
  234. it('should abort operator list parsing', function (done) {
  235. var evaluator = new _evaluator.PartialEvaluator(new PdfManagerMock(), new XrefMock(), new HandlerMock(), 'prefix');
  236. var stream = new _stream.StringStream('qqQQ');
  237. var resources = new ResourcesMock();
  238. var result = new _evaluator.OperatorList();
  239. var task = new _worker.WorkerTask('OperatorListAbort');
  240. task.terminate();
  241. evaluator.getOperatorList(stream, task, resources, result).catch(function () {
  242. expect(!!result.fnArray && !!result.argsArray).toEqual(true);
  243. expect(result.fnArray.length).toEqual(0);
  244. done();
  245. });
  246. });
  247. it('should abort text parsing parsing', function (done) {
  248. var resources = new ResourcesMock();
  249. var evaluator = new _evaluator.PartialEvaluator(new PdfManagerMock(), new XrefMock(), new HandlerMock(), 'prefix');
  250. var stream = new _stream.StringStream('qqQQ');
  251. var task = new _worker.WorkerTask('TextContentAbort');
  252. task.terminate();
  253. evaluator.getTextContent(stream, task, resources).catch(function () {
  254. expect(true).toEqual(true);
  255. done();
  256. });
  257. });
  258. });
  259. describe('operator list', function () {
  260. function MessageHandlerMock() {}
  261. MessageHandlerMock.prototype = {
  262. send: function send() {}
  263. };
  264. it('should get correct total length after flushing', function () {
  265. var operatorList = new _evaluator.OperatorList(null, new MessageHandlerMock());
  266. operatorList.addOp(_util.OPS.save, null);
  267. operatorList.addOp(_util.OPS.restore, null);
  268. expect(operatorList.totalLength).toEqual(2);
  269. expect(operatorList.length).toEqual(2);
  270. operatorList.flush();
  271. expect(operatorList.totalLength).toEqual(2);
  272. expect(operatorList.length).toEqual(0);
  273. });
  274. });
  275. });