mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-31 12:41:20 -06:00 
			
		
		
		
	New testing framework
This commit is contained in:
		
							parent
							
								
									8ae96a8868
								
							
						
					
					
						commit
						2abf2be781
					
				
					 4 changed files with 176 additions and 13 deletions
				
			
		
							
								
								
									
										2
									
								
								MANIFEST
									
										
									
									
									
								
							
							
						
						
									
										2
									
								
								MANIFEST
									
										
									
									
									
								
							|  | @ -45,6 +45,7 @@ lib/Slic3r/Print/Region.pm | ||||||
| lib/Slic3r/Print/Object.pm | lib/Slic3r/Print/Object.pm | ||||||
| lib/Slic3r/Surface.pm | lib/Slic3r/Surface.pm | ||||||
| lib/Slic3r/SVG.pm | lib/Slic3r/SVG.pm | ||||||
|  | lib/Slic3r/Test.pm | ||||||
| lib/Slic3r/TriangleMesh.pm | lib/Slic3r/TriangleMesh.pm | ||||||
| MANIFEST			This list of files | MANIFEST			This list of files | ||||||
| README.markdown | README.markdown | ||||||
|  | @ -58,6 +59,7 @@ t/dynamic.t | ||||||
| t/fill.t | t/fill.t | ||||||
| t/geometry.t | t/geometry.t | ||||||
| t/polyclip.t | t/polyclip.t | ||||||
|  | t/retract.t | ||||||
| t/serialize.t | t/serialize.t | ||||||
| t/stl.t | t/stl.t | ||||||
| utils/amf-to-stl.pl | utils/amf-to-stl.pl | ||||||
|  |  | ||||||
|  | @ -434,9 +434,9 @@ sub export_gcode { | ||||||
|     $self->make_brim;  # must come after make_skirt |     $self->make_brim;  # must come after make_skirt | ||||||
|      |      | ||||||
|     # output everything to a G-code file |     # output everything to a G-code file | ||||||
|     my $output_file = $self->expanded_output_filepath($params{output_file}); |     my $output_file = $params{output_file} ? $self->expanded_output_filepath($params{output_file}) : ''; | ||||||
|     $status_cb->(90, "Exporting G-code to $output_file"); |     $status_cb->(90, "Exporting G-code to $output_file"); | ||||||
|     $self->write_gcode($output_file); |     $self->write_gcode($params{output_fh} || $output_file); | ||||||
|      |      | ||||||
|     # run post-processing scripts |     # run post-processing scripts | ||||||
|     if (@{$Slic3r::Config->post_process}) { |     if (@{$Slic3r::Config->post_process}) { | ||||||
|  | @ -449,14 +449,16 @@ sub export_gcode { | ||||||
|     } |     } | ||||||
|      |      | ||||||
|     # output some statistics |     # output some statistics | ||||||
|     $self->processing_time(tv_interval($t0)); |     unless ($params{quiet}) { | ||||||
|     printf "Done. Process took %d minutes and %.3f seconds\n",  |         $self->processing_time(tv_interval($t0)); | ||||||
|         int($self->processing_time/60), |         printf "Done. Process took %d minutes and %.3f seconds\n",  | ||||||
|         $self->processing_time - int($self->processing_time/60)*60; |             int($self->processing_time/60), | ||||||
|  |             $self->processing_time - int($self->processing_time/60)*60; | ||||||
|          |          | ||||||
|     # TODO: more statistics! |         # TODO: more statistics! | ||||||
|     printf "Filament required: %.1fmm (%.1fcm3)\n", |         printf "Filament required: %.1fmm (%.1fcm3)\n", | ||||||
|         $self->total_extrusion_length, $self->total_extrusion_volume; |             $self->total_extrusion_length, $self->total_extrusion_volume; | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| sub export_svg { | sub export_svg { | ||||||
|  | @ -643,9 +645,14 @@ sub write_gcode { | ||||||
|     my $self = shift; |     my $self = shift; | ||||||
|     my ($file) = @_; |     my ($file) = @_; | ||||||
|      |      | ||||||
|     # open output gcode file |     # open output gcode file if we weren't supplied a file-handle | ||||||
|     open my $fh, ">", $file |     my $fh; | ||||||
|         or die "Failed to open $file for writing\n"; |     if (ref $file eq 'IO::Scalar') { | ||||||
|  |         $fh = $file; | ||||||
|  |     } else { | ||||||
|  |         open $fh, ">", $file | ||||||
|  |             or die "Failed to open $file for writing\n"; | ||||||
|  |     } | ||||||
|      |      | ||||||
|     # write some information |     # write some information | ||||||
|     my @lt = localtime; |     my @lt = localtime; | ||||||
|  |  | ||||||
							
								
								
									
										112
									
								
								lib/Slic3r/Test.pm
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										112
									
								
								lib/Slic3r/Test.pm
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,112 @@ | ||||||
|  | package Slic3r::Test; | ||||||
|  | use strict; | ||||||
|  | use warnings; | ||||||
|  | 
 | ||||||
|  | use IO::Scalar; | ||||||
|  | use Slic3r::Geometry qw(epsilon); | ||||||
|  | 
 | ||||||
|  | sub init_print { | ||||||
|  |     my ($model_name, %params) = @_; | ||||||
|  |      | ||||||
|  |     my $model = Slic3r::Model->new; | ||||||
|  |     { | ||||||
|  |         my ($vertices, $facets); | ||||||
|  |         if ($model_name eq '20mm_cube') { | ||||||
|  |             $vertices = [ | ||||||
|  |                 [10,10,-10], [10,-10,-10], [-10,-10,-10], [-10,10,-10], [10,10,10], [-10,10,10], [-10,-10,10], [10,-10,10], | ||||||
|  |             ]; | ||||||
|  |             $facets = [ | ||||||
|  |                 [0,1,2], [0,2,3], [4,5,6], [4,6,7], [0,4,7], [0,7,1], [1,7,6], [1,6,2], [2,6,5], [2,5,3], [4,0,3], [4,3,5], | ||||||
|  |             ], | ||||||
|  |         } | ||||||
|  |         $model->add_object(vertices => $vertices)->add_volume(facets => $facets); | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     my $config = Slic3r::Config->new_from_defaults; | ||||||
|  |     $config->apply($params{config}) if $params{config}; | ||||||
|  |      | ||||||
|  |     my $print = Slic3r::Print->new(config => $config); | ||||||
|  |     $print->add_model($model); | ||||||
|  |     $print->validate; | ||||||
|  |      | ||||||
|  |     return $print; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | sub gcode { | ||||||
|  |     my ($print) = @_; | ||||||
|  |      | ||||||
|  |     my $fh = IO::Scalar->new(\my $gcode); | ||||||
|  |     $print->export_gcode(output_fh => $fh, quiet => 1); | ||||||
|  |     $fh->close; | ||||||
|  |      | ||||||
|  |     return $gcode; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | sub compare { | ||||||
|  |     my ($a, $b) = @_; | ||||||
|  |     return abs($a - $b) < epsilon; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | package Slic3r::Test::GCodeReader; | ||||||
|  | use Moo; | ||||||
|  | 
 | ||||||
|  | has 'gcode' => (is => 'ro', required => 1); | ||||||
|  | has 'X' => (is => 'rw', default => sub {0}); | ||||||
|  | has 'Y' => (is => 'rw', default => sub {0}); | ||||||
|  | has 'Z' => (is => 'rw', default => sub {0}); | ||||||
|  | has 'E' => (is => 'rw', default => sub {0}); | ||||||
|  | has 'F' => (is => 'rw', default => sub {0}); | ||||||
|  | 
 | ||||||
|  | our $Verbose = 0; | ||||||
|  | my @AXES = qw(X Y Z E F); | ||||||
|  | 
 | ||||||
|  | sub parse { | ||||||
|  |     my $self = shift; | ||||||
|  |     my ($cb) = @_; | ||||||
|  |      | ||||||
|  |     foreach my $line (split /\n/, $self->gcode) { | ||||||
|  |         $line =~ s/\s*;(.*)//; # strip comment | ||||||
|  |         next if $line eq ''; | ||||||
|  |         my $comment = $1; | ||||||
|  |          | ||||||
|  |         # parse command | ||||||
|  |         my ($command, @args) = split /\s+/, $line; | ||||||
|  |         my %args = map { /([A-Z])(.*)/; ($1 => $2) } @args; | ||||||
|  |         my %info = (); | ||||||
|  |          | ||||||
|  |         # check retraction | ||||||
|  |         if ($command =~ /^G[01]$/) { | ||||||
|  |             if (!exists $args{E}) { | ||||||
|  |                 $info{travel} = 1; | ||||||
|  |             } | ||||||
|  |             foreach my $axis (@AXES) { | ||||||
|  |                 if (!exists $args{$axis}) { | ||||||
|  |                     $info{"dist_$axis"} = 0; | ||||||
|  |                     next; | ||||||
|  |                 } | ||||||
|  |                 $info{"dist_$axis"} = $args{$axis} - $self->$axis; | ||||||
|  |             } | ||||||
|  |             $info{dist_XY} = Slic3r::Line->new([0,0], [@info{qw(dist_X dist_Y)}])->length; | ||||||
|  |             if (exists $args{E}) { | ||||||
|  |                 ($info{dist_E} > 0) | ||||||
|  |                     ? ($info{extruding} = 1) | ||||||
|  |                     : ($info{retracting} = 1); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         # run callback | ||||||
|  |         printf "$line\n" if $Verbose; | ||||||
|  |         $cb->($self, $command, \%args, \%info); | ||||||
|  |          | ||||||
|  |         # update coordinates | ||||||
|  |         if ($command =~ /^(?:G[01]|G92)$/) { | ||||||
|  |             for (@AXES) { | ||||||
|  |                 $self->$_($args{$_}) if exists $args{$_}; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         # TODO: update temperatures | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 1; | ||||||
							
								
								
									
										42
									
								
								t/retraction.t
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								t/retraction.t
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,42 @@ | ||||||
|  | use Test::More; | ||||||
|  | use strict; | ||||||
|  | use warnings; | ||||||
|  | 
 | ||||||
|  | BEGIN { | ||||||
|  |     use FindBin; | ||||||
|  |     use lib "$FindBin::Bin/../lib"; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | use Slic3r; | ||||||
|  | use Slic3r::Geometry qw(epsilon); | ||||||
|  | use Slic3r::Test; | ||||||
|  | 
 | ||||||
|  | { | ||||||
|  |     my $config = Slic3r::Config->new( | ||||||
|  |         retract_length          => [1.5], | ||||||
|  |         retract_before_travel   => [3], | ||||||
|  |     ); | ||||||
|  |     my $print = Slic3r::Test::init_print('20mm_cube', config => $config); | ||||||
|  |      | ||||||
|  |     my $retracted = 1;  # ignore the first travel move from home to first point | ||||||
|  |     Slic3r::Test::GCodeReader->new(gcode => Slic3r::Test::gcode($print))->parse(sub { | ||||||
|  |         my ($self, $cmd, $args, $info) = @_; | ||||||
|  |          | ||||||
|  |         if ($info->{retracting}) { | ||||||
|  |             ok Slic3r::Test::compare(-$info->{dist_E}, $config->retract_length->[0]), | ||||||
|  |                 'retracted by the right amount'; | ||||||
|  |             $retracted = 1; | ||||||
|  |         } | ||||||
|  |         if ($info->{extruding}) { | ||||||
|  |             $retracted = 0; | ||||||
|  |         } | ||||||
|  |         if ($info->{travel} && $info->{dist_XY} >= $config->retract_before_travel->[0]) { | ||||||
|  |             ok $retracted, | ||||||
|  |                 'retracted before long travel move'; | ||||||
|  |         } | ||||||
|  |     }); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | done_testing; | ||||||
|  | 
 | ||||||
|  | __END__ | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Alessandro Ranellucci
						Alessandro Ranellucci