mirror of
				https://github.com/SquidDev-CC/CC-Tweaked
				synced 2025-10-31 21:52:59 +00:00 
			
		
		
		
	Merge branch 'master' into mc-1.14.x
This commit is contained in:
		| @@ -30,12 +30,14 @@ import org.opentest4j.AssertionFailedError; | ||||
|  | ||||
| import javax.annotation.Nonnull; | ||||
| import javax.annotation.Nullable; | ||||
| import java.io.BufferedWriter; | ||||
| import java.io.File; | ||||
| import java.io.IOException; | ||||
| import java.io.Writer; | ||||
| import java.nio.channels.Channels; | ||||
| import java.nio.channels.WritableByteChannel; | ||||
| import java.nio.charset.StandardCharsets; | ||||
| import java.nio.file.Files; | ||||
| import java.util.*; | ||||
| import java.util.concurrent.TimeUnit; | ||||
| import java.util.concurrent.locks.Condition; | ||||
| @@ -58,6 +60,8 @@ import static dan200.computercraft.api.lua.ArgumentHelper.getType; | ||||
|  */ | ||||
| public class ComputerTestDelegate | ||||
| { | ||||
|     private static final File REPORT_PATH = new File( "test-files/luacov.report.out" ); | ||||
|  | ||||
|     private static final Logger LOG = LogManager.getLogger( ComputerTestDelegate.class ); | ||||
|  | ||||
|     private static final long TICK_TIME = TimeUnit.MILLISECONDS.toNanos( 50 ); | ||||
| @@ -77,12 +81,15 @@ public class ComputerTestDelegate | ||||
|  | ||||
|     private final Condition hasFinished = lock.newCondition(); | ||||
|     private boolean finished = false; | ||||
|     private Map<String, Map<Double, Double>> finishedWith; | ||||
|  | ||||
|     @BeforeEach | ||||
|     public void before() throws IOException | ||||
|     { | ||||
|         ComputerCraft.logPeripheralErrors = true; | ||||
|  | ||||
|         if( REPORT_PATH.delete() ) ComputerCraft.log.info( "Deleted previous coverage report." ); | ||||
|  | ||||
|         Terminal term = new Terminal( 78, 20 ); | ||||
|         IWritableMount mount = new FileMount( new File( "test-files/mount" ), 10_000_000 ); | ||||
|  | ||||
| @@ -264,6 +271,13 @@ public class ComputerTestDelegate | ||||
|                         try | ||||
|                         { | ||||
|                             finished = true; | ||||
|                             if( arguments.length > 0 ) | ||||
|                             { | ||||
|                                 @SuppressWarnings( "unchecked" ) | ||||
|                                 Map<String, Map<Double, Double>> finished = (Map<String, Map<Double, Double>>) arguments[0]; | ||||
|                                 finishedWith = finished; | ||||
|                             } | ||||
|  | ||||
|                             hasFinished.signal(); | ||||
|                         } | ||||
|                         finally | ||||
| @@ -281,7 +295,7 @@ public class ComputerTestDelegate | ||||
|     } | ||||
|  | ||||
|     @AfterEach | ||||
|     public void after() throws InterruptedException | ||||
|     public void after() throws InterruptedException, IOException | ||||
|     { | ||||
|         try | ||||
|         { | ||||
| @@ -316,6 +330,14 @@ public class ComputerTestDelegate | ||||
|             // And shutdown | ||||
|             computer.shutdown(); | ||||
|         } | ||||
|  | ||||
|         if( finishedWith != null ) | ||||
|         { | ||||
|             try( BufferedWriter writer = Files.newBufferedWriter( REPORT_PATH.toPath() ) ) | ||||
|             { | ||||
|                 new LuaCoverage( finishedWith ).write( writer ); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     @TestFactory | ||||
|   | ||||
							
								
								
									
										158
									
								
								src/test/java/dan200/computercraft/core/LuaCoverage.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										158
									
								
								src/test/java/dan200/computercraft/core/LuaCoverage.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,158 @@ | ||||
| /* | ||||
|  * This file is part of ComputerCraft - http://www.computercraft.info | ||||
|  * Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission. | ||||
|  * Send enquiries to dratcliffe@gmail.com | ||||
|  */ | ||||
|  | ||||
| package dan200.computercraft.core; | ||||
|  | ||||
| import com.google.common.base.Strings; | ||||
| import dan200.computercraft.ComputerCraft; | ||||
| import it.unimi.dsi.fastutil.ints.IntOpenHashSet; | ||||
| import it.unimi.dsi.fastutil.ints.IntSet; | ||||
| import org.squiddev.cobalt.Prototype; | ||||
| import org.squiddev.cobalt.compiler.CompileException; | ||||
| import org.squiddev.cobalt.compiler.LuaC; | ||||
|  | ||||
| import java.io.*; | ||||
| import java.nio.file.Files; | ||||
| import java.nio.file.Path; | ||||
| import java.util.*; | ||||
| import java.util.stream.Collectors; | ||||
| import java.util.stream.Stream; | ||||
|  | ||||
| class LuaCoverage | ||||
| { | ||||
|     private static final Path ROOT = new File( "src/main/resources/assets/computercraft/lua" ).toPath(); | ||||
|     private static final Path BIOS = ROOT.resolve( "bios.lua" ); | ||||
|     private static final Path APIS = ROOT.resolve( "rom/apis" ); | ||||
|     private static final Path SHELL = ROOT.resolve( "rom/programs/shell.lua" ); | ||||
|     private static final Path MULTISHELL = ROOT.resolve( "rom/programs/advanced/multishell.lua" ); | ||||
|     private static final Path TREASURE = ROOT.resolve( "treasure" ); | ||||
|  | ||||
|     private final Map<String, Map<Double, Double>> coverage; | ||||
|     private final String blank; | ||||
|     private final String zero; | ||||
|     private final String countFormat; | ||||
|  | ||||
|     LuaCoverage( Map<String, Map<Double, Double>> coverage ) | ||||
|     { | ||||
|         this.coverage = coverage; | ||||
|  | ||||
|         int max = (int) coverage.values().stream() | ||||
|             .flatMapToDouble( x -> x.values().stream().mapToDouble( y -> y ) ) | ||||
|             .max().orElse( 0 ); | ||||
|         int maxLen = Math.max( 1, (int) Math.ceil( Math.log10( max ) ) ); | ||||
|         blank = Strings.repeat( " ", maxLen + 1 ); | ||||
|         zero = Strings.repeat( "*", maxLen ) + "0"; | ||||
|         countFormat = "%" + (maxLen + 1) + "d"; | ||||
|     } | ||||
|  | ||||
|     void write( Writer out ) throws IOException | ||||
|     { | ||||
|         Files.find( ROOT, Integer.MAX_VALUE, ( path, attr ) -> attr.isRegularFile() && !path.startsWith( TREASURE ) ).forEach( path -> { | ||||
|             Path relative = ROOT.relativize( path ); | ||||
|             String full = relative.toString().replace( '\\', '/' ); | ||||
|             if( !full.endsWith( ".lua" ) ) return; | ||||
|  | ||||
|             Map<Double, Double> files = Stream.of( | ||||
|                 coverage.remove( "/" + full ), | ||||
|                 path.equals( BIOS ) ? coverage.remove( "bios.lua" ) : null, | ||||
|                 path.equals( SHELL ) ? coverage.remove( "shell.lua" ) : null, | ||||
|                 path.equals( MULTISHELL ) ? coverage.remove( "multishell.lua" ) : null, | ||||
|                 path.startsWith( APIS ) ? coverage.remove( path.getFileName().toString() ) : null | ||||
|             ) | ||||
|                 .filter( Objects::nonNull ) | ||||
|                 .flatMap( x -> x.entrySet().stream() ) | ||||
|                 .collect( Collectors.toMap( Map.Entry::getKey, Map.Entry::getValue, Double::sum ) ); | ||||
|  | ||||
|             try | ||||
|             { | ||||
|                 writeCoverageFor( out, path, files ); | ||||
|             } | ||||
|             catch( IOException e ) | ||||
|             { | ||||
|                 throw new UncheckedIOException( e ); | ||||
|             } | ||||
|         } ); | ||||
|  | ||||
|         for( String filename : coverage.keySet() ) | ||||
|         { | ||||
|             if( filename.startsWith( "/test-rom/" ) ) continue; | ||||
|             ComputerCraft.log.warn( "Unknown file {}", filename ); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private void writeCoverageFor( Writer out, Path fullName, Map<Double, Double> visitedLines ) throws IOException | ||||
|     { | ||||
|         if( !Files.exists( fullName ) ) | ||||
|         { | ||||
|             ComputerCraft.log.error( "Cannot locate file {}", fullName ); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         IntSet activeLines = getActiveLines( fullName.toFile() ); | ||||
|  | ||||
|         out.write( "==============================================================================\n" ); | ||||
|         out.write( fullName.toString().replace( '\\', '/' ) ); | ||||
|         out.write( "\n" ); | ||||
|         out.write( "==============================================================================\n" ); | ||||
|  | ||||
|         try( BufferedReader reader = Files.newBufferedReader( fullName ) ) | ||||
|         { | ||||
|             String line; | ||||
|             int lineNo = 0; | ||||
|             while( (line = reader.readLine()) != null ) | ||||
|             { | ||||
|                 lineNo++; | ||||
|                 Double count = visitedLines.get( (double) lineNo ); | ||||
|                 if( count != null ) | ||||
|                 { | ||||
|                     out.write( String.format( countFormat, count.intValue() ) ); | ||||
|                 } | ||||
|                 else if( activeLines.contains( lineNo ) ) | ||||
|                 { | ||||
|                     out.write( zero ); | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     out.write( blank ); | ||||
|                 } | ||||
|  | ||||
|                 out.write( ' ' ); | ||||
|                 out.write( line ); | ||||
|                 out.write( "\n" ); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private static IntSet getActiveLines( File file ) throws IOException | ||||
|     { | ||||
|         IntSet activeLines = new IntOpenHashSet(); | ||||
|         try( InputStream stream = new FileInputStream( file ) ) | ||||
|         { | ||||
|             Prototype proto = LuaC.compile( stream, "@" + file.getPath() ); | ||||
|             Queue<Prototype> queue = new ArrayDeque<>(); | ||||
|             queue.add( proto ); | ||||
|  | ||||
|             while( (proto = queue.poll()) != null ) | ||||
|             { | ||||
|                 int[] lines = proto.lineinfo; | ||||
|                 if( lines != null ) | ||||
|                 { | ||||
|                     for( int line : lines ) | ||||
|                     { | ||||
|                         activeLines.add( line ); | ||||
|                     } | ||||
|                 } | ||||
|                 if( proto.p != null ) Collections.addAll( queue, proto.p ); | ||||
|             } | ||||
|         } | ||||
|         catch( CompileException e ) | ||||
|         { | ||||
|             throw new IllegalStateException( "Cannot compile", e ); | ||||
|         } | ||||
|  | ||||
|         return activeLines; | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user
	 SquidDev
					SquidDev