evaluator_spec.js 11 KB

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