由成幻OnlineJudge学习如何做自己的Acm-Icpc在线评判系统-5.在线编译与测试系统代码粗解

简介: 由于近来很忙,加之此类文章少有人问津.所以少有时间写这一系列的文章的续篇 所以先把核心在线编译的代码发出来,细的部分大家可以查资料,或者留言问我^^ 部分类库可以查我以前的文章using System;using System.
由于近来很忙,加之此类文章少有人问津.所以少有时间写这一系列的文章的续篇
所以先把核心在线编译的代码发出来,细的部分大家可以查资料,或者留言问我^^
部分类库可以查我以前的文章
using  System;
using  System.Text;
using  System.Data;
using  System.Diagnostics;
using  System.Threading;
using  System.IO;

namespace  ChswordOJ {
    
///   <summary>
    
///  DoFile 进行在线编译与测试
    
///  Builder:邹健 2007 4 28
    
///  V1.0 2007 6 12
    
///   </summary>
     public   class  DoFile {
        StringBuilder _output 
=   new  StringBuilder();
        StringBuilder _TestOutput 
=   new  StringBuilder();
        StringBuilder _TestFile_Output 
=   new  StringBuilder();
        String _Test;
        String _CompilerName;
        StringBuilder _CompilerText 
=   new  StringBuilder();
        
private  Int64 _Memory, _myMemory;
        
private  Int32 _Time; // , _myTime;
         private  Option.AnswerStatus _TestResult;
        
private  String _ExePath;
        
private  String _CodePath;
        
private  String _TextPath;
        
private  String _TestPath;
        
private  Int64 _AnswerId;
        
private  String _Sign;
        
private  Boolean _TestEnd;
        Process _process;
        
///   <summary>
        
///  构造函数,对DoFile类进行初始化
        
///   </summary>
         public  DoFile() {
            _Memory 
=   23768 ;
            _Time 
=   3 ;
        }
        
///   <summary>
        
///  进行编译及测试代码。
        
///   </summary>
        
///   <param name="code"> 要编译的代码。 </param>
        
///   <param name="UserName"> 编译的用户名。 </param>
        
///   <param name="PassWord"> 用户密码。 </param>
        
///   <param name="QNum"> 代码的问题ID。 </param>
        
///   <param name="CompilerName"> 编译器。 </param>
         public   void  GetResult(String code, String UserName, String PassWord, String QNum, String CompilerName) {
            Option cp 
=   new  Option();
            DataSet ds 
=  cp.GetLimit(QNum);
            User u 
=   new  User(UserName, CompilerName.Split( ' , ' )[ 0 ], CompilerName.Split( ' , ' )[ 1 ]);
            _Memory 
=   int .Parse(ds.Tables[ 0 ].Rows[ 0 ][ 0 ].ToString()); // 从数据库读取当前的程序 要求的Memory
            _Time  =   int .Parse(ds.Tables[ 0 ].Rows[ 0 ][ 1 ].ToString()); // 从数据库读取当前的程序 要求的Time limit
            _Test  =  ds.Tables[ 0 ].Rows[ 0 ][ " test " ].ToString(); // 读取测试文件
            _CompilerName  =  CompilerName; // 编译器名称
            _Sign  =  u.Sign;
            _CodePath 
=  u.CodePath; // 源代码文件保存的路径
            _TextPath  =  u.TextPath; // 生成文本文件保存的路径
            _ExePath  =  u.ExePath; // EXE文件保存的路径
            _myMemory  =   0 ; // 对我当前耗费的内存进行初始化
            _TestPath  =  u.GetTestPath(QNum); // 得到当前测试路径
            _AnswerId  =  cp.AddAnswer(UserName, Int64.Parse(QNum), CompilerName); // 将当前数据作为一条回答存入数据库(创建一条数据库记录)
            Code cc  =   new  Code(CompilerName, code); // 创建Code实例
             if  (cc.Check()) { // 调用配置文件中的正则表达式,测试代码中有无危险代码,有,则此回答为危险代码

                SaveTextFile(u.CodePath, code);
// 将源代码保存为相应格式文件
                _CompilerText.AppendLine(u.CompilerString); //
                DoCmd(u.CompilerString); // 用u生成编译字符串,执行编译操作
                IsTempExists(u.TextPath, u.CompilerString); // 是否编译完成
                 if  ( 0   ==  _AnswerId)
                    
return ;
                cp.SetAnswerStatus(_AnswerId, Option.AnswerStatus.编译中);
                
// 编译完成
                 if  (IsCompilerSucess(u.TextPath, u.CodePath, u.ExePath,  0 )) { // 编译产生EXE则编译成功
                    
// 编译成功
                    cp.SetAnswerStatus(_AnswerId, Option.AnswerStatus.测试中);
                    ThreadStart thr_start_func 
=   new  ThreadStart(Test); // 异步调用Test进行测试
                    Thread fThread  =   new  Thread(thr_start_func);
                    fThread.Name 
=   " Test " ;
                    fThread.Start();
                    Thread.Sleep(_Time 
*   2000 ); // 初始化最大超时时间(规定时间的2倍)
                     if  (Option.AnswerStatus.测试通过  ==  _TestResult) {
                        
// cp.SetAnswerStatus(_AnswerId, Compiler.AnswerStatus.测试通过);
                    }
                    
else  {
                        
if  (_TestResult  ==   0 ) {
                            
try  {
                            
// 对进程查看是否结束,未结束则进行操作
                                 if  ( ! _process.HasExited) {
                                    
if  ( ! _process.CloseMainWindow())
                                        _process.Kill();
                                    
if  (_TestFile_Output.ToString().StartsWith(_TestOutput.ToString()))
                                        _TestResult 
=  Option.AnswerStatus.超时;
                                    
else
                                        _TestResult 
=  Option.AnswerStatus.测试失败;
                                }
                            }
                            
catch  {
                                _TestResult 
=  Option.AnswerStatus.测试失败;
                            }

                        }
                        
if  (fThread.IsAlive) fThread.Abort(); // 最终的强制结束进程
                    }
                }
                
else  {
                    _TestResult 
=  Option.AnswerStatus.编译失败;
                    cp.SetAnswerText(_AnswerId, ReplaceFileName(_CompilerText.ToString()));
                }

                
try  {
                    
if  (_TestResult  ==  Option.AnswerStatus.测试中  ||  _TestResult  ==  Option.AnswerStatus.测试失败) {
                        Process[] p 
=  Process.GetProcessesByName(_Sign);
                        
if  (p.Length  >   0 ) {
                            
if  ( ! p[ 0 ].HasExited) {
                                
if  (p[ 0 ].Responding) {
                                    p[
0 ].CloseMainWindow();
                                    p[
0 ].Kill();
                                }
                                
else  {
                                    p[
0 ].Kill();
                                }
                            }
                            
if  (_TestFile_Output.ToString().StartsWith(_TestOutput.ToString()))
                                _TestResult 
=  Option.AnswerStatus.超时;
                            
else
                                _TestResult 
=  Option.AnswerStatus.测试失败;
                        }
                    }
                }
                
catch  { }
            }
            
else  {
                _TestResult 
=  Option.AnswerStatus.危险代码;
            }

            cp.SetAnswerStatus(_AnswerId, _TestResult);
// 写入测试结果
            cp.SaveAnswerCode(_AnswerId, code); // 写入提交的源代码
             /* try {
                if (_TestResult == Option.AnswerStatus.测试通过) {
                    using (StreamReader sr = File.OpenText(_CodePath)) {
                        cp.SaveAnswerCode(_AnswerId, sr.ReadToEnd());
                    }
                }
            }
            catch { }
*/
            DeleteTempFile();
// 删除临时文件
        }

        
private   void  DeleteTempFile() { // 删除临时文件
            Byte b  =   0 ;
            
try  {
                Thread.Sleep(
1000 ); // 每一秒试删除一次
                 if  (File.Exists(_ExePath)) File.Delete(_ExePath);  else  b ++ ;
                
if  (File.Exists(_CodePath)) File.Delete(_CodePath);  else  b ++ ;
                
if  (File.Exists(_TextPath)) File.Delete(_TextPath);  else  b ++ ;
            }
            
catch  { }
            
if  (b  !=   3 ) DeleteTempFile(); // 递归调用
             return ;
        }
        
private   bool  IsCompilerSucess( string  TextPath,  string  CppPath, String ExePath,  int  count) {
            
try  { // 看是否编译成功的函数
                 using  (StreamReader sr  =   new  StreamReader(TextPath, Encoding.Default)) {
                    String input;
                    
bool  f  =   true ;
                    
while  ((input  =  sr.ReadLine())  !=   null ) {
                        _CompilerText.AppendLine(input);
                        
if  (input.Contains( " : error: " )) {

                            _output.AppendLine(input);
                        }
                        
else  {
                            
if  (f  &&   ! input.StartsWith(CppPath))
                                _output.AppendLine(input);
                            f 
=   false ;
                        }
                    }
                    sr.Close();
                    
if  (File.Exists(ExePath)) {
                        
return   true ;
                    }
                    
else  {
                        _output.Insert(
0 " 编译出错:\r\n " );
                        
return   false ;
                    }
                }
            }
            
catch  {
            }
            Thread.Sleep(
1000 );
            
if  (count  >=   300 ) {
                _CompilerText.Insert(
0 " 服务器响应超时或您选择的编译器不正确 " );
                
return   false ;
            }
            
return  IsCompilerSucess(TextPath, CppPath, ExePath, count  +   1 );
        }
        
private   string  ReplaceFileName( string  input) {
            input 
=  System.Text.RegularExpressions.Regex.Replace(input,  @" ([A-Z]:[\\|\/][^:\*\?<>\|]+\.(txt|cs|cpp|c|vb|jsl|js|exe))|(\\{2}[^/:\*\?<>\|]+\.(txt|cs|cpp|c|vb|jsl|js|exe)) " " > " , System.Text.RegularExpressions.RegexOptions.IgnoreCase);
            
return  input;
        }
        
private   void  Process_Exited( object  sender, EventArgs e) { // 测试程序是否超时的判断
             if  (_process.TotalProcessorTime.Milliseconds  >  _Time * 1000 ) {
                
if  (_TestFile_Output.ToString().StartsWith(_TestOutput.ToString()))
                    _TestResult 
=  Option.AnswerStatus.超时;
                
else
                    _TestResult 
=  Option.AnswerStatus.测试失败;
            }
        }
        
private   void  Test() { // 进行测试
             string  ExePath  =  _ExePath;
            
string  TestPath  =  _TestPath;
            String input;
            
bool  f  =   true ;
            _TestEnd 
=   false ;
            _process 
=   new  Process();
            _process.StartInfo.WindowStyle 
=  ProcessWindowStyle.Hidden;
            _process.StartInfo.UseShellExecute 
=   false ;
            _process.StartInfo.CreateNoWindow 
=   true ;
            _process.StartInfo.RedirectStandardInput 
=   true ;
            _process.StartInfo.RedirectStandardOutput 
=   true ;
            _process.StartInfo.RedirectStandardError 
=   true ;
            _process.StartInfo.FileName 
=  ExePath;
            _process.Exited 
+=   new  EventHandler(Process_Exited);
            _process.OutputDataReceived 
+=   new  DataReceivedEventHandler(TestOutputHandler);
            _process.Start();
            _process.BeginOutputReadLine();
            _myMemory 
=  (_process.PeakWorkingSet64  >>   10 ); // 获取内存大小
            StreamWriter sortStreamWriter  =  _process.StandardInput; // 设置异步读取流
             try  {
                
using  (StringReader sr  =   new  StringReader(_Test)) {
                    
while  (((input  =  sr.ReadLine())  !=   null )) {
                        
if  (input.StartsWith( " EOF " )) // C/C++程序的结束(CTRL+Z)方式
                             if  (_CompilerName.ToLower()  ==   " c "   ||  _CompilerName.ToLower()  ==   " cpp " )
                                sortStreamWriter.WriteLine(((
char ) 26 ).ToString());
                            
else // .net程序的结束(CTRL+Z)方式
                                _process.CloseMainWindow();
                        
if  (input.StartsWith( " > " )) // 测试的写操作
                            sortStreamWriter.WriteLine(input.Substring( 1 ));
                        
if  (input.StartsWith( " < " )) // 测试的读操作
                            _TestFile_Output.AppendLine(input.Substring( 1 ));
                    }
                }
                sortStreamWriter.Close();
                _process.WaitForExit();
                _TestEnd 
=   true ;
            }
            
catch  {
                _TestEnd 
=   true ;
            }

            
if  (_TestOutput.ToString()  ==  _TestFile_Output.ToString())
                f 
=   true ;
            
else
                f 
=   false ;
            
if  (_TestEnd  &&  f)
                _TestResult 
=  Option.AnswerStatus.测试通过;
            
else  {

            }
            
if  (_TestEnd  &&  (_myMemory  >  _Memory)) // 内存消耗太大
            {
                _TestResult 
=  Option.AnswerStatus.内存超量;
            }
            _process.Close();
            _process.Dispose();
            
if  (f  &&  _TestEnd) {
                _TestResult 
=  Option.AnswerStatus.测试通过;
            }
            
return ;

        }
        
void  SaveTextFile( string  Path,  string  text) {
            
using  (StreamWriter sw  =   new  StreamWriter(Path)) { sw.Write(text); }
        }
        
void  DoCmd( string  cmd) { // 执行一条CMD命令的函数
            Process process  =   new  Process();
            process.StartInfo.WindowStyle 
=  ProcessWindowStyle.Hidden;
            process.StartInfo.UseShellExecute 
=   false ;
            process.StartInfo.CreateNoWindow 
=   true ;
            process.StartInfo.RedirectStandardInput 
=   true ;
            process.StartInfo.RedirectStandardError 
=   true ;
            process.StartInfo.FileName 
=   " cmd.exe " ;
            process.Start();
            process.StandardInput.WriteLine(cmd);
            process.StandardInput.WriteLine(
" \r\nexit " );
            process.Close();
            process.Dispose();
        }
        
bool  IsTempExists(String TextPath, String CompilerString) {
            
int  i  =   0 ;
            
while  ( ! File.Exists(TextPath)) {
                Thread.Sleep(
1000 );
                i
++ ;
                
if  (i  >   178 return   false ;
                
if  (i  %   30   ==   0   &&  i  >   10 ) {
                    DoCmd(CompilerString);
                }
            }
            
return   true ;
        }
        
private   void  TestOutputHandler( object  sendingProcess,
            DataReceivedEventArgs outLine) {
            
int  numOutputLines  =   0 ;
            
if  ( ! String.IsNullOrEmpty(outLine.Data)) {
                numOutputLines
++ ;
                
// Environment.NewLine +"[" + numOutputLines.ToString() + "] - " + 
                _TestOutput.AppendLine(outLine.Data);
            }
        }
    }

}

上篇:由成幻OnlineJudge学习如何做自己的Acm-Icpc在线评判系统-4.建立基本的网站类库
目录
相关文章
|
30天前
|
设计模式 安全 测试技术
【软件设计师备考 专题 】系统实施:程序设计和系统测试
【软件设计师备考 专题 】系统实施:程序设计和系统测试
64 0
|
30天前
|
Java 关系型数据库 数据库连接
Mybatis+MySQL动态分页查询数据经典案例(含代码以及测试)
Mybatis+MySQL动态分页查询数据经典案例(含代码以及测试)
26 1
|
2月前
|
测试技术
包含用例执行时间的测试报告代码
包含用例执行时间的测试报告代码
|
3月前
|
Kubernetes NoSQL 网络协议
VS2017编译TarsCpp测试工程
VS2017编译TarsCpp测试工程
|
3月前
|
算法 异构计算 索引
m基于FPGA的Hamming汉明编译码verilog实现,包含testbench测试文件,不使用IP核
m基于FPGA的Hamming汉明编译码verilog实现,包含testbench测试文件,不使用IP核
42 1
|
1月前
|
算法
m基于OFDM+QPSK和LDPC编译码以及MMSE信道估计的无线图像传输matlab仿真,输出误码率,并用图片进行测试
MATLAB2022a仿真实现了无线图像传输的算法,包括OFDM、QPSK调制、LDPC编码和MMSE信道估计。OFDM抗频率选择性衰落,QPSK用相位表示二进制,LDPC码用于前向纠错,MMSE估计信道响应。算法流程涉及编码、调制、信道估计、均衡、解码和图像重建。MATLAB代码展示了从串行数据到OFDM信号的生成,经过信道模型、噪声添加,再到接收端的信道估计和解码过程,最终计算误码率。
21 1
|
4天前
|
消息中间件 网络协议 物联网
如何入门做物联网系统压测?
【4月更文挑战第18天】物联网系统在架构、网络模式、通信协议等方面与传统的互联网系统有所区别。因此,传统的性能测试方法不能直接套用到物联网系统中。
65 13
如何入门做物联网系统压测?
|
1月前
|
算法 异构计算
m基于FPGA的RS+卷积级联编译码实现,RS用IP核实现,卷积用verilog实现,包含testbench测试文件
m基于FPGA的RS+卷积级联编译码实现,RS用IP核实现,卷积用verilog实现,包含testbench测试文件
13 0
|
15天前
|
算法 安全 Java
java代码 实现AES_CMAC 算法测试
该代码实现了一个AES-CMAC算法的简单测试,使用Bouncy Castle作为安全提供者。静态变量K定义了固定密钥。`Aes_Cmac`函数接受密钥和消息,返回AES-CMAC生成的MAC值。在`main`方法中,程序对给定的消息进行AES-CMAC加密,然后模拟接收ECU的加密结果并进行比较。如果两者匹配,输出&quot;验证成功&quot;,否则输出&quot;验证失败&quot;。辅助方法包括将字节转为16进制字符串和将16进制字符串转为字节。
|
29天前
|
监控 安全 Shell
深入探究App压力测试的关键要点:从零开始学习Monkey
Monkey是Google的自动化测试工具,用于模拟用户随机事件以测试应用的稳定性和压力。它可以在模拟器或设备上运行,通过随机点击发现潜在问题。
25 1

热门文章

最新文章