15_config.t 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4. use Slic3r::XS;
  5. use Test::More tests => 159;
  6. use Data::Dumper;
  7. foreach my $config (Slic3r::Config->new, Slic3r::Config::Static::new_FullPrintConfig) {
  8. $config->set('layer_height', 0.3);
  9. ok abs($config->get('layer_height') - 0.3) < 1e-4, 'set/get float';
  10. is $config->serialize('layer_height'), '0.3', 'serialize float';
  11. $config->set('perimeters', 2);
  12. is $config->get('perimeters'), 2, 'set/get int';
  13. is $config->serialize('perimeters'), '2', 'serialize int';
  14. $config->set('extrusion_axis', 'A');
  15. is $config->get('extrusion_axis'), 'A', 'set/get string';
  16. is $config->serialize('extrusion_axis'), 'A', 'serialize string';
  17. $config->set('notes', "foo\nbar");
  18. is $config->get('notes'), "foo\nbar", 'set/get string with newline';
  19. is $config->serialize('notes'), 'foo\nbar', 'serialize string with newline';
  20. $config->set_deserialize('notes', 'bar\nbaz');
  21. is $config->get('notes'), "bar\nbaz", 'deserialize string with newline';
  22. foreach my $test_data (
  23. {
  24. name => 'empty',
  25. values => [],
  26. serialized => ''
  27. },
  28. {
  29. name => 'single empty',
  30. values => [''],
  31. serialized => '""'
  32. },
  33. {
  34. name => 'single noempty, simple',
  35. values => ['RGB'],
  36. serialized => 'RGB'
  37. },
  38. {
  39. name => 'multiple noempty, simple',
  40. values => ['ABC', 'DEF', '09182745@!#$*(&'],
  41. serialized => 'ABC;DEF;09182745@!#$*(&'
  42. },
  43. {
  44. name => 'multiple, simple, some empty',
  45. values => ['ABC', 'DEF', '', '09182745@!#$*(&', ''],
  46. serialized => 'ABC;DEF;;09182745@!#$*(&;'
  47. },
  48. {
  49. name => 'complex',
  50. values => ['some "quoted" notes', "yet\n some notes", "whatever \n notes", ''],
  51. serialized => '"some \"quoted\" notes";"yet\n some notes";"whatever \n notes";'
  52. }
  53. )
  54. {
  55. $config->set('filament_notes', $test_data->{values});
  56. is $config->serialize('filament_notes'), $test_data->{serialized}, 'serialize multi-string value ' . $test_data->{name};
  57. $config->set_deserialize('filament_notes', '');
  58. is_deeply $config->get('filament_notes'), [], 'deserialize multi-string value - empty ' . $test_data->{name};
  59. $config->set_deserialize('filament_notes', $test_data->{serialized});
  60. is_deeply $config->get('filament_notes'), $test_data->{values}, 'deserialize complex multi-string value ' . $test_data->{name};
  61. }
  62. $config->set('first_layer_height', 0.3);
  63. ok abs($config->get('first_layer_height') - 0.3) < 1e-4, 'set/get absolute floatOrPercent';
  64. is $config->serialize('first_layer_height'), '0.3', 'serialize absolute floatOrPercent';
  65. $config->set('first_layer_height', '50%');
  66. $config->get_abs_value('first_layer_height');
  67. ok abs($config->get_abs_value('first_layer_height') - 0.15) < 1e-4, 'set/get relative floatOrPercent';
  68. is $config->serialize('first_layer_height'), '50%', 'serialize relative floatOrPercent';
  69. # Uh-oh, we have no point option to test at the moment
  70. #ok $config->set('print_center', [50,80]), 'valid point coordinates';
  71. #is_deeply $config->get('print_center'), [50,80], 'set/get point';
  72. #is $config->serialize('print_center'), '50,80', 'serialize point';
  73. #$config->set_deserialize('print_center', '20,10');
  74. #is_deeply $config->get('print_center'), [20,10], 'deserialize point';
  75. #ok !$config->set('print_center', ['t',80]), 'invalid point X';
  76. #ok !$config->set('print_center', [50,'t']), 'invalid point Y';
  77. $config->set('use_relative_e_distances', 1);
  78. is $config->get('use_relative_e_distances'), 1, 'set/get bool';
  79. is $config->serialize('use_relative_e_distances'), '1', 'serialize bool';
  80. $config->set('gcode_flavor', 'teacup');
  81. is $config->get('gcode_flavor'), 'teacup', 'set/get enum';
  82. is $config->serialize('gcode_flavor'), 'teacup', 'serialize enum';
  83. $config->set_deserialize('gcode_flavor', 'mach3');
  84. is $config->get('gcode_flavor'), 'mach3', 'deserialize enum (gcode_flavor)';
  85. $config->set_deserialize('gcode_flavor', 'machinekit');
  86. is $config->get('gcode_flavor'), 'machinekit', 'deserialize enum (gcode_flavor)';
  87. $config->set_deserialize('fill_pattern', 'stars');
  88. is $config->get('fill_pattern'), 'stars', 'deserialize enum (fill_pattern)';
  89. $config->set_deserialize('support_material_pattern', 'pillars');
  90. is $config->get('support_material_pattern'), 'pillars', 'deserialize enum (support_material_pattern)';
  91. $config->set('extruder_offset', [[10,20],[30,45]]);
  92. is_deeply [ map $_->pp, @{$config->get('extruder_offset')} ], [[10,20],[30,45]], 'set/get points';
  93. $config->set('extruder_offset', [Slic3r::Pointf->new(10,20),Slic3r::Pointf->new(30,45)]);
  94. is_deeply [ map $_->pp, @{$config->get('extruder_offset')} ], [[10,20],[30,45]], 'set/get points';
  95. $config->set_deserialize('extruder_offset', $config->serialize('extruder_offset'));
  96. is $config->serialize('extruder_offset'), '10x20,30x45', 'serialize points';
  97. $config->set_deserialize('extruder_offset', '20x10');
  98. is_deeply [ map $_->pp, @{$config->get('extruder_offset')} ], [[20,10]], 'deserialize points';
  99. $config->set_deserialize('extruder_offset', '0x0');
  100. is_deeply [ map $_->pp, @{$config->get('extruder_offset')} ], [[0,0]], 'deserialize points';
  101. {
  102. my @values = ([10,20]);
  103. $values[2] = [10,20]; # implicitely extend array; this is not the same as explicitely assigning undef to second item
  104. ok !$config->set('extruder_offset', \@values), 'reject undef points';
  105. }
  106. # truncate ->get() to first decimal digit
  107. $config->set('nozzle_diameter', [0.2,3]);
  108. is_deeply [ map int($_*10)/10, @{$config->get('nozzle_diameter')} ], [0.2,3], 'set/get floats';
  109. is $config->serialize('nozzle_diameter'), '0.2,3', 'serialize floats';
  110. $config->set_deserialize('nozzle_diameter', '0.1,0.4');
  111. is_deeply [ map int($_*10)/10, @{$config->get('nozzle_diameter')} ], [0.1,0.4], 'deserialize floats';
  112. $config->set_deserialize('nozzle_diameter', '3');
  113. is_deeply [ map int($_*10)/10, @{$config->get('nozzle_diameter')} ], [3], 'deserialize a single float';
  114. {
  115. my @values = (0.4);
  116. $values[2] = 2; # implicitely extend array; this is not the same as explicitely assigning undef to second item
  117. ok !$config->set('nozzle_diameter', \@values), 'reject undef floats';
  118. }
  119. $config->set('temperature', [180,210]);
  120. is_deeply $config->get('temperature'), [180,210], 'set/get ints';
  121. is $config->serialize('temperature'), '180,210', 'serialize ints';
  122. $config->set_deserialize('temperature', '195,220');
  123. is_deeply $config->get('temperature'), [195,220], 'deserialize ints';
  124. {
  125. my @values = (180);
  126. $values[2] = 200; # implicitely extend array; this is not the same as explicitely assigning undef to second item
  127. ok !$config->set('temperature', \@values), 'reject undef ints';
  128. }
  129. $config->set('wipe', [1,0]);
  130. is_deeply $config->get('wipe'), [1,0], 'set/get bools';
  131. is $config->get_at('wipe', 0), 1, 'get_at bools';
  132. is $config->get_at('wipe', 1), 0, 'get_at bools';
  133. is $config->get_at('wipe', 9), 1, 'get_at bools';
  134. is $config->serialize('wipe'), '1,0', 'serialize bools';
  135. $config->set_deserialize('wipe', '0,1,1');
  136. is_deeply $config->get('wipe'), [0,1,1], 'deserialize bools';
  137. $config->set_deserialize('wipe', '');
  138. is_deeply $config->get('wipe'), [], 'deserialize bools from empty string';
  139. $config->set_deserialize('retract_layer_change', 0);
  140. is_deeply $config->get('retract_layer_change'), [0], 'deserialize bools from non-string value';
  141. {
  142. my @values = (1);
  143. $values[2] = 1; # implicitely extend array; this is not the same as explicitely assigning undef to second item
  144. ok !$config->set('wipe', \@values), 'reject undef bools';
  145. }
  146. $config->set('post_process', ['foo','bar']);
  147. is_deeply $config->get('post_process'), ['foo','bar'], 'set/get strings';
  148. is $config->serialize('post_process'), 'foo;bar', 'serialize strings';
  149. $config->set_deserialize('post_process', 'bar;baz');
  150. is_deeply $config->get('post_process'), ['bar','baz'], 'deserialize strings';
  151. {
  152. my @values = ('foo');
  153. $values[2] = 'bar'; # implicitely extend array; this is not the same as explicitely assigning undef to second item
  154. ok !$config->set('post_process', \@values), 'reject undef strings';
  155. }
  156. is_deeply [ sort @{$config->get_keys} ], [ sort keys %{$config->as_hash} ], 'get_keys and as_hash';
  157. }
  158. {
  159. my $config = Slic3r::Config->new;
  160. $config->set('perimeters', 2);
  161. # test that no crash happens when using set_deserialize() with a key that hasn't been set() yet
  162. $config->set_deserialize('filament_diameter', '3');
  163. my $config2 = Slic3r::Config::Static::new_FullPrintConfig;
  164. $config2->apply_dynamic($config);
  165. is $config2->get('perimeters'), 2, 'apply_dynamic';
  166. }
  167. {
  168. my $config = Slic3r::Config::Static::new_FullPrintConfig;
  169. my $config2 = Slic3r::Config->new;
  170. $config2->apply_static($config);
  171. is $config2->get('perimeters'), Slic3r::Config::print_config_def()->{perimeters}{default}, 'apply_static and print_config_def';
  172. $config->set('top_solid_infill_speed', 70);
  173. is $config->get_abs_value('top_solid_infill_speed'), 70, 'get_abs_value() works when ratio_over references a floatOrPercent option';
  174. }
  175. {
  176. my $config = Slic3r::Config->new;
  177. $config->set('fill_pattern', 'stars');
  178. my $config2 = Slic3r::Config->new;
  179. $config2->set('fill_pattern', 'hilbertcurve');
  180. is $config->get('fill_pattern'), 'stars', 'no interferences between DynamicConfig objects';
  181. }
  182. {
  183. my $config = Slic3r::Config->new;
  184. # the pair [0,0] is part of the test, since it checks whether the 0x0 serialized value is correctly parsed
  185. $config->set('extruder_offset', [ [0,0], [20,0], [0,20] ]);
  186. my $config2 = Slic3r::Config->new;
  187. $config2->apply($config);
  188. is_deeply [ map $_->pp, @{$config->get('extruder_offset')} ], [ map $_->pp, @{$config2->get('extruder_offset')} ],
  189. 'apply dynamic over dynamic';
  190. }
  191. {
  192. my $config = Slic3r::Config->new;
  193. $config->set('extruder', 2);
  194. $config->set('perimeter_extruder', 3);
  195. $config->normalize;
  196. ok !$config->has('extruder'), 'extruder option is removed after normalize()';
  197. is $config->get('infill_extruder'), 2, 'undefined extruder is populated with default extruder';
  198. is $config->get('perimeter_extruder'), 3, 'defined extruder is not overwritten by default extruder';
  199. }
  200. {
  201. my $config = Slic3r::Config->new;
  202. $config->set('infill_extruder', 2);
  203. $config->normalize;
  204. is $config->get('solid_infill_extruder'), 2, 'undefined solid infill extruder is populated with infill extruder';
  205. }
  206. {
  207. my $config = Slic3r::Config->new;
  208. $config->set('spiral_vase', 1);
  209. $config->set('retract_layer_change', [1,0]);
  210. $config->normalize;
  211. is_deeply $config->get('retract_layer_change'), [0,0], 'retract_layer_change is disabled with spiral_vase';
  212. }
  213. {
  214. use Cwd qw(abs_path);
  215. use File::Basename qw(dirname);
  216. my $class = Slic3r::Config->new;
  217. my $path = abs_path($0);
  218. my $config = $class->_load(dirname($path)."/inc/22_config_bad_config_options.ini");
  219. ok 1, 'did not crash on reading invalid items in config';
  220. }
  221. {
  222. my $parse = sub {
  223. my @argv = @_;
  224. my $config = Slic3r::Config->new;
  225. $config->read_cli(\@argv);
  226. return $config;
  227. };
  228. {
  229. my $config = $parse->(qw(--extra-perimeters --perimeters 1 --layer-height 0.45
  230. --fill-density 70% --detect-bridging-perimeters --notes=foobar));
  231. is $config->get('extra_perimeters'), 1, 'read_cli(): bool';
  232. is $config->get('perimeters'), 1, 'read_cli(): int';
  233. is $config->get('layer_height'), 0.45, 'read_cli(): float';
  234. is $config->serialize('fill_density'), '70%', 'read_cli(): percent';
  235. is $config->get('overhangs'), 1, 'read_cli(): alternative';
  236. is $config->get('notes'), 'foobar', 'read_cli(): key=val';
  237. }
  238. {
  239. my $config = $parse->(qw(--extra-perimeters --no-extra-perimeters));
  240. ok $config->has('extra_perimeters'), 'read_cli(): negated bool';
  241. is_deeply $config->get('extra_perimeters'), 0, 'read_cli(): negated bool';
  242. }
  243. {
  244. my $config = $parse->(qw(--wipe --no-wipe --wipe));
  245. is_deeply $config->get('wipe'), [1,0,1], 'read_cli(): bools array';
  246. }
  247. {
  248. my $config = $parse->(qw(--post-process foo --post-process bar));
  249. is_deeply $config->get('post_process'), ['foo', 'bar'], 'read_cli(): strings array';
  250. }
  251. {
  252. my $config = $parse->(qw(--retract-speed 0.4 --retract-speed 0.5));
  253. is_deeply $config->get('retract_speed'), [0.4, 0.5], 'read_cli(): floats array';
  254. }
  255. {
  256. no warnings 'qw';
  257. my $config = $parse->(qw(--extruder-offset 0,0 --extruder-offset 10x5));
  258. is_deeply [ map $_->pp, @{$config->get('extruder_offset')} ],
  259. [[0,0], [10,5]], 'read_cli(): points array';
  260. }
  261. }
  262. __END__