puppet 3.1.1 → 3.2.0.rc1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of puppet might be problematic. Click here for more details.

Files changed (477) hide show
  1. data/CONTRIBUTING.md +2 -2
  2. data/Gemfile +32 -19
  3. data/README_DEVELOPER.md +332 -14
  4. data/Rakefile +9 -5
  5. data/ext/build_defaults.yaml +2 -3
  6. data/ext/debian/changelog.erb +6 -0
  7. data/ext/debian/control +6 -6
  8. data/ext/envpuppet +4 -4
  9. data/ext/project_data.yaml +1 -0
  10. data/ext/puppet-nm-dispatcher +13 -0
  11. data/ext/redhat/puppet.spec.erb +17 -0
  12. data/ext/suse/client.init +1 -1
  13. data/ext/systemd/puppetagent.service +2 -2
  14. data/ext/systemd/puppetmaster.service +2 -2
  15. data/lib/hiera/scope.rb +29 -11
  16. data/lib/hiera_puppet.rb +1 -3
  17. data/lib/puppet/agent.rb +3 -3
  18. data/lib/puppet/application.rb +2 -2
  19. data/lib/puppet/application/agent.rb +27 -12
  20. data/lib/puppet/application/apply.rb +11 -1
  21. data/lib/puppet/application/describe.rb +1 -1
  22. data/lib/puppet/application/doc.rb +13 -9
  23. data/lib/puppet/application/filebucket.rb +0 -1
  24. data/lib/puppet/application/kick.rb +1 -0
  25. data/lib/puppet/application/master.rb +16 -8
  26. data/lib/puppet/daemon.rb +19 -64
  27. data/lib/puppet/defaults.rb +61 -5
  28. data/lib/puppet/error.rb +15 -4
  29. data/lib/puppet/external/nagios/grammar.ry +1 -1
  30. data/lib/puppet/external/nagios/makefile +1 -1
  31. data/lib/puppet/external/nagios/parser.rb +185 -618
  32. data/lib/puppet/external/pson/pure/parser.rb +47 -1
  33. data/lib/puppet/face/certificate.rb +3 -3
  34. data/lib/puppet/face/module.rb +1 -1
  35. data/lib/puppet/face/module/changes.rb +3 -1
  36. data/lib/puppet/face/module/uninstall.rb +1 -1
  37. data/lib/puppet/face/node/clean.rb +5 -5
  38. data/lib/puppet/feature/base.rb +3 -1
  39. data/lib/puppet/feature/libuser.rb +8 -0
  40. data/lib/puppet/file_serving/fileset.rb +9 -1
  41. data/lib/puppet/forge.rb +28 -5
  42. data/lib/puppet/forge/errors.rb +34 -0
  43. data/lib/puppet/forge/repository.rb +1 -1
  44. data/lib/puppet/indirector.rb +4 -1
  45. data/lib/puppet/indirector/catalog/compiler.rb +37 -30
  46. data/lib/puppet/indirector/facts/inventory_active_record.rb +1 -0
  47. data/lib/puppet/indirector/indirection.rb +28 -15
  48. data/lib/puppet/indirector/rest.rb +18 -10
  49. data/lib/puppet/interface.rb +11 -4
  50. data/lib/puppet/interface/action.rb +1 -3
  51. data/lib/puppet/interface/action_builder.rb +0 -3
  52. data/lib/puppet/interface/action_manager.rb +0 -3
  53. data/lib/puppet/interface/face_collection.rb +0 -2
  54. data/lib/puppet/interface/option.rb +0 -2
  55. data/lib/puppet/interface/option_builder.rb +0 -2
  56. data/lib/puppet/interface/option_manager.rb +0 -2
  57. data/lib/puppet/metatype/manager.rb +1 -1
  58. data/lib/puppet/module_tool.rb +1 -0
  59. data/lib/puppet/module_tool/applications/application.rb +0 -3
  60. data/lib/puppet/module_tool/applications/builder.rb +8 -20
  61. data/lib/puppet/module_tool/applications/checksummer.rb +1 -1
  62. data/lib/puppet/module_tool/applications/installer.rb +1 -0
  63. data/lib/puppet/module_tool/applications/unpacker.rb +3 -11
  64. data/lib/puppet/module_tool/checksums.rb +1 -1
  65. data/lib/puppet/module_tool/errors/installer.rb +18 -1
  66. data/lib/puppet/module_tool/modulefile.rb +2 -2
  67. data/lib/puppet/module_tool/skeleton/templates/generator/Modulefile.erb +1 -1
  68. data/lib/puppet/module_tool/tar.rb +17 -0
  69. data/lib/puppet/module_tool/tar/gnu.rb +9 -0
  70. data/lib/puppet/module_tool/tar/mini.rb +39 -0
  71. data/lib/puppet/module_tool/tar/solaris.rb +5 -0
  72. data/lib/puppet/network/http.rb +1 -0
  73. data/lib/puppet/network/http/connection.rb +9 -23
  74. data/lib/puppet/network/http/handler.rb +38 -7
  75. data/lib/puppet/network/http/rack/rest.rb +14 -3
  76. data/lib/puppet/network/http/webrick.rb +3 -1
  77. data/lib/puppet/network/http/webrick/rest.rb +11 -2
  78. data/lib/puppet/node/environment.rb +3 -1
  79. data/lib/puppet/parameter.rb +32 -29
  80. data/lib/puppet/parameter/package_options.rb +1 -1
  81. data/lib/puppet/parameter/path.rb +1 -1
  82. data/lib/puppet/parameter/value.rb +1 -1
  83. data/lib/puppet/parameter/value_collection.rb +7 -3
  84. data/lib/puppet/parser/ast.rb +3 -1
  85. data/lib/puppet/parser/ast/arithmetic_operator.rb +56 -12
  86. data/lib/puppet/parser/ast/astarray.rb +1 -1
  87. data/lib/puppet/parser/ast/block_expression.rb +41 -0
  88. data/lib/puppet/parser/ast/function.rb +13 -2
  89. data/lib/puppet/parser/ast/lambda.rb +107 -0
  90. data/lib/puppet/parser/ast/leaf.rb +1 -2
  91. data/lib/puppet/parser/ast/method_call.rb +77 -0
  92. data/lib/puppet/parser/ast/vardef.rb +7 -0
  93. data/lib/puppet/parser/compiler.rb +27 -16
  94. data/lib/puppet/parser/e_parser_adapter.rb +120 -0
  95. data/lib/puppet/parser/files.rb +7 -6
  96. data/lib/puppet/parser/functions.rb +10 -8
  97. data/lib/puppet/parser/functions/collect.rb +43 -0
  98. data/lib/puppet/parser/functions/each.rb +96 -0
  99. data/lib/puppet/parser/functions/foreach.rb +96 -0
  100. data/lib/puppet/parser/functions/fqdn_rand.rb +2 -2
  101. data/lib/puppet/parser/functions/hiera.rb +20 -2
  102. data/lib/puppet/parser/functions/hiera_array.rb +21 -2
  103. data/lib/puppet/parser/functions/hiera_hash.rb +23 -2
  104. data/lib/puppet/parser/functions/hiera_include.rb +33 -2
  105. data/lib/puppet/parser/functions/inline_template.rb +4 -4
  106. data/lib/puppet/parser/functions/reduce.rb +74 -0
  107. data/lib/puppet/parser/functions/reject.rb +46 -0
  108. data/lib/puppet/parser/functions/select.rb +46 -0
  109. data/lib/puppet/parser/functions/slice.rb +96 -0
  110. data/lib/puppet/parser/functions/template.rb +2 -2
  111. data/lib/puppet/parser/grammar.ra +7 -4
  112. data/lib/puppet/parser/lexer.rb +10 -0
  113. data/lib/puppet/parser/methods.rb +69 -0
  114. data/lib/puppet/parser/parser.rb +855 -808
  115. data/lib/puppet/parser/parser_factory.rb +62 -0
  116. data/lib/puppet/parser/parser_support.rb +8 -2
  117. data/lib/puppet/parser/scope.rb +153 -47
  118. data/lib/puppet/parser/templatewrapper.rb +28 -21
  119. data/lib/puppet/parser/type_loader.rb +3 -1
  120. data/lib/puppet/pops.rb +40 -0
  121. data/lib/puppet/pops/adaptable.rb +190 -0
  122. data/lib/puppet/pops/adapters.rb +65 -0
  123. data/lib/puppet/pops/containment.rb +37 -0
  124. data/lib/puppet/pops/issues.rb +258 -0
  125. data/lib/puppet/pops/label_provider.rb +71 -0
  126. data/lib/puppet/pops/model/ast_transformer.rb +636 -0
  127. data/lib/puppet/pops/model/ast_tree_dumper.rb +378 -0
  128. data/lib/puppet/pops/model/factory.rb +804 -0
  129. data/lib/puppet/pops/model/model.rb +567 -0
  130. data/lib/puppet/pops/model/model_label_provider.rb +75 -0
  131. data/lib/puppet/pops/model/model_tree_dumper.rb +352 -0
  132. data/lib/puppet/pops/model/tree_dumper.rb +59 -0
  133. data/lib/puppet/pops/parser/egrammar.ra +723 -0
  134. data/lib/puppet/pops/parser/eparser.rb +2300 -0
  135. data/lib/puppet/pops/parser/grammar.ra +746 -0
  136. data/lib/puppet/pops/parser/lexer.rb +842 -0
  137. data/lib/puppet/pops/parser/makefile +13 -0
  138. data/lib/puppet/pops/parser/parser_support.rb +203 -0
  139. data/lib/puppet/pops/patterns.rb +35 -0
  140. data/lib/puppet/pops/utils.rb +104 -0
  141. data/lib/puppet/pops/validation.rb +297 -0
  142. data/lib/puppet/pops/validation/checker3_1.rb +551 -0
  143. data/lib/puppet/pops/validation/validator_factory_3_1.rb +41 -0
  144. data/lib/puppet/pops/visitable.rb +6 -0
  145. data/lib/puppet/pops/visitor.rb +50 -0
  146. data/lib/puppet/property.rb +37 -28
  147. data/lib/puppet/property/ensure.rb +2 -2
  148. data/lib/puppet/property/ordered_list.rb +1 -1
  149. data/lib/puppet/provider.rb +26 -30
  150. data/lib/puppet/provider/aixobject.rb +45 -44
  151. data/lib/puppet/provider/augeas/augeas.rb +0 -1
  152. data/lib/puppet/provider/confiner.rb +1 -1
  153. data/lib/puppet/provider/cron/crontab.rb +107 -67
  154. data/lib/puppet/provider/group/groupadd.rb +59 -3
  155. data/lib/puppet/provider/interface/cisco.rb +4 -4
  156. data/lib/puppet/provider/mount/parsed.rb +1 -1
  157. data/lib/puppet/provider/nameservice.rb +22 -6
  158. data/lib/puppet/provider/nameservice/pw.rb +1 -1
  159. data/lib/puppet/provider/package/aix.rb +28 -4
  160. data/lib/puppet/provider/package/gem.rb +0 -2
  161. data/lib/puppet/provider/package/macports.rb +1 -1
  162. data/lib/puppet/provider/package/nim.rb +249 -4
  163. data/lib/puppet/provider/package/opkg.rb +77 -0
  164. data/lib/puppet/provider/package/pacman.rb +2 -2
  165. data/lib/puppet/provider/package/rpm.rb +30 -16
  166. data/lib/puppet/provider/package/yum.rb +3 -3
  167. data/lib/puppet/provider/parsedfile.rb +80 -3
  168. data/lib/puppet/provider/selmodule/semodule.rb +2 -2
  169. data/lib/puppet/provider/service/debian.rb +0 -4
  170. data/lib/puppet/provider/service/freebsd.rb +2 -2
  171. data/lib/puppet/provider/service/gentoo.rb +0 -9
  172. data/lib/puppet/provider/service/init.rb +27 -2
  173. data/lib/puppet/provider/service/launchd.rb +1 -1
  174. data/lib/puppet/provider/service/openwrt.rb +36 -0
  175. data/lib/puppet/provider/service/redhat.rb +0 -9
  176. data/lib/puppet/provider/service/src.rb +38 -4
  177. data/lib/puppet/provider/service/systemd.rb +2 -2
  178. data/lib/puppet/provider/service/upstart.rb +1 -8
  179. data/lib/puppet/provider/user/aix.rb +4 -10
  180. data/lib/puppet/provider/user/pw.rb +6 -10
  181. data/lib/puppet/provider/user/useradd.rb +129 -31
  182. data/lib/puppet/provider/vlan/cisco.rb +4 -4
  183. data/lib/puppet/reference/function.rb +2 -2
  184. data/lib/puppet/reference/indirection.rb +46 -5
  185. data/lib/puppet/reference/metaparameter.rb +2 -2
  186. data/lib/puppet/reports.rb +5 -5
  187. data/lib/puppet/reports/rrdgraph.rb +4 -4
  188. data/lib/puppet/reports/tagmail.rb +1 -1
  189. data/lib/puppet/resource.rb +1 -1
  190. data/lib/puppet/resource/type.rb +13 -11
  191. data/lib/puppet/scheduler.rb +16 -0
  192. data/lib/puppet/scheduler/job.rb +53 -0
  193. data/lib/puppet/scheduler/scheduler.rb +45 -0
  194. data/lib/puppet/scheduler/splay_job.rb +32 -0
  195. data/lib/puppet/scheduler/timer.rb +13 -0
  196. data/lib/puppet/settings/base_setting.rb +1 -1
  197. data/lib/puppet/simple_graph.rb +4 -4
  198. data/lib/puppet/ssl/base.rb +12 -2
  199. data/lib/puppet/ssl/certificate.rb +4 -1
  200. data/lib/puppet/ssl/certificate_request.rb +4 -1
  201. data/lib/puppet/ssl/certificate_revocation_list.rb +4 -1
  202. data/lib/puppet/ssl/configuration.rb +32 -0
  203. data/lib/puppet/ssl/host.rb +18 -21
  204. data/lib/puppet/ssl/key.rb +4 -1
  205. data/lib/puppet/ssl/validator.rb +116 -0
  206. data/lib/puppet/transaction.rb +1 -1
  207. data/lib/puppet/transaction/event.rb +3 -10
  208. data/lib/puppet/transaction/event_manager.rb +8 -1
  209. data/lib/puppet/transaction/report.rb +17 -16
  210. data/lib/puppet/type.rb +77 -69
  211. data/lib/puppet/type/cron.rb +20 -8
  212. data/lib/puppet/type/exec.rb +9 -3
  213. data/lib/puppet/type/file.rb +95 -21
  214. data/lib/puppet/type/file/content.rb +1 -1
  215. data/lib/puppet/type/file/mode.rb +7 -1
  216. data/lib/puppet/type/file/source.rb +2 -2
  217. data/lib/puppet/type/group.rb +11 -0
  218. data/lib/puppet/type/scheduled_task.rb +5 -1
  219. data/lib/puppet/type/service.rb +1 -1
  220. data/lib/puppet/type/ssh_authorized_key.rb +2 -2
  221. data/lib/puppet/type/user.rb +24 -6
  222. data/lib/puppet/util.rb +12 -2
  223. data/lib/puppet/util/classgen.rb +4 -4
  224. data/lib/puppet/util/colors.rb +55 -0
  225. data/lib/puppet/util/command_line/trollop.rb +4 -4
  226. data/lib/puppet/util/errors.rb +39 -3
  227. data/lib/puppet/util/fileparsing.rb +5 -0
  228. data/lib/puppet/util/filetype.rb +11 -9
  229. data/lib/puppet/util/instrumentation/instrumentable.rb +2 -2
  230. data/lib/puppet/util/libuser.conf +15 -0
  231. data/lib/puppet/util/libuser.rb +12 -0
  232. data/lib/puppet/util/monkey_patches.rb +48 -0
  233. data/lib/puppet/util/network_device.rb +1 -1
  234. data/lib/puppet/util/network_device/base.rb +2 -2
  235. data/lib/puppet/util/network_device/cisco/device.rb +29 -19
  236. data/lib/puppet/util/network_device/config.rb +5 -2
  237. data/lib/puppet/util/network_device/ipcalc.rb +1 -1
  238. data/lib/puppet/util/network_device/transport/ssh.rb +4 -3
  239. data/lib/puppet/util/network_device/transport/telnet.rb +4 -2
  240. data/lib/puppet/util/plugins.rb +4 -4
  241. data/lib/puppet/util/posix.rb +1 -1
  242. data/lib/puppet/util/profiler.rb +28 -0
  243. data/lib/puppet/util/profiler/logging.rb +47 -0
  244. data/lib/puppet/util/profiler/none.rb +8 -0
  245. data/lib/puppet/util/profiler/object_counts.rb +17 -0
  246. data/lib/puppet/util/profiler/wall_clock.rb +34 -0
  247. data/lib/puppet/util/provider_features.rb +1 -1
  248. data/lib/puppet/util/rdoc/parser.rb +5 -5
  249. data/lib/puppet/util/ssl.rb +38 -0
  250. data/lib/puppet/util/subclass_loader.rb +1 -5
  251. data/lib/puppet/util/windows.rb +1 -0
  252. data/lib/puppet/util/windows/process.rb +3 -0
  253. data/lib/puppet/util/windows/root_certs.rb +86 -0
  254. data/lib/puppet/util/windows/security.rb +1 -0
  255. data/lib/puppet/version.rb +1 -1
  256. data/spec/fixtures/integration/provider/cron/crontab/create_normal_entry +19 -0
  257. data/spec/fixtures/integration/provider/cron/crontab/create_special_entry +18 -0
  258. data/spec/fixtures/integration/provider/cron/crontab/crontab_user1 +15 -0
  259. data/spec/fixtures/integration/provider/cron/crontab/crontab_user2 +4 -0
  260. data/spec/fixtures/integration/provider/cron/crontab/modify_entry +13 -0
  261. data/spec/fixtures/integration/provider/cron/crontab/moved_cronjob_input1 +15 -0
  262. data/spec/fixtures/integration/provider/cron/crontab/moved_cronjob_input2 +6 -0
  263. data/spec/fixtures/integration/provider/cron/crontab/remove_named_resource +12 -0
  264. data/spec/fixtures/integration/provider/cron/crontab/remove_unnamed_resource +14 -0
  265. data/spec/fixtures/unit/pops/parser/lexer/aliastest.pp +16 -0
  266. data/spec/fixtures/unit/pops/parser/lexer/append.pp +11 -0
  267. data/spec/fixtures/unit/pops/parser/lexer/argumentdefaults.pp +14 -0
  268. data/spec/fixtures/unit/pops/parser/lexer/arithmetic_expression.pp +8 -0
  269. data/spec/fixtures/unit/pops/parser/lexer/arraytrailingcomma.pp +3 -0
  270. data/spec/fixtures/unit/pops/parser/lexer/casestatement.pp +65 -0
  271. data/spec/fixtures/unit/pops/parser/lexer/classheirarchy.pp +15 -0
  272. data/spec/fixtures/unit/pops/parser/lexer/classincludes.pp +17 -0
  273. data/spec/fixtures/unit/pops/parser/lexer/classpathtest.pp +11 -0
  274. data/spec/fixtures/unit/pops/parser/lexer/collection.pp +10 -0
  275. data/spec/fixtures/unit/pops/parser/lexer/collection_override.pp +8 -0
  276. data/spec/fixtures/unit/pops/parser/lexer/collection_within_virtual_definitions.pp +20 -0
  277. data/spec/fixtures/unit/pops/parser/lexer/componentmetaparams.pp +11 -0
  278. data/spec/fixtures/unit/pops/parser/lexer/componentrequire.pp +8 -0
  279. data/spec/fixtures/unit/pops/parser/lexer/deepclassheirarchy.pp +23 -0
  280. data/spec/fixtures/unit/pops/parser/lexer/defineoverrides.pp +17 -0
  281. data/spec/fixtures/unit/pops/parser/lexer/emptyclass.pp +9 -0
  282. data/spec/fixtures/unit/pops/parser/lexer/emptyexec.pp +3 -0
  283. data/spec/fixtures/unit/pops/parser/lexer/emptyifelse.pp +9 -0
  284. data/spec/fixtures/unit/pops/parser/lexer/falsevalues.pp +3 -0
  285. data/spec/fixtures/unit/pops/parser/lexer/filecreate.pp +11 -0
  286. data/spec/fixtures/unit/pops/parser/lexer/fqdefinition.pp +5 -0
  287. data/spec/fixtures/unit/pops/parser/lexer/fqparents.pp +11 -0
  288. data/spec/fixtures/unit/pops/parser/lexer/funccomma.pp +5 -0
  289. data/spec/fixtures/unit/pops/parser/lexer/hash.pp +33 -0
  290. data/spec/fixtures/unit/pops/parser/lexer/ifexpression.pp +12 -0
  291. data/spec/fixtures/unit/pops/parser/lexer/implicititeration.pp +15 -0
  292. data/spec/fixtures/unit/pops/parser/lexer/multilinecomments.pp +10 -0
  293. data/spec/fixtures/unit/pops/parser/lexer/multipleclass.pp +9 -0
  294. data/spec/fixtures/unit/pops/parser/lexer/multipleinstances.pp +7 -0
  295. data/spec/fixtures/unit/pops/parser/lexer/multisubs.pp +13 -0
  296. data/spec/fixtures/unit/pops/parser/lexer/namevartest.pp +9 -0
  297. data/spec/fixtures/unit/pops/parser/lexer/scopetest.pp +13 -0
  298. data/spec/fixtures/unit/pops/parser/lexer/selectorvalues.pp +49 -0
  299. data/spec/fixtures/unit/pops/parser/lexer/simpledefaults.pp +5 -0
  300. data/spec/fixtures/unit/pops/parser/lexer/simpleselector.pp +38 -0
  301. data/spec/fixtures/unit/pops/parser/lexer/singleary.pp +19 -0
  302. data/spec/fixtures/unit/pops/parser/lexer/singlequote.pp +11 -0
  303. data/spec/fixtures/unit/pops/parser/lexer/singleselector.pp +22 -0
  304. data/spec/fixtures/unit/pops/parser/lexer/subclass_name_duplication.pp +11 -0
  305. data/spec/fixtures/unit/pops/parser/lexer/tag.pp +9 -0
  306. data/spec/fixtures/unit/pops/parser/lexer/tagged.pp +35 -0
  307. data/spec/fixtures/unit/pops/parser/lexer/virtualresources.pp +14 -0
  308. data/spec/fixtures/unit/provider/cron/crontab/single_line.yaml +4 -4
  309. data/spec/fixtures/unit/provider/cron/crontab/vixie_header.txt +3 -0
  310. data/spec/fixtures/unit/provider/cron/parsed/managed +6 -0
  311. data/spec/fixtures/unit/provider/cron/parsed/simple +9 -0
  312. data/spec/fixtures/unit/provider/parsedfile/simple.txt +4 -0
  313. data/spec/fixtures/unit/provider/service/systemd/list_units +18 -0
  314. data/spec/integration/parser/collector_spec.rb +1 -1
  315. data/spec/integration/parser/compiler_spec.rb +252 -227
  316. data/spec/integration/parser/parser_spec.rb +171 -53
  317. data/spec/integration/parser/scope_spec.rb +1 -1
  318. data/spec/integration/provider/cron/crontab_spec.rb +187 -0
  319. data/spec/integration/provider/service/systemd_spec.rb +20 -0
  320. data/spec/integration/type/file_spec.rb +21 -21
  321. data/spec/integration/type/package_spec.rb +1 -1
  322. data/spec/lib/puppet_spec/database.rb +2 -5
  323. data/spec/spec_helper.rb +6 -1
  324. data/spec/unit/application/apply_spec.rb +16 -1
  325. data/spec/unit/application/describe_spec.rb +1 -1
  326. data/spec/unit/application/doc_spec.rb +55 -32
  327. data/spec/unit/application/kick_spec.rb +8 -6
  328. data/spec/unit/application/master_spec.rb +4 -4
  329. data/spec/unit/daemon_spec.rb +1 -1
  330. data/spec/unit/forge/errors_spec.rb +40 -0
  331. data/spec/unit/forge/repository_spec.rb +11 -1
  332. data/spec/unit/forge_spec.rb +13 -3
  333. data/spec/unit/hiera/backend/puppet_backend_spec.rb +1 -0
  334. data/spec/unit/hiera/scope_spec.rb +48 -25
  335. data/spec/unit/indirector/catalog/active_record_spec.rb +6 -3
  336. data/spec/unit/indirector/catalog/compiler_spec.rb +3 -28
  337. data/spec/unit/indirector/catalog/static_compiler_spec.rb +1 -1
  338. data/spec/unit/indirector/facts/inventory_active_record_spec.rb +154 -150
  339. data/spec/unit/indirector/indirection_spec.rb +5 -0
  340. data/spec/unit/indirector/resource/active_record_spec.rb +5 -22
  341. data/spec/unit/indirector_spec.rb +7 -1
  342. data/spec/unit/interface/action_builder_spec.rb +1 -1
  343. data/spec/unit/interface/action_manager_spec.rb +0 -2
  344. data/spec/unit/interface/action_spec.rb +1 -1
  345. data/spec/unit/interface/documentation_spec.rb +0 -2
  346. data/spec/unit/interface/face_collection_spec.rb +1 -1
  347. data/spec/unit/interface/option_builder_spec.rb +1 -1
  348. data/spec/unit/interface/option_spec.rb +0 -1
  349. data/spec/unit/module_spec.rb +17 -19
  350. data/spec/unit/module_tool/application_spec.rb +1 -3
  351. data/spec/unit/module_tool/applications/builder_spec.rb +38 -0
  352. data/spec/unit/module_tool/applications/checksummer_spec.rb +134 -0
  353. data/spec/unit/module_tool/applications/installer_spec.rb +71 -91
  354. data/spec/unit/module_tool/applications/searcher_spec.rb +1 -3
  355. data/spec/unit/module_tool/applications/uninstaller_spec.rb +18 -26
  356. data/spec/unit/module_tool/applications/unpacker_spec.rb +19 -52
  357. data/spec/unit/module_tool/tar/gnu_spec.rb +19 -0
  358. data/spec/unit/module_tool/tar/mini_spec.rb +59 -0
  359. data/spec/unit/module_tool/tar/solaris_spec.rb +19 -0
  360. data/spec/unit/network/http/connection_spec.rb +17 -2
  361. data/spec/unit/network/http/handler_spec.rb +195 -167
  362. data/spec/unit/network/http/rack/rest_spec.rb +26 -4
  363. data/spec/unit/network/http/webrick/rest_spec.rb +28 -1
  364. data/spec/unit/network/http/webrick_spec.rb +12 -3
  365. data/spec/unit/node/environment_spec.rb +421 -404
  366. data/spec/unit/parser/ast/arithmetic_operator_spec.rb +98 -2
  367. data/spec/unit/parser/collector_spec.rb +4 -4
  368. data/spec/unit/parser/compiler_spec.rb +13 -13
  369. data/spec/unit/parser/eparser_adapter_spec.rb +407 -0
  370. data/spec/unit/parser/functions/extlookup_spec.rb +20 -17
  371. data/spec/unit/parser/functions/fqdn_rand_spec.rb +5 -0
  372. data/spec/unit/parser/functions/hiera_include_spec.rb +0 -2
  373. data/spec/unit/parser/functions/hiera_spec.rb +0 -2
  374. data/spec/unit/parser/functions_spec.rb +27 -15
  375. data/spec/unit/parser/methods/collect_spec.rb +110 -0
  376. data/spec/unit/parser/methods/each_spec.rb +91 -0
  377. data/spec/unit/parser/methods/foreach_spec.rb +91 -0
  378. data/spec/unit/parser/methods/reduce_spec.rb +67 -0
  379. data/spec/unit/parser/methods/reject_spec.rb +73 -0
  380. data/spec/unit/parser/methods/select_spec.rb +79 -0
  381. data/spec/unit/parser/methods/shared.rb +61 -0
  382. data/spec/unit/parser/methods/slice_spec.rb +97 -0
  383. data/spec/unit/parser/parser_spec.rb +2 -2
  384. data/spec/unit/parser/scope_spec.rb +39 -16
  385. data/spec/unit/parser/templatewrapper_spec.rb +6 -5
  386. data/spec/unit/parser/type_loader_spec.rb +191 -165
  387. data/spec/unit/pops/adaptable_spec.rb +143 -0
  388. data/spec/unit/pops/containment_spec.rb +25 -0
  389. data/spec/unit/pops/factory_rspec_helper.rb +77 -0
  390. data/spec/unit/pops/factory_spec.rb +329 -0
  391. data/spec/unit/pops/issues_spec.rb +26 -0
  392. data/spec/unit/pops/label_provider_spec.rb +42 -0
  393. data/spec/unit/pops/model/ast_transformer_spec.rb +65 -0
  394. data/spec/unit/pops/model/model_spec.rb +37 -0
  395. data/spec/unit/pops/parser/lexer_spec.rb +884 -0
  396. data/spec/unit/pops/parser/parse_basic_expressions_spec.rb +248 -0
  397. data/spec/unit/pops/parser/parse_calls_spec.rb +93 -0
  398. data/spec/unit/pops/parser/parse_conditionals_spec.rb +159 -0
  399. data/spec/unit/pops/parser/parse_containers_spec.rb +175 -0
  400. data/spec/unit/pops/parser/parse_resource_spec.rb +228 -0
  401. data/spec/unit/pops/parser/parser_rspec_helper.rb +11 -0
  402. data/spec/unit/pops/parser/parser_spec.rb +15 -0
  403. data/spec/unit/pops/parser/rgen_sanitycheck_spec.rb +16 -0
  404. data/spec/unit/pops/transformer/transform_basic_expressions_spec.rb +243 -0
  405. data/spec/unit/pops/transformer/transform_calls_spec.rb +80 -0
  406. data/spec/unit/pops/transformer/transform_conditionals_spec.rb +132 -0
  407. data/spec/unit/pops/transformer/transform_containers_spec.rb +182 -0
  408. data/spec/unit/pops/transformer/transform_resource_spec.rb +185 -0
  409. data/spec/unit/pops/transformer/transformer_rspec_helper.rb +27 -0
  410. data/spec/unit/pops/visitor_spec.rb +94 -0
  411. data/spec/unit/property_spec.rb +11 -0
  412. data/spec/unit/provider/augeas/augeas_spec.rb +3 -0
  413. data/spec/unit/provider/cron/crontab_spec.rb +97 -7
  414. data/spec/unit/provider/cron/parsed_spec.rb +325 -0
  415. data/spec/unit/provider/exec/posix_spec.rb +1 -1
  416. data/spec/unit/provider/group/groupadd_spec.rb +33 -3
  417. data/spec/unit/provider/group/pw_spec.rb +5 -5
  418. data/spec/unit/provider/nameservice_spec.rb +304 -0
  419. data/spec/unit/provider/package/aix_spec.rb +53 -11
  420. data/spec/unit/provider/package/aptrpm_spec.rb +6 -0
  421. data/spec/unit/provider/package/gem_spec.rb +6 -11
  422. data/spec/unit/provider/package/nim_spec.rb +216 -7
  423. data/spec/unit/provider/package/opkg_spec.rb +180 -0
  424. data/spec/unit/provider/package/rpm_spec.rb +149 -3
  425. data/spec/unit/provider/package/yum_spec.rb +6 -5
  426. data/spec/unit/provider/parsedfile_spec.rb +122 -28
  427. data/spec/unit/provider/service/freebsd_spec.rb +18 -0
  428. data/spec/unit/provider/service/init_spec.rb +108 -87
  429. data/spec/unit/provider/service/launchd_spec.rb +2 -2
  430. data/spec/unit/provider/service/openwrt_spec.rb +109 -0
  431. data/spec/unit/provider/service/src_spec.rb +117 -41
  432. data/spec/unit/provider/service/systemd_spec.rb +125 -17
  433. data/spec/unit/provider/service/upstart_spec.rb +1 -1
  434. data/spec/unit/provider/user/aix_spec.rb +42 -0
  435. data/spec/unit/provider/user/directoryservice_spec.rb +1 -0
  436. data/spec/unit/provider/user/pw_spec.rb +24 -12
  437. data/spec/unit/provider/user/user_role_add_spec.rb +1 -1
  438. data/spec/unit/provider/user/useradd_spec.rb +179 -15
  439. data/spec/unit/resource/type_spec.rb +3 -3
  440. data/spec/unit/scheduler/job_spec.rb +79 -0
  441. data/spec/unit/scheduler/scheduler_spec.rb +129 -0
  442. data/spec/unit/scheduler/splay_job_spec.rb +35 -0
  443. data/spec/unit/ssl/base_spec.rb +3 -9
  444. data/spec/unit/ssl/certificate_authority_spec.rb +1 -0
  445. data/spec/unit/ssl/certificate_request_spec.rb +3 -1
  446. data/spec/unit/ssl/certificate_spec.rb +3 -1
  447. data/spec/unit/ssl/configuration_spec.rb +74 -0
  448. data/spec/unit/ssl/host_spec.rb +28 -7
  449. data/spec/unit/ssl/validator_spec.rb +311 -0
  450. data/spec/unit/transaction/event_manager_spec.rb +49 -0
  451. data/spec/unit/transaction/event_spec.rb +20 -5
  452. data/spec/unit/transaction/report_spec.rb +8 -0
  453. data/spec/unit/type/cron_spec.rb +9 -0
  454. data/spec/unit/type/exec_spec.rb +11 -0
  455. data/spec/unit/type/file/content_spec.rb +20 -20
  456. data/spec/unit/type/file/mode_spec.rb +6 -0
  457. data/spec/unit/type/file/source_spec.rb +9 -7
  458. data/spec/unit/type/file_spec.rb +22 -3
  459. data/spec/unit/type/service_spec.rb +34 -21
  460. data/spec/unit/type_spec.rb +46 -1
  461. data/spec/unit/util/backups_spec.rb +2 -2
  462. data/spec/unit/util/execution_spec.rb +4 -1
  463. data/spec/unit/util/filetype_spec.rb +6 -0
  464. data/spec/unit/util/monkey_patches_spec.rb +18 -0
  465. data/spec/unit/util/network_device/cisco/device_spec.rb +37 -0
  466. data/spec/unit/util/network_device/config_spec.rb +14 -0
  467. data/spec/unit/util/network_device_spec.rb +3 -3
  468. data/spec/unit/util/profiler/logging_spec.rb +81 -0
  469. data/spec/unit/util/profiler/none_spec.rb +12 -0
  470. data/spec/unit/util/profiler/object_counts_spec.rb +14 -0
  471. data/spec/unit/util/profiler/wall_clock_spec.rb +13 -0
  472. data/spec/unit/util/pson_spec.rb +5 -0
  473. data/spec/unit/util/ssl_spec.rb +51 -0
  474. data/spec/unit/util/windows/root_certs_spec.rb +15 -0
  475. data/spec/unit/util_spec.rb +28 -0
  476. metadata +2593 -2307
  477. data/spec/unit/module_tool/applications/application_spec.rb +0 -19
@@ -0,0 +1,42 @@
1
+ require 'spec_helper'
2
+ require 'puppet/pops'
3
+
4
+ describe Puppet::Pops::LabelProvider do
5
+ let(:labeler) { Puppet::Pops::LabelProvider.new }
6
+
7
+ it "prefixes words that start with a vowel with an 'an'" do
8
+ labeler.a_an('owl').should == 'an owl'
9
+ end
10
+
11
+ it "prefixes words that start with a consonant with an 'a'" do
12
+ labeler.a_an('bear').should == 'a bear'
13
+ end
14
+
15
+ it "prefixes non-word characters with an 'a'" do
16
+ labeler.a_an('[] expression').should == 'a [] expression'
17
+ end
18
+
19
+ it "ignores a single quote leading the word" do
20
+ labeler.a_an("'owl'").should == "an 'owl'"
21
+ end
22
+
23
+ it "ignores a double quote leading the word" do
24
+ labeler.a_an('"owl"').should == 'an "owl"'
25
+ end
26
+
27
+ it "capitalizes the indefinite article for a word when requested" do
28
+ labeler.a_an_uc('owl').should == 'An owl'
29
+ end
30
+
31
+ it "raises an error when missing a character to work with" do
32
+ expect {
33
+ labeler.a_an('"')
34
+ }.to raise_error(Puppet::DevError, /<"> does not appear to contain a word/)
35
+ end
36
+
37
+ it "raises an error when given an empty string" do
38
+ expect {
39
+ labeler.a_an('')
40
+ }.to raise_error(Puppet::DevError, /<> does not appear to contain a word/)
41
+ end
42
+ end
@@ -0,0 +1,65 @@
1
+ require 'spec_helper'
2
+
3
+ require File.join(File.dirname(__FILE__), '/../factory_rspec_helper')
4
+ require 'puppet/pops'
5
+
6
+ describe Puppet::Pops::Model::AstTransformer do
7
+ include FactoryRspecHelper
8
+
9
+ let(:filename) { "the-file.pp" }
10
+ let(:transformer) { Puppet::Pops::Model::AstTransformer.new(filename) }
11
+
12
+ context "literal numbers" do
13
+ it "converts a decimal number to a string Name" do
14
+ ast = transform(QNAME_OR_NUMBER("10"))
15
+
16
+ ast.should be_kind_of Puppet::Parser::AST::Name
17
+ ast.value.should == "10"
18
+ end
19
+
20
+ it "converts an octal number to a string Name" do
21
+ ast = transform(QNAME_OR_NUMBER("020"))
22
+
23
+ ast.should be_kind_of Puppet::Parser::AST::Name
24
+ ast.value.should == "020"
25
+ end
26
+
27
+ it "converts a hex number to a string Name" do
28
+ ast = transform(QNAME_OR_NUMBER("0x20"))
29
+
30
+ ast.should be_kind_of Puppet::Parser::AST::Name
31
+ ast.value.should == "0x20"
32
+ end
33
+
34
+ it "converts an unknown radix to an error string" do
35
+ ast = transform(Puppet::Pops::Model::Factory.new(Puppet::Pops::Model::LiteralNumber, 3, 2))
36
+
37
+ ast.should be_kind_of Puppet::Parser::AST::Name
38
+ ast.value.should == "bad radix:3"
39
+ end
40
+ end
41
+
42
+ it "preserves the file location" do
43
+ model = literal(1)
44
+ model.record_position(location(3, 1, 10), location(3, 2, 11))
45
+
46
+ ast = transform(model)
47
+
48
+ ast.file.should == filename
49
+ ast.line.should == 3
50
+ ast.pos.should == 1
51
+ end
52
+
53
+ def transform(model)
54
+ transformer.transform(model)
55
+ end
56
+
57
+ def location(line, column, offset)
58
+ position = Puppet::Pops::Adapters::SourcePosAdapter.new
59
+ position.line = line
60
+ position.pos = column
61
+ position.offset = offset
62
+
63
+ position
64
+ end
65
+ end
@@ -0,0 +1,37 @@
1
+ #! /usr/bin/env ruby
2
+ require 'spec_helper'
3
+ require 'puppet/pops'
4
+
5
+ describe Puppet::Pops::Model do
6
+ it "should be possible to create an instance of a model object" do
7
+ nop = Puppet::Pops::Model::Nop.new
8
+ nop.class.should == Puppet::Pops::Model::Nop
9
+ end
10
+ end
11
+
12
+ describe Puppet::Pops::Model::Factory do
13
+ Factory = Puppet::Pops::Model::Factory
14
+ Model = Puppet::Pops::Model
15
+
16
+ it "construct an arithmetic expression" do
17
+ x = Factory.literal(10) + Factory.literal(20)
18
+ x.is_a?(Factory).should == true
19
+ current = x.current
20
+ current.is_a?(Model::ArithmeticExpression).should == true
21
+ current.operator.should == :'+'
22
+ current.left_expr.class.should == Model::LiteralNumber
23
+ current.right_expr.class.should == Model::LiteralNumber
24
+ current.left_expr.value.should == 10
25
+ current.right_expr.value.should == 20
26
+ end
27
+
28
+ it "should be easy to compare using a model tree dumper" do
29
+ x = Factory.literal(10) + Factory.literal(20)
30
+ Puppet::Pops::Model::ModelTreeDumper.new.dump(x.current).should == "(+ 10 20)"
31
+ end
32
+
33
+ it "builder should apply precedence" do
34
+ x = Factory.literal(2) * Factory.literal(10) + Factory.literal(20)
35
+ Puppet::Pops::Model::ModelTreeDumper.new.dump(x.current).should == "(+ (* 2 10) 20)"
36
+ end
37
+ end
@@ -0,0 +1,884 @@
1
+ #! /usr/bin/env ruby
2
+ require 'spec_helper'
3
+
4
+ require 'puppet/pops'
5
+
6
+ # This is a special matcher to match easily lexer output
7
+ RSpec::Matchers.define :be_like do |*expected|
8
+ match do |actual|
9
+ diffable
10
+ expected.zip(actual).all? { |e,a| !e or a[0] == e or (e.is_a? Array and a[0] == e[0] and (a[1] == e[1] or (a[1].is_a?(Hash) and a[1][:value] == e[1]))) }
11
+ end
12
+ end
13
+ __ = nil
14
+
15
+ module EgrammarLexerSpec
16
+ def self.tokens_scanned_from(s)
17
+ lexer = Puppet::Pops::Parser::Lexer.new
18
+ lexer.string = s
19
+ lexer.fullscan[0..-2]
20
+ end
21
+ end
22
+
23
+ describe Puppet::Pops::Parser::Lexer do
24
+ include EgrammarLexerSpec
25
+
26
+ describe "when reading strings" do
27
+ before { @lexer = Puppet::Pops::Parser::Lexer.new }
28
+
29
+ it "should increment the line count for every carriage return in the string" do
30
+ @lexer.string = "'this\nis\natest'"
31
+ @lexer.fullscan[0..-2]
32
+
33
+ line = @lexer.line
34
+ line.should == 3
35
+ end
36
+
37
+ it "should not increment the line count for escapes in the string" do
38
+ @lexer.string = "'this\\nis\\natest'"
39
+ @lexer.fullscan[0..-2]
40
+
41
+ @lexer.line.should == 1
42
+ end
43
+
44
+ it "should not think the terminator is escaped, when preceeded by an even number of backslashes" do
45
+ @lexer.string = "'here\nis\nthe\nstring\\\\'with\nextra\njunk"
46
+ @lexer.fullscan[0..-2]
47
+
48
+ @lexer.line.should == 6
49
+ end
50
+
51
+ {
52
+ 'r' => "\r",
53
+ 'n' => "\n",
54
+ 't' => "\t",
55
+ 's' => " "
56
+ }.each do |esc, expected_result|
57
+ it "should recognize \\#{esc} sequence" do
58
+ @lexer.string = "\\#{esc}'"
59
+ @lexer.slurpstring("'")[0].should == expected_result
60
+ end
61
+ end
62
+ end
63
+ end
64
+
65
+ describe Puppet::Pops::Parser::Lexer::Token, "when initializing" do
66
+ it "should create a regex if the first argument is a string" do
67
+ Puppet::Pops::Parser::Lexer::Token.new("something", :NAME).regex.should == %r{something}
68
+ end
69
+
70
+ it "should set the string if the first argument is one" do
71
+ Puppet::Pops::Parser::Lexer::Token.new("something", :NAME).string.should == "something"
72
+ end
73
+
74
+ it "should set the regex if the first argument is one" do
75
+ Puppet::Pops::Parser::Lexer::Token.new(%r{something}, :NAME).regex.should == %r{something}
76
+ end
77
+ end
78
+
79
+ describe Puppet::Pops::Parser::Lexer::TokenList do
80
+ before do
81
+ @list = Puppet::Pops::Parser::Lexer::TokenList.new
82
+ end
83
+
84
+ it "should have a method for retrieving tokens by the name" do
85
+ token = @list.add_token :name, "whatever"
86
+ @list[:name].should equal(token)
87
+ end
88
+
89
+ it "should have a method for retrieving string tokens by the string" do
90
+ token = @list.add_token :name, "whatever"
91
+ @list.lookup("whatever").should equal(token)
92
+ end
93
+
94
+ it "should add tokens to the list when directed" do
95
+ token = @list.add_token :name, "whatever"
96
+ @list[:name].should equal(token)
97
+ end
98
+
99
+ it "should have a method for adding multiple tokens at once" do
100
+ @list.add_tokens "whatever" => :name, "foo" => :bar
101
+ @list[:name].should_not be_nil
102
+ @list[:bar].should_not be_nil
103
+ end
104
+
105
+ it "should fail to add tokens sharing a name with an existing token" do
106
+ @list.add_token :name, "whatever"
107
+ expect { @list.add_token :name, "whatever" }.to raise_error(ArgumentError)
108
+ end
109
+
110
+ it "should set provided options on tokens being added" do
111
+ token = @list.add_token :name, "whatever", :skip_text => true
112
+ token.skip_text.should == true
113
+ end
114
+
115
+ it "should define any provided blocks as a :convert method" do
116
+ token = @list.add_token(:name, "whatever") do "foo" end
117
+ token.convert.should == "foo"
118
+ end
119
+
120
+ it "should store all string tokens in the :string_tokens list" do
121
+ one = @list.add_token(:name, "1")
122
+ @list.string_tokens.should be_include(one)
123
+ end
124
+
125
+ it "should store all regex tokens in the :regex_tokens list" do
126
+ one = @list.add_token(:name, %r{one})
127
+ @list.regex_tokens.should be_include(one)
128
+ end
129
+
130
+ it "should not store string tokens in the :regex_tokens list" do
131
+ one = @list.add_token(:name, "1")
132
+ @list.regex_tokens.should_not be_include(one)
133
+ end
134
+
135
+ it "should not store regex tokens in the :string_tokens list" do
136
+ one = @list.add_token(:name, %r{one})
137
+ @list.string_tokens.should_not be_include(one)
138
+ end
139
+
140
+ it "should sort the string tokens inversely by length when asked" do
141
+ one = @list.add_token(:name, "1")
142
+ two = @list.add_token(:other, "12")
143
+ @list.sort_tokens
144
+ @list.string_tokens.should == [two, one]
145
+ end
146
+ end
147
+
148
+ describe Puppet::Pops::Parser::Lexer::TOKENS do
149
+ before do
150
+ @lexer = Puppet::Pops::Parser::Lexer.new
151
+ end
152
+
153
+ {
154
+ :LBRACK => '[',
155
+ :RBRACK => ']',
156
+ # :LBRACE => '{',
157
+ :RBRACE => '}',
158
+ :LPAREN => '(',
159
+ :RPAREN => ')',
160
+ :EQUALS => '=',
161
+ :ISEQUAL => '==',
162
+ :GREATEREQUAL => '>=',
163
+ :GREATERTHAN => '>',
164
+ :LESSTHAN => '<',
165
+ :LESSEQUAL => '<=',
166
+ :NOTEQUAL => '!=',
167
+ :NOT => '!',
168
+ :COMMA => ',',
169
+ :DOT => '.',
170
+ :COLON => ':',
171
+ :AT => '@',
172
+ :LLCOLLECT => '<<|',
173
+ :RRCOLLECT => '|>>',
174
+ :LCOLLECT => '<|',
175
+ :RCOLLECT => '|>',
176
+ :SEMIC => ';',
177
+ :QMARK => '?',
178
+ :BACKSLASH => '\\',
179
+ :FARROW => '=>',
180
+ :PARROW => '+>',
181
+ :APPENDS => '+=',
182
+ :PLUS => '+',
183
+ :MINUS => '-',
184
+ :DIV => '/',
185
+ :TIMES => '*',
186
+ :LSHIFT => '<<',
187
+ :RSHIFT => '>>',
188
+ :MATCH => '=~',
189
+ :NOMATCH => '!~',
190
+ :IN_EDGE => '->',
191
+ :OUT_EDGE => '<-',
192
+ :IN_EDGE_SUB => '~>',
193
+ :OUT_EDGE_SUB => '<~',
194
+ :PIPE => '|',
195
+ }.each do |name, string|
196
+ it "should have a token named #{name.to_s}" do
197
+ Puppet::Pops::Parser::Lexer::TOKENS[name].should_not be_nil
198
+ end
199
+
200
+ it "should match '#{string}' for the token #{name.to_s}" do
201
+ Puppet::Pops::Parser::Lexer::TOKENS[name].string.should == string
202
+ end
203
+ end
204
+
205
+ {
206
+ "case" => :CASE,
207
+ "class" => :CLASS,
208
+ "default" => :DEFAULT,
209
+ "define" => :DEFINE,
210
+ # "import" => :IMPORT, # done as a function in egrammar
211
+ "if" => :IF,
212
+ "elsif" => :ELSIF,
213
+ "else" => :ELSE,
214
+ "inherits" => :INHERITS,
215
+ "node" => :NODE,
216
+ "and" => :AND,
217
+ "or" => :OR,
218
+ "undef" => :UNDEF,
219
+ "false" => :FALSE,
220
+ "true" => :TRUE,
221
+ "in" => :IN,
222
+ "unless" => :UNLESS,
223
+ }.each do |string, name|
224
+ it "should have a keyword named #{name.to_s}" do
225
+ Puppet::Pops::Parser::Lexer::KEYWORDS[name].should_not be_nil
226
+ end
227
+
228
+ it "should have the keyword for #{name.to_s} set to #{string}" do
229
+ Puppet::Pops::Parser::Lexer::KEYWORDS[name].string.should == string
230
+ end
231
+ end
232
+
233
+ # These tokens' strings don't matter, just that the tokens exist.
234
+ [:STRING, :DQPRE, :DQMID, :DQPOST, :BOOLEAN, :NAME, :NUMBER, :COMMENT, :MLCOMMENT,
235
+ :LBRACE, :LAMBDA,
236
+ :RETURN, :SQUOTE, :DQUOTE, :VARIABLE].each do |name|
237
+ it "should have a token named #{name.to_s}" do
238
+ Puppet::Pops::Parser::Lexer::TOKENS[name].should_not be_nil
239
+ end
240
+ end
241
+ end
242
+
243
+ describe Puppet::Pops::Parser::Lexer::TOKENS[:CLASSREF] do
244
+ before { @token = Puppet::Pops::Parser::Lexer::TOKENS[:CLASSREF] }
245
+
246
+ it "should match against single upper-case alpha-numeric terms" do
247
+ @token.regex.should =~ "One"
248
+ end
249
+
250
+ it "should match against upper-case alpha-numeric terms separated by double colons" do
251
+ @token.regex.should =~ "One::Two"
252
+ end
253
+
254
+ it "should match against many upper-case alpha-numeric terms separated by double colons" do
255
+ @token.regex.should =~ "One::Two::Three::Four::Five"
256
+ end
257
+
258
+ it "should match against upper-case alpha-numeric terms prefixed by double colons" do
259
+ @token.regex.should =~ "::One"
260
+ end
261
+ end
262
+
263
+ describe Puppet::Pops::Parser::Lexer::TOKENS[:NAME] do
264
+ before { @token = Puppet::Pops::Parser::Lexer::TOKENS[:NAME] }
265
+
266
+ it "should match against lower-case alpha-numeric terms" do
267
+ @token.regex.should =~ "one-two"
268
+ end
269
+
270
+ it "should return itself and the value if the matched term is not a keyword" do
271
+ Puppet::Pops::Parser::Lexer::KEYWORDS.expects(:lookup).returns(nil)
272
+ @token.convert(stub("lexer"), "myval").should == [Puppet::Pops::Parser::Lexer::TOKENS[:NAME], "myval"]
273
+ end
274
+
275
+ it "should return the keyword token and the value if the matched term is a keyword" do
276
+ keyword = stub 'keyword', :name => :testing
277
+ Puppet::Pops::Parser::Lexer::KEYWORDS.expects(:lookup).returns(keyword)
278
+ @token.convert(stub("lexer"), "myval").should == [keyword, "myval"]
279
+ end
280
+
281
+ it "should return the BOOLEAN token and 'true' if the matched term is the string 'true'" do
282
+ keyword = stub 'keyword', :name => :TRUE
283
+ Puppet::Pops::Parser::Lexer::KEYWORDS.expects(:lookup).returns(keyword)
284
+ @token.convert(stub('lexer'), "true").should == [Puppet::Pops::Parser::Lexer::TOKENS[:BOOLEAN], true]
285
+ end
286
+
287
+ it "should return the BOOLEAN token and 'false' if the matched term is the string 'false'" do
288
+ keyword = stub 'keyword', :name => :FALSE
289
+ Puppet::Pops::Parser::Lexer::KEYWORDS.expects(:lookup).returns(keyword)
290
+ @token.convert(stub('lexer'), "false").should == [Puppet::Pops::Parser::Lexer::TOKENS[:BOOLEAN], false]
291
+ end
292
+
293
+ it "should match against lower-case alpha-numeric terms separated by double colons" do
294
+ @token.regex.should =~ "one::two"
295
+ end
296
+
297
+ it "should match against many lower-case alpha-numeric terms separated by double colons" do
298
+ @token.regex.should =~ "one::two::three::four::five"
299
+ end
300
+
301
+ it "should match against lower-case alpha-numeric terms prefixed by double colons" do
302
+ @token.regex.should =~ "::one"
303
+ end
304
+
305
+ it "should match against nested terms starting with numbers" do
306
+ @token.regex.should =~ "::1one::2two::3three"
307
+ end
308
+ end
309
+
310
+ describe Puppet::Pops::Parser::Lexer::TOKENS[:NUMBER] do
311
+ before do
312
+ @token = Puppet::Pops::Parser::Lexer::TOKENS[:NUMBER]
313
+ @regex = @token.regex
314
+ end
315
+
316
+ it "should match against numeric terms" do
317
+ @regex.should =~ "2982383139"
318
+ end
319
+
320
+ it "should match against float terms" do
321
+ @regex.should =~ "29823.235"
322
+ end
323
+
324
+ it "should match against hexadecimal terms" do
325
+ @regex.should =~ "0xBEEF0023"
326
+ end
327
+
328
+ it "should match against float with exponent terms" do
329
+ @regex.should =~ "10e23"
330
+ end
331
+
332
+ it "should match against float terms with negative exponents" do
333
+ @regex.should =~ "10e-23"
334
+ end
335
+
336
+ it "should match against float terms with fractional parts and exponent" do
337
+ @regex.should =~ "1.234e23"
338
+ end
339
+ end
340
+
341
+ describe Puppet::Pops::Parser::Lexer::TOKENS[:COMMENT] do
342
+ before { @token = Puppet::Pops::Parser::Lexer::TOKENS[:COMMENT] }
343
+
344
+ it "should match against lines starting with '#'" do
345
+ @token.regex.should =~ "# this is a comment"
346
+ end
347
+
348
+ it "should be marked to get skipped" do
349
+ @token.skip?.should be_true
350
+ end
351
+
352
+ it "'s block should return the comment without the #" do
353
+ @token.convert(@lexer,"# this is a comment")[1].should == "this is a comment"
354
+ end
355
+ end
356
+
357
+ describe Puppet::Pops::Parser::Lexer::TOKENS[:MLCOMMENT] do
358
+ before do
359
+ @token = Puppet::Pops::Parser::Lexer::TOKENS[:MLCOMMENT]
360
+ @lexer = stub 'lexer', :line => 0
361
+ end
362
+
363
+ it "should match against lines enclosed with '/*' and '*/'" do
364
+ @token.regex.should =~ "/* this is a comment */"
365
+ end
366
+
367
+ it "should match multiple lines enclosed with '/*' and '*/'" do
368
+ @token.regex.should =~ """/*
369
+ this is a comment
370
+ */"""
371
+ end
372
+
373
+ # # TODO: REWRITE THIS TEST TO NOT BE BASED ON INTERNALS
374
+ # it "should increase the lexer current line number by the amount of lines spanned by the comment" do
375
+ # @lexer.expects(:line=).with(2)
376
+ # @token.convert(@lexer, "1\n2\n3")
377
+ # end
378
+
379
+ it "should not greedily match comments" do
380
+ match = @token.regex.match("/* first */ word /* second */")
381
+ match[1].should == " first "
382
+ end
383
+
384
+ it "'s block should return the comment without the comment marks" do
385
+ @lexer.stubs(:line=).with(0)
386
+
387
+ @token.convert(@lexer,"/* this is a comment */")[1].should == "this is a comment"
388
+ end
389
+ end
390
+
391
+ describe Puppet::Pops::Parser::Lexer::TOKENS[:RETURN] do
392
+ before { @token = Puppet::Pops::Parser::Lexer::TOKENS[:RETURN] }
393
+
394
+ it "should match against carriage returns" do
395
+ @token.regex.should =~ "\n"
396
+ end
397
+
398
+ it "should be marked to initiate text skipping" do
399
+ @token.skip_text.should be_true
400
+ end
401
+ end
402
+
403
+ shared_examples_for "handling `-` in standard variable names for egrammar" do |prefix|
404
+ # Watch out - a regex might match a *prefix* on these, not just the whole
405
+ # word, so make sure you don't have false positive or negative results based
406
+ # on that.
407
+ legal = %w{f foo f::b foo::b f::bar foo::bar 3 foo3 3foo}
408
+ illegal = %w{f- f-o -f f::-o f::o- f::o-o}
409
+
410
+ ["", "::"].each do |global_scope|
411
+ legal.each do |name|
412
+ var = prefix + global_scope + name
413
+ it "should accept #{var.inspect} as a valid variable name" do
414
+ (subject.regex.match(var) || [])[0].should == var
415
+ end
416
+ end
417
+
418
+ illegal.each do |name|
419
+ var = prefix + global_scope + name
420
+ it "when `variable_with_dash` is disabled it should NOT accept #{var.inspect} as a valid variable name" do
421
+ Puppet[:allow_variables_with_dashes] = false
422
+ (subject.regex.match(var) || [])[0].should_not == var
423
+ end
424
+
425
+ it "when `variable_with_dash` is enabled it should NOT accept #{var.inspect} as a valid variable name" do
426
+ Puppet[:allow_variables_with_dashes] = true
427
+ (subject.regex.match(var) || [])[0].should_not == var
428
+ end
429
+ end
430
+ end
431
+ end
432
+
433
+ describe Puppet::Pops::Parser::Lexer::TOKENS[:DOLLAR_VAR] do
434
+ its(:skip_text) { should be_false }
435
+
436
+ it_should_behave_like "handling `-` in standard variable names for egrammar", '$'
437
+ end
438
+
439
+ describe Puppet::Pops::Parser::Lexer::TOKENS[:VARIABLE] do
440
+ its(:skip_text) { should be_false }
441
+
442
+ it_should_behave_like "handling `-` in standard variable names for egrammar", ''
443
+ end
444
+
445
+ describe "the horrible deprecation / compatibility variables with dashes" do
446
+ ENamesWithDashes = %w{f- f-o -f f::-o f::o- f::o-o}
447
+
448
+ { Puppet::Pops::Parser::Lexer::TOKENS[:DOLLAR_VAR_WITH_DASH] => '$',
449
+ Puppet::Pops::Parser::Lexer::TOKENS[:VARIABLE_WITH_DASH] => ''
450
+ }.each do |token, prefix|
451
+ describe token do
452
+ its(:skip_text) { should be_false }
453
+
454
+ context "when compatibly is disabled" do
455
+ before :each do Puppet[:allow_variables_with_dashes] = false end
456
+ Puppet::Pops::Parser::Lexer::TOKENS.each do |name, value|
457
+ it "should be unacceptable after #{name}" do
458
+ token.acceptable?(:after => name).should be_false
459
+ end
460
+ end
461
+
462
+ # Yes, this should still *match*, just not be acceptable.
463
+ ENamesWithDashes.each do |name|
464
+ ["", "::"].each do |global_scope|
465
+ var = prefix + global_scope + name
466
+ it "should match #{var.inspect}" do
467
+ subject.regex.match(var).to_a.should == [var]
468
+ end
469
+ end
470
+ end
471
+ end
472
+
473
+ context "when compatibility is enabled" do
474
+ before :each do Puppet[:allow_variables_with_dashes] = true end
475
+
476
+ it "should be acceptable after DQPRE" do
477
+ token.acceptable?(:after => :DQPRE).should be_true
478
+ end
479
+
480
+ ENamesWithDashes.each do |name|
481
+ ["", "::"].each do |global_scope|
482
+ var = prefix + global_scope + name
483
+ it "should match #{var.inspect}" do
484
+ subject.regex.match(var).to_a.should == [var]
485
+ end
486
+ end
487
+ end
488
+ end
489
+ end
490
+ end
491
+
492
+ context "deprecation warnings" do
493
+ before :each do Puppet[:allow_variables_with_dashes] = true end
494
+
495
+ it "should match a top level variable" do
496
+ Puppet.expects(:deprecation_warning).once
497
+
498
+ EgrammarLexerSpec.tokens_scanned_from('$foo-bar').should == [
499
+ [:VARIABLE, {:value=>"foo-bar", :line=>1, :pos=>1, :offset=>0, :length=>8}]
500
+ ]
501
+ end
502
+
503
+ it "does not warn about a variable without a dash" do
504
+ Puppet.expects(:deprecation_warning).never
505
+
506
+ EgrammarLexerSpec.tokens_scanned_from('$c').should == [
507
+ [:VARIABLE, {:value=>"c", :line=>1, :pos=>1, :offset=>0, :length=>2}]
508
+ ]
509
+ end
510
+
511
+ it "does not warn about referencing a class name that contains a dash" do
512
+ Puppet.expects(:deprecation_warning).never
513
+
514
+ EgrammarLexerSpec.tokens_scanned_from('foo-bar').should == [
515
+ [:NAME, {:value=>"foo-bar", :line=>1, :pos=>1, :offset=>0, :length=>7}]
516
+ ]
517
+ end
518
+
519
+ it "warns about reference to variable" do
520
+ Puppet.expects(:deprecation_warning).once
521
+
522
+ EgrammarLexerSpec.tokens_scanned_from('$::foo-bar::baz-quux').should == [
523
+ [:VARIABLE, {:value=>"::foo-bar::baz-quux", :line=>1, :pos=>1, :offset=>0, :length=>20}]
524
+ ]
525
+ end
526
+
527
+ it "warns about reference to variable interpolated in a string" do
528
+ Puppet.expects(:deprecation_warning).once
529
+
530
+ EgrammarLexerSpec.tokens_scanned_from('"$::foo-bar::baz-quux"').should == [
531
+ [:DQPRE, {:value=>"", :line=>1, :pos=>1, :offset=>0, :length=>2}], # length since preamble includes start and terminator
532
+ [:VARIABLE, {:value=>"::foo-bar::baz-quux", :line=>1, :pos=>3, :offset=>2, :length=>19}],
533
+ [:DQPOST, {:value=>"", :line=>1, :pos=>22, :offset=>21, :length=>1}],
534
+ ]
535
+ end
536
+
537
+ it "warns about reference to variable interpolated in a string as an expression" do
538
+ Puppet.expects(:deprecation_warning).once
539
+
540
+ EgrammarLexerSpec.tokens_scanned_from('"${::foo-bar::baz-quux}"').should == [
541
+ [:DQPRE, {:value=>"", :line=>1, :pos=>1, :offset=>0, :length=>3}],
542
+ [:VARIABLE, {:value=>"::foo-bar::baz-quux", :line=>1, :pos=>4, :offset=>3, :length=>19}],
543
+ [:DQPOST, {:value=>"", :line=>1, :pos=>23, :offset=>22, :length=>2}],
544
+ ]
545
+ end
546
+ end
547
+ end
548
+
549
+
550
+ describe Puppet::Pops::Parser::Lexer,"when lexing strings" do
551
+ {
552
+ %q{'single quoted string')} => [[:STRING,'single quoted string']],
553
+ %q{"double quoted string"} => [[:STRING,'double quoted string']],
554
+ %q{'single quoted string with an escaped "\\'"'} => [[:STRING,'single quoted string with an escaped "\'"']],
555
+ %q{'single quoted string with an escaped "\$"'} => [[:STRING,'single quoted string with an escaped "\$"']],
556
+ %q{'single quoted string with an escaped "\."'} => [[:STRING,'single quoted string with an escaped "\."']],
557
+ %q{'single quoted string with an escaped "\r\n"'} => [[:STRING,'single quoted string with an escaped "\r\n"']],
558
+ %q{'single quoted string with an escaped "\n"'} => [[:STRING,'single quoted string with an escaped "\n"']],
559
+ %q{'single quoted string with an escaped "\\\\"'} => [[:STRING,'single quoted string with an escaped "\\\\"']],
560
+ %q{"string with an escaped '\\"'"} => [[:STRING,"string with an escaped '\"'"]],
561
+ %q{"string with an escaped '\\$'"} => [[:STRING,"string with an escaped '$'"]],
562
+ %Q{"string with a line ending with a backslash: \\\nfoo"} => [[:STRING,"string with a line ending with a backslash: foo"]],
563
+ %q{"string with $v (but no braces)"} => [[:DQPRE,"string with "],[:VARIABLE,'v'],[:DQPOST,' (but no braces)']],
564
+ %q["string with ${v} in braces"] => [[:DQPRE,"string with "],[:VARIABLE,'v'],[:DQPOST,' in braces']],
565
+ %q["string with ${qualified::var} in braces"] => [[:DQPRE,"string with "],[:VARIABLE,'qualified::var'],[:DQPOST,' in braces']],
566
+ %q{"string with $v and $v (but no braces)"} => [[:DQPRE,"string with "],[:VARIABLE,"v"],[:DQMID," and "],[:VARIABLE,"v"],[:DQPOST," (but no braces)"]],
567
+ %q["string with ${v} and ${v} in braces"] => [[:DQPRE,"string with "],[:VARIABLE,"v"],[:DQMID," and "],[:VARIABLE,"v"],[:DQPOST," in braces"]],
568
+ %q["string with ${'a nested single quoted string'} inside it."] => [[:DQPRE,"string with "],[:STRING,'a nested single quoted string'],[:DQPOST,' inside it.']],
569
+ %q["string with ${['an array ',$v2]} in it."] => [[:DQPRE,"string with "],:LBRACK,[:STRING,"an array "],:COMMA,[:VARIABLE,"v2"],:RBRACK,[:DQPOST," in it."]],
570
+ %q{a simple "scanner" test} => [[:NAME,"a"],[:NAME,"simple"], [:STRING,"scanner"],[:NAME,"test"]],
571
+ %q{a simple 'single quote scanner' test} => [[:NAME,"a"],[:NAME,"simple"], [:STRING,"single quote scanner"],[:NAME,"test"]],
572
+ %q{a harder 'a $b \c"'} => [[:NAME,"a"],[:NAME,"harder"], [:STRING,'a $b \c"']],
573
+ %q{a harder "scanner test"} => [[:NAME,"a"],[:NAME,"harder"], [:STRING,"scanner test"]],
574
+ %q{a hardest "scanner \"test\""} => [[:NAME,"a"],[:NAME,"hardest"],[:STRING,'scanner "test"']],
575
+ %Q{a hardestest "scanner \\"test\\"\n"} => [[:NAME,"a"],[:NAME,"hardestest"],[:STRING,%Q{scanner "test"\n}]],
576
+ %q{function("call")} => [[:NAME,"function"],[:LPAREN,"("],[:STRING,'call'],[:RPAREN,")"]],
577
+ %q["string with ${(3+5)/4} nested math."] => [[:DQPRE,"string with "],:LPAREN,[:NAME,"3"],:PLUS,[:NAME,"5"],:RPAREN,:DIV,[:NAME,"4"],[:DQPOST," nested math."]],
578
+ %q["$$$$"] => [[:STRING,"$$$$"]],
579
+ %q["$variable"] => [[:DQPRE,""],[:VARIABLE,"variable"],[:DQPOST,""]],
580
+ %q["$var$other"] => [[:DQPRE,""],[:VARIABLE,"var"],[:DQMID,""],[:VARIABLE,"other"],[:DQPOST,""]],
581
+ %q["foo$bar$"] => [[:DQPRE,"foo"],[:VARIABLE,"bar"],[:DQPOST,"$"]],
582
+ %q["foo$$bar"] => [[:DQPRE,"foo$"],[:VARIABLE,"bar"],[:DQPOST,""]],
583
+ %q[""] => [[:STRING,""]],
584
+ %q["123 456 789 0"] => [[:STRING,"123 456 789 0"]],
585
+ %q["${123} 456 $0"] => [[:DQPRE,""],[:VARIABLE,"123"],[:DQMID," 456 "],[:VARIABLE,"0"],[:DQPOST,""]],
586
+ %q["$foo::::bar"] => [[:DQPRE,""],[:VARIABLE,"foo"],[:DQPOST,"::::bar"]]
587
+ }.each { |src,expected_result|
588
+ it "should handle #{src} correctly" do
589
+ EgrammarLexerSpec.tokens_scanned_from(src).should be_like(*expected_result)
590
+ end
591
+ }
592
+ end
593
+
594
+ describe Puppet::Pops::Parser::Lexer::TOKENS[:DOLLAR_VAR] do
595
+ before { @token = Puppet::Pops::Parser::Lexer::TOKENS[:DOLLAR_VAR] }
596
+
597
+ it "should match against alpha words prefixed with '$'" do
598
+ @token.regex.should =~ '$this_var'
599
+ end
600
+
601
+ it "should return the VARIABLE token and the variable name stripped of the '$'" do
602
+ @token.convert(stub("lexer"), "$myval").should == [Puppet::Pops::Parser::Lexer::TOKENS[:VARIABLE], "myval"]
603
+ end
604
+ end
605
+
606
+ describe Puppet::Pops::Parser::Lexer::TOKENS[:REGEX] do
607
+ before { @token = Puppet::Pops::Parser::Lexer::TOKENS[:REGEX] }
608
+
609
+ it "should match against any expression enclosed in //" do
610
+ @token.regex.should =~ '/this is a regex/'
611
+ end
612
+
613
+ it 'should not match if there is \n in the regex' do
614
+ @token.regex.should_not =~ "/this is \n a regex/"
615
+ end
616
+
617
+ describe "when scanning" do
618
+ it "should not consider escaped slashes to be the end of a regex" do
619
+ EgrammarLexerSpec.tokens_scanned_from("$x =~ /this \\/ foo/").should be_like(__,__,[:REGEX,%r{this / foo}])
620
+ end
621
+
622
+ it "should not lex chained division as a regex" do
623
+ EgrammarLexerSpec.tokens_scanned_from("$x = $a/$b/$c").collect { |name, data| name }.should_not be_include( :REGEX )
624
+ end
625
+
626
+ it "should accept a regular expression after NODE" do
627
+ EgrammarLexerSpec.tokens_scanned_from("node /www.*\.mysite\.org/").should be_like(__,[:REGEX,Regexp.new("www.*\.mysite\.org")])
628
+ end
629
+
630
+ it "should accept regular expressions in a CASE" do
631
+ s = %q{case $variable {
632
+ "something": {$othervar = 4096 / 2}
633
+ /regex/: {notice("this notably sucks")}
634
+ }
635
+ }
636
+ EgrammarLexerSpec.tokens_scanned_from(s).should be_like(
637
+ :CASE,:VARIABLE,:LBRACE,:STRING,:COLON,:LBRACE,:VARIABLE,:EQUALS,:NAME,:DIV,:NAME,:RBRACE,[:REGEX,/regex/],:COLON,:LBRACE,:NAME,:LPAREN,:STRING,:RPAREN,:RBRACE,:RBRACE
638
+ )
639
+ end
640
+ end
641
+
642
+ it "should return the REGEX token and a Regexp" do
643
+ @token.convert(stub("lexer"), "/myregex/").should == [Puppet::Pops::Parser::Lexer::TOKENS[:REGEX], Regexp.new(/myregex/)]
644
+ end
645
+ end
646
+
647
+ describe Puppet::Pops::Parser::Lexer, "when lexing comments" do
648
+ before { @lexer = Puppet::Pops::Parser::Lexer.new }
649
+
650
+ it "should skip whitespace before lexing the next token after a non-token" do
651
+ EgrammarLexerSpec.tokens_scanned_from("/* 1\n\n */ \ntest").should be_like([:NAME, "test"])
652
+ end
653
+ end
654
+
655
+ # FIXME: We need to rewrite all of these tests, but I just don't want to take the time right now.
656
+ describe "Puppet::Pops::Parser::Lexer in the old tests" do
657
+ before { @lexer = Puppet::Pops::Parser::Lexer.new }
658
+
659
+ it "should do simple lexing" do
660
+ {
661
+ %q{\\} => [[:BACKSLASH,"\\"]],
662
+ %q{simplest scanner test} => [[:NAME,"simplest"],[:NAME,"scanner"],[:NAME,"test"]],
663
+ %Q{returned scanner test\n} => [[:NAME,"returned"],[:NAME,"scanner"],[:NAME,"test"]]
664
+ }.each { |source,expected|
665
+ EgrammarLexerSpec.tokens_scanned_from(source).should be_like(*expected)
666
+ }
667
+ end
668
+
669
+ it "should fail usefully" do
670
+ expect { EgrammarLexerSpec.tokens_scanned_from('^') }.to raise_error(RuntimeError)
671
+ end
672
+
673
+ it "should fail if the string is not set" do
674
+ expect { @lexer.fullscan }.to raise_error(Puppet::LexError)
675
+ end
676
+
677
+ it "should correctly identify keywords" do
678
+ EgrammarLexerSpec.tokens_scanned_from("case").should be_like([:CASE, "case"])
679
+ end
680
+
681
+ it "should correctly parse class references" do
682
+ %w{Many Different Words A Word}.each { |t| EgrammarLexerSpec.tokens_scanned_from(t).should be_like([:CLASSREF,t])}
683
+ end
684
+
685
+ # #774
686
+ it "should correctly parse namespaced class refernces token" do
687
+ %w{Foo ::Foo Foo::Bar ::Foo::Bar}.each { |t| EgrammarLexerSpec.tokens_scanned_from(t).should be_like([:CLASSREF, t]) }
688
+ end
689
+
690
+ it "should correctly parse names" do
691
+ %w{this is a bunch of names}.each { |t| EgrammarLexerSpec.tokens_scanned_from(t).should be_like([:NAME,t]) }
692
+ end
693
+
694
+ it "should correctly parse names with numerals" do
695
+ %w{1name name1 11names names11}.each { |t| EgrammarLexerSpec.tokens_scanned_from(t).should be_like([:NAME,t]) }
696
+ end
697
+
698
+ it "should correctly parse empty strings" do
699
+ expect { EgrammarLexerSpec.tokens_scanned_from('$var = ""') }.to_not raise_error
700
+ end
701
+
702
+ it "should correctly parse virtual resources" do
703
+ EgrammarLexerSpec.tokens_scanned_from("@type {").should be_like([:AT, "@"], [:NAME, "type"], [:LBRACE, "{"])
704
+ end
705
+
706
+ it "should correctly deal with namespaces" do
707
+ @lexer.string = %{class myclass}
708
+ @lexer.fullscan
709
+ @lexer.namespace.should == "myclass"
710
+
711
+ @lexer.namepop
712
+ @lexer.namespace.should == ""
713
+
714
+ @lexer.string = "class base { class sub { class more"
715
+ @lexer.fullscan
716
+ @lexer.namespace.should == "base::sub::more"
717
+
718
+ @lexer.namepop
719
+ @lexer.namespace.should == "base::sub"
720
+ end
721
+
722
+ it "should not put class instantiation on the namespace" do
723
+ @lexer.string = "class base { class sub { class { mode"
724
+ @lexer.fullscan
725
+ @lexer.namespace.should == "base::sub"
726
+ end
727
+
728
+ it "should correctly handle fully qualified names" do
729
+ @lexer.string = "class base { class sub::more {"
730
+ @lexer.fullscan
731
+ @lexer.namespace.should == "base::sub::more"
732
+
733
+ @lexer.namepop
734
+ @lexer.namespace.should == "base"
735
+ end
736
+
737
+ it "should correctly lex variables" do
738
+ ["$variable", "$::variable", "$qualified::variable", "$further::qualified::variable"].each do |string|
739
+ EgrammarLexerSpec.tokens_scanned_from(string).should be_like([:VARIABLE,string.sub(/^\$/,'')])
740
+ end
741
+ end
742
+
743
+ it "should end variables at `-`" do
744
+ EgrammarLexerSpec.tokens_scanned_from('$hyphenated-variable').
745
+ should be_like [:VARIABLE, "hyphenated"], [:MINUS, '-'], [:NAME, 'variable']
746
+ end
747
+
748
+ it "should not include whitespace in a variable" do
749
+ EgrammarLexerSpec.tokens_scanned_from("$foo bar").should_not be_like([:VARIABLE, "foo bar"])
750
+ end
751
+ it "should not include excess colons in a variable" do
752
+ EgrammarLexerSpec.tokens_scanned_from("$foo::::bar").should_not be_like([:VARIABLE, "foo::::bar"])
753
+ end
754
+ end
755
+
756
+ describe "Puppet::Pops::Parser::Lexer in the old tests when lexing example files" do
757
+ my_fixtures('*.pp') do |file|
758
+ it "should correctly lex #{file}" do
759
+ lexer = Puppet::Pops::Parser::Lexer.new
760
+ lexer.file = file
761
+ expect { lexer.fullscan }.to_not raise_error
762
+ end
763
+ end
764
+ end
765
+
766
+ describe "when trying to lex an non-existent file" do
767
+ include PuppetSpec::Files
768
+
769
+ it "should return an empty list of tokens" do
770
+ lexer = Puppet::Pops::Parser::Lexer.new
771
+ lexer.file = nofile = tmpfile('lexer')
772
+ File.exists?(nofile).should == false
773
+
774
+ lexer.fullscan.should == [[false,false]]
775
+ end
776
+ end
777
+
778
+ describe "when string quotes are not closed" do
779
+ it "should report with message including an \" opening quote" do
780
+ expect { EgrammarLexerSpec.tokens_scanned_from('$var = "') }.to raise_error(/after '"'/)
781
+ end
782
+
783
+ it "should report with message including an \' opening quote" do
784
+ expect { EgrammarLexerSpec.tokens_scanned_from('$var = \'') }.to raise_error(/after "'"/)
785
+ end
786
+
787
+ it "should report <eof> if immediately followed by eof" do
788
+ expect { EgrammarLexerSpec.tokens_scanned_from('$var = "') }.to raise_error(/followed by '<eof>'/)
789
+ end
790
+
791
+ it "should report max 5 chars following quote" do
792
+ expect { EgrammarLexerSpec.tokens_scanned_from('$var = "123456') }.to raise_error(/followed by '12345...'/)
793
+ end
794
+
795
+ it "should escape control chars" do
796
+ expect { EgrammarLexerSpec.tokens_scanned_from('$var = "12\n3456') }.to raise_error(/followed by '12\\n3...'/)
797
+ end
798
+
799
+ it "should resport position of opening quote" do
800
+ expect { EgrammarLexerSpec.tokens_scanned_from('$var = "123456') }.to raise_error(/at line 1:8/)
801
+ expect { EgrammarLexerSpec.tokens_scanned_from('$var = "123456') }.to raise_error(/at line 1:9/)
802
+ end
803
+ end
804
+
805
+ describe "when lexing number, bad input should not go unpunished" do
806
+ it "should slap bad octal as such" do
807
+ expect { EgrammarLexerSpec.tokens_scanned_from('$var = 0778') }.to raise_error(/Not a valid octal/)
808
+ end
809
+
810
+ it "should slap bad hex as such" do
811
+ expect { EgrammarLexerSpec.tokens_scanned_from('$var = 0xFG') }.to raise_error(/Not a valid hex/)
812
+ expect { EgrammarLexerSpec.tokens_scanned_from('$var = 0xfg') }.to raise_error(/Not a valid hex/)
813
+ end
814
+ # Note, bad decimals are probably impossible to enter, as they are not recognized as complete numbers, instead,
815
+ # the error will be something else, depending on what follows some initial digit.
816
+ #
817
+ end
818
+
819
+ describe "when lexing interpolation detailed positioning should be correct" do
820
+ it "should correctly position a string without interpolation" do
821
+ EgrammarLexerSpec.tokens_scanned_from('"not interpolated"').should be_like(
822
+ [:STRING, {:value=>"not interpolated", :line=>1, :offset=>0, :pos=>1, :length=>18}])
823
+ end
824
+
825
+ it "should correctly position a string with false start in interpolation" do
826
+ EgrammarLexerSpec.tokens_scanned_from('"not $$$ rpolated"').should be_like(
827
+ [:STRING, {:value=>"not $$$ rpolated", :line=>1, :offset=>0, :pos=>1, :length=>18}])
828
+ end
829
+
830
+ it "should correctly position pre-mid-end interpolation " do
831
+ EgrammarLexerSpec.tokens_scanned_from('"pre $x mid $y end"').should be_like(
832
+ [:DQPRE, {:value=>"pre ", :line=>1, :offset=>0, :pos=>1, :length=>6}],
833
+ [:VARIABLE, {:value=>"x", :line=>1, :offset=>6, :pos=>7, :length=>1}],
834
+ [:DQMID, {:value=>" mid ", :line=>1, :offset=>7, :pos=>8, :length=>6}],
835
+ [:VARIABLE, {:value=>"y", :line=>1, :offset=>13, :pos=>14, :length=>1}],
836
+ [:DQPOST, {:value=>" end", :line=>1, :offset=>14, :pos=>15, :length=>5}]
837
+ )
838
+ end
839
+
840
+ it "should correctly position pre-mid-end interpolation using ${} " do
841
+ EgrammarLexerSpec.tokens_scanned_from('"pre ${x} mid ${y} end"').should be_like(
842
+ [:DQPRE, {:value=>"pre ", :line=>1, :offset=>0, :pos=>1, :length=>7}],
843
+ [:VARIABLE, {:value=>"x", :line=>1, :offset=>7, :pos=>8, :length=>1}],
844
+ [:DQMID, {:value=>" mid ", :line=>1, :offset=>8, :pos=>9, :length=>8}],
845
+ [:VARIABLE, {:value=>"y", :line=>1, :offset=>16, :pos=>17, :length=>1}],
846
+ [:DQPOST, {:value=>" end", :line=>1, :offset=>17, :pos=>18, :length=>6}]
847
+ )
848
+ end
849
+
850
+ it "should correctly position pre-end interpolation using ${} with f call" do
851
+ EgrammarLexerSpec.tokens_scanned_from('"pre ${x()} end"').should be_like(
852
+ [:DQPRE, {:value=>"pre ", :line=>1, :offset=>0, :pos=>1, :length=>7}],
853
+ [:NAME, {:value=>"x", :line=>1, :offset=>7, :pos=>8, :length=>1}],
854
+ [:LPAREN, {:value=>"(", :line=>1, :offset=>8, :pos=>9, :length=>1}],
855
+ [:RPAREN, {:value=>")", :line=>1, :offset=>9, :pos=>10, :length=>1}],
856
+ [:DQPOST, {:value=>" end", :line=>1, :offset=>10, :pos=>11, :length=>6}]
857
+ )
858
+ end
859
+
860
+ it "should correctly position pre-end interpolation using ${} with $x" do
861
+ EgrammarLexerSpec.tokens_scanned_from('"pre ${$x} end"').should be_like(
862
+ [:DQPRE, {:value=>"pre ", :line=>1, :offset=>0, :pos=>1, :length=>7}],
863
+ [:VARIABLE, {:value=>"x", :line=>1, :offset=>7, :pos=>8, :length=>2}],
864
+ [:DQPOST, {:value=>" end", :line=>1, :offset=>9, :pos=>10, :length=>6}]
865
+ )
866
+ end
867
+
868
+ it "should correctly position pre-end interpolation across lines" do
869
+ EgrammarLexerSpec.tokens_scanned_from(%Q["pre ${\n$x} end"]).should be_like(
870
+ [:DQPRE, {:value=>"pre ", :line=>1, :offset=>0, :pos=>1, :length=>7}],
871
+ [:VARIABLE, {:value=>"x", :line=>2, :offset=>8, :pos=>1, :length=>2}],
872
+ [:DQPOST, {:value=>" end", :line=>2, :offset=>10, :pos=>3, :length=>6}]
873
+ )
874
+ end
875
+
876
+ it "should correctly position interpolation across lines when strings have embedded newlines" do
877
+ EgrammarLexerSpec.tokens_scanned_from(%Q["pre \n\n${$x}\n mid$y"]).should be_like(
878
+ [:DQPRE, {:value=>"pre \n\n", :line=>1, :offset=>0, :pos=>1, :length=>9}],
879
+ [:VARIABLE, {:value=>"x", :line=>3, :offset=>9, :pos=>3, :length=>2}],
880
+ [:DQMID, {:value=>"\n mid", :line=>3, :offset=>11, :pos=>5, :length=>7}],
881
+ [:VARIABLE, {:value=>"y", :line=>4, :offset=>18, :pos=>6, :length=>1}]
882
+ )
883
+ end
884
+ end