PageRenderTime 55ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 0ms

/test/plugins/orders.lua

https://github.com/warmist/dfhack
Lua | 266 lines | 221 code | 23 blank | 22 comment | 1 complexity | 3450a3ac0fabc3816f5295501cb28720 MD5 | raw file
  1. config.mode = 'fortress'
  2. local FILE_PATH_PATTERN = 'dfhack-config/orders/%s.json'
  3. local BACKUP_FILE_NAME = 'tmp-backup'
  4. local BACKUP_FILE_PATH = FILE_PATH_PATTERN:format(BACKUP_FILE_NAME)
  5. local TMP_FILE_NAME = 'tmp-test'
  6. local TMP_FILE_PATH = FILE_PATH_PATTERN:format(TMP_FILE_NAME)
  7. local function test_wrapper(test_fn)
  8. -- backup and clear active orders
  9. dfhack.run_command_silent{'orders', 'export', BACKUP_FILE_NAME}
  10. dfhack.run_command_silent{'orders', 'clear'}
  11. df.global.world.manager_order_next_id = 0
  12. return dfhack.with_finalize(
  13. function()
  14. -- clear test orders, restore original orders, remove temp files
  15. dfhack.run_command_silent{'orders', 'clear'}
  16. df.global.world.manager_order_next_id = 0
  17. dfhack.run_command_silent{'orders', 'import', BACKUP_FILE_NAME}
  18. df.global.world.manager_order_next_id =
  19. #df.global.world.manager_orders
  20. os.remove(BACKUP_FILE_PATH)
  21. os.remove(TMP_FILE_PATH)
  22. end,
  23. test_fn)
  24. end
  25. config.wrapper = test_wrapper
  26. -- returns export command result and exported file content
  27. function run_orders_export()
  28. local _, result = dfhack.run_command_silent{'orders', 'export',
  29. TMP_FILE_NAME}
  30. local f = io.open(TMP_FILE_PATH, 'r')
  31. return dfhack.with_finalize(
  32. function() f:close() end,
  33. function() return result, f:read('*all') end)
  34. end
  35. function run_orders_import(file_content)
  36. local f = io.open(TMP_FILE_PATH, 'w')
  37. f:write(file_content)
  38. f:close()
  39. return dfhack.run_command_silent{'orders', 'import', TMP_FILE_NAME}
  40. end
  41. local function normalize_whitespace(str)
  42. return str:gsub('%s+', ' '):trim()
  43. end
  44. function check_export_success(expected_file_content)
  45. local result, file_content = run_orders_export()
  46. expect.eq(result, CR_OK)
  47. -- ignore whitespace (otherwise the expected file content is impossible to
  48. -- format properly in this file)
  49. expect.eq(normalize_whitespace(expected_file_content),
  50. normalize_whitespace(file_content))
  51. end
  52. function check_import_success(file_content, comment, num_expected_orders)
  53. local prev_num_orders = #df.global.world.manager_orders
  54. local output, result = run_orders_import(file_content)
  55. expect.eq(result, CR_OK, comment)
  56. expect.eq(prev_num_orders + num_expected_orders,
  57. #df.global.world.manager_orders, comment)
  58. end
  59. function check_import_fail(file_content, comment, prefix)
  60. comment = comment or ''
  61. local prev_num_orders = #df.global.world.manager_orders
  62. local output, result = run_orders_import(file_content)
  63. expect.eq(result, CR_FAILURE, ('%s: was successful'):format(comment))
  64. if prefix then
  65. expect.true_(output:lower():startswith(prefix), ('%s: "%s" missing "%s"'):format(comment, output, prefix))
  66. end
  67. expect.eq(prev_num_orders, #df.global.world.manager_orders, ('%s: number of manager orders changed'):format(comment))
  68. end
  69. function test.import_empty()
  70. check_import_success('[]', 'empty input', 0)
  71. end
  72. function test.import_non_array()
  73. check_import_fail('{}', 'object', 'invalid')
  74. check_import_fail('null', 'null', 'invalid')
  75. check_import_fail('2', 'number', 'invalid')
  76. end
  77. function test.import_invalid_syntax()
  78. -- for https://github.com/DFHack/dfhack/pull/1770
  79. check_import_fail('', 'empty')
  80. check_import_fail(']', 'missing opening bracket')
  81. check_import_fail([[
  82. [
  83. {
  84. "amount_left" : 0,
  85. "amount_total" : 0,
  86. "frequency" : "OneTime",
  87. "id" : 0,
  88. "is_active" : false,
  89. "is_validated" : true,
  90. "job" : "CustomReaction",
  91. "reaction" : "BRASS_MAKING"
  92. }
  93. ]], 'missing closing bracket')
  94. end
  95. function test.import_missing_fields()
  96. check_import_fail('[{}]', 'empty order', 'invalid')
  97. end
  98. function test.import_invalid_id()
  99. -- for https://github.com/DFHack/dfhack/issues/1893
  100. check_import_fail([[
  101. [
  102. {
  103. "amount_left": 0,
  104. "amount_total": 0,
  105. "frequency": "OneTime",
  106. "id": "",
  107. "is_active": false,
  108. "is_validated": false,
  109. "item_category": [
  110. "finished_goods"
  111. ],
  112. "job": "EncrustWithGems",
  113. "material": "INORGANIC:AMBER OPAL"
  114. }
  115. ]
  116. ]], 'string id instead of int', 'error')
  117. end
  118. function test.import_valid_and_invalid_orders()
  119. -- check_import_fail([[
  120. -- [
  121. -- {
  122. -- "amount_left" : 1,
  123. -- "amount_total" : 1,
  124. -- "frequency" : "OneTime",
  125. -- "id" : 0,
  126. -- "is_active" : false,
  127. -- "is_validated" : true,
  128. -- "job" : "ConstructTable",
  129. -- "material" : "INORGANIC:IRON"
  130. -- },
  131. -- {}
  132. -- ]
  133. -- ]], 'empty order after valid order')
  134. check_import_fail([[
  135. [
  136. {},
  137. {
  138. "amount_left" : 1,
  139. "amount_total" : 1,
  140. "frequency" : "OneTime",
  141. "id" : 0,
  142. "is_active" : false,
  143. "is_validated" : true,
  144. "job" : "ConstructTable",
  145. "material" : "INORGANIC:IRON"
  146. }
  147. ]
  148. ]], 'empty order before valid order')
  149. end
  150. function test.import_export_reaction_condition()
  151. local file_content = [[
  152. [
  153. {
  154. "amount_left" : 1,
  155. "amount_total" : 1,
  156. "frequency" : "Daily",
  157. "id" : 0,
  158. "is_active" : false,
  159. "is_validated" : false,
  160. "item_conditions" :
  161. [
  162. {
  163. "condition" : "AtLeast",
  164. "contains" :
  165. [
  166. "lye"
  167. ],
  168. "reaction_id" : "MAKE_SOAP_FROM_TALLOW",
  169. "value" : 5
  170. }
  171. ],
  172. "job" : "CustomReaction",
  173. "reaction" : "MAKE_SOAP_FROM_TALLOW"
  174. }
  175. ]
  176. ]]
  177. check_import_success(file_content, 'valid reaction condition', 1)
  178. check_export_success(file_content)
  179. end
  180. local function get_last_order()
  181. return df.global.world.manager_orders[#df.global.world.manager_orders-1]
  182. end
  183. function test.import_invalid_reaction_conditions()
  184. check_import_success([[
  185. [
  186. {
  187. "amount_left" : 1,
  188. "amount_total" : 1,
  189. "frequency" : "OneTime",
  190. "id" : 0,
  191. "is_active" : false,
  192. "is_validated" : true,
  193. "item_conditions" :
  194. [
  195. {
  196. "condition" : "AtLeast",
  197. "contains" :
  198. [
  199. "lye"
  200. ],
  201. "reaction_id" : "MAKE_SOAP_FROM_TALLOW_xxx",
  202. "value" : 5
  203. }
  204. ],
  205. "job" : "CustomReaction",
  206. "reaction" : "MAKE_SOAP_FROM_TALLOW"
  207. }
  208. ]
  209. ]], 'condition ignored for bad reaction id', 1)
  210. expect.eq(0, #get_last_order().item_conditions)
  211. check_import_success([[
  212. [
  213. {
  214. "amount_left" : 1,
  215. "amount_total" : 1,
  216. "frequency" : "OneTime",
  217. "id" : 0,
  218. "is_active" : false,
  219. "is_validated" : true,
  220. "item_conditions" :
  221. [
  222. {
  223. "condition" : "AtLeast",
  224. "contains" :
  225. [
  226. "lye_xxx"
  227. ],
  228. "reaction_id" : "MAKE_SOAP_FROM_TALLOW",
  229. "value" : 5
  230. }
  231. ],
  232. "job" : "CustomReaction",
  233. "reaction" : "MAKE_SOAP_FROM_TALLOW"
  234. }
  235. ]
  236. ]], 'condition ignored for bad reagent name', 1)
  237. expect.eq(0, #get_last_order().item_conditions)
  238. end
  239. function test.list()
  240. local output, status = dfhack.run_command_silent('orders', 'list')
  241. expect.eq(CR_OK, status)
  242. expect.str_find(BACKUP_FILE_NAME:gsub('%-', '%%-'), output)
  243. end