主页 > 测试知识 > 分布式文件系统底层功能测试【原创】

分布式文件系统底层功能测试【原创】

2013年3月6日 发表评论 查看评论
cloudfs文件系统正确性,完整性验证:
对于上一层的应用程序而言,cloudfs文件系统的底层只提供上传,下载,删除功能。
明月需要验证这三个功能的正确性和完整性。需要先了解文件系统的构架以及工作方法。
上传功能:当一个文件上传时,cloudfs返回一个storageid,这个ID在整个文件系统是唯一的。并且在这个文件上传前,cloudfs会根据将要上传的文件的MD5,CRC32以及文件大小,在底层比对是否存在相同文件,如果有,就直接返回一个storageid给客户端,并将文件的引用计数加1。如果没有,则上传该文件,将文件的md5+crc32+size保存到redis里面,在将文件引用计数设置为1.
下载功能:通过nginx,直接将硬盘上的目录映射出来。
删除功能: 当一个文件删除时,找到这个文件对应的md5+crc32+size,将引用计算减1,当引用计数为0时,文件进入cloud-mq,等待销毁。cloud-mq是自主研发的消息队列,用于消息推送。
 
虽然只有简单的三个功能,但是测试却不简单。
 
第一个脚本:上传一个新文件到cloudfs
随机生成一个文件到/upload目录,使用的是系统自带的随机字符设备/dev/random。共获取1000行,行的定义其实就与遇到/r/n算一行,也就是文件大小也是不定的。不过一般都在2M以下。之后计算这个文件的MD5值,再上传到文件系统。上传完会获取到一个storageid。脚本根据这个storageid下载这个文件到download目录,然后计算下载文件的MD5值,比对是否是一致的。之后将storageid作为key,将filename+MD5作为value,存入到redis数据库中。在清空download目录中刚刚下载的文件。在存入redis之前,检索一下redis中是否已经存在这个storgid,这点是验证storageid是否会出现碰撞。如果出现碰撞,则一个storageid对应两个文件,这样文件系统就出毛病了。storageid必须是文件的唯一标识。
#!/usr/bin/perl
###############################################################################
# 文件系统测试脚本1–上传新文件
# 2012-11-22   V01.00.000  新建程序
###############################################################################
use strict;
use constant VERSION => "V01.00.000";          #版本号
use Data::Dumper;
use Digest::MD5;
use Redis;
 
die("usage: $0 <ident> <cnt>\n") if ($#ARGV != 1);
 
my $upload_path="/home/upload/";                   #保存上传文件的目录。
my $download_path="/home/download/";               #保存下载文件的目录,文件名是上传的文件名。
 
my ($ident,$cnt) = @ARGV;
my $redis = Redis->new(server => '127.0.0.1:7900');
open IN,"/dev/urandom" or die "can't open file urandom !\n";
foreach (0..$cnt-1){
    #生成测试文件
    my $file = "${upload_path}test_${ident}_${_}.log";
    open FH,">$file" or die "can't create file $file !\n";
    foreach(1..int rand(10000)){
        my $tmp=<IN>;
        print FH $tmp;
    }
    close(FH);
    #计算文件md5值
    open FH,"$file" or die "can't create file $file !\n";   
    binmode(FH);
    my $c_md5sum = Digest::MD5->new->addfile(*FH)->hexdigest;
    print "\n\n———————-\n";
    print "生成的文件md5值是: $c_md5sum  \n";
    close(FH);
 
    #上传文件,并获取文件系统上面的hash值。
    my @upload_result = `/usr/local/cloudfs/bin/dfs-cli put $file`;    
    my $upload_result = join '', @upload_result;
    my $dfs_hash;
  
    print $upload_result;
    if($upload_result =~ /storageid:(.*)/){
        $dfs_hash=$1;
    }else{
        print "上传文件 ${file} 失败 /n";
    }
 
    #根据hash值下载文件,并计算文件MD5值验证是否同个文件。
    my @download_result = `/usr/local/cloudfs/bin/dfs-cli get $dfs_hash "${download_path}$dfs_hash"`;    
    my $download_result = join '', @download_result;
    print $download_result;
    open FH1,"${download_path}$dfs_hash" or die "can't read file ${download_path}$dfs_hash !\n";
    binmode(FH1);
    my $d_md5sum = Digest::MD5->new->addfile(*FH1)->hexdigest;
    print "下载的文件md5值是: $d_md5sum  \n"; 
    close(FH1);
    if($c_md5sum eq $d_md5sum){
        print "上传下载文件一致 \n";
    }else{
        print "上传下载文件内容不一致";
    }
 
    #检查redis中是否有fds-hash相同的文件,如果有,检查文件MD5值是否一致。如果不一致,则表示文件系统同一个hash值代表了两个不同文件。是否是hash算法产出碰撞,还是程序存在错误。
    if($redis->exists( $dfs_hash )){
        my $hash_value = $redis->get($dfs_hash);
        if ($hash_value eq "test_${ident}_${_}.log:$d_md5sum" ){
            print "下载文件与已有文件一致 \n";
            print "当前文件: $hash_value \n";
            print "已有文件: test_${ident}_${_}.log:$d_md5sum \n";
        }else{
            print "error: 下载文件与已有文件不一致 \n";
            print "当前文件: $hash_value \n";
            print "已有文件: test_${ident}_${_}.log:$d_md5sum \n";            
        }
    }else{
        print "新文件: ${file}:$d_md5sum \n";    
        $redis->set($dfs_hash => "test_${ident}_${_}.log:$d_md5sum");
        system("rm -rf ${download_path}$dfs_hash");
    }
}
 
 
第二个脚本:在第一个脚本的基础上做修改,使用已经存在的目录(如/upload),将里面的文件重复上传到服务器上。
随机选择/upload目录下一个文件,然后上传,上传完根据storageid下载该文件。比对两次的文件MD5值是否一致。

#!/usr/bin/perl
###############################################################################
# 文件系统测试脚本2–上传存在的文件
# 2012-11-22     V01.00.000  新建程序
###############################################################################
use strict;
use constant VERSION => "V01.00.000";          #版本号
use Data::Dumper;
use Digest::MD5;
use Redis;
 
die("usage: $0 <path> <cnt>\n") if ($#ARGV != 1);
 
my $download_path="./download/";
my $redis = Redis->new(server => '127.0.0.1:7900');
my ($path,$cnt) = @ARGV;
$path=~s/\/\s*$//;
$path=~s/\s*$/\//;
my @file = glob("${path}*");
 
foreach (0..$cnt-1){
    #随机获取指定目录下一个文件上传
    my $file = $file[int rand($#file)];
 
    #计算文件md5值
    $file =~ s/\s+$//g;
    open FH,$file or die "can't open file $file !\n";   
    binmode(FH);
    my $c_md5sum = Digest::MD5->new->addfile(*FH)->hexdigest;
    print "\n\n———————-\n";
    print "文件md5值是: $c_md5sum  \n";
    close(FH);
 
    #上传文件,并获取文件系统上面的hash值。
    my @upload_result = `/usr/local/cloudfs/bin/dfs-cli put $file`;    
    my $upload_result = join '', @upload_result;
    my $dfs_hash;
  
    print $upload_result;
    if($upload_result =~ /storageid:(.*)/){
        $dfs_hash=$1;
    }else{
        print "上传文件 ${file} 失败 /n";
    }
 
    #根据hash值下载文件,并计算文件MD5值验证是否同个文件。
    my @download_result = `/usr/local/cloudfs/bin/dfs-cli get $dfs_hash "${download_path}$dfs_hash"`;    
    my $download_result = join '', @download_result;
    print $download_result;
    open FH1,"${download_path}$dfs_hash" or die "can't read file ${download_path}$dfs_hash !\n";
    binmode(FH1);
    my $d_md5sum = Digest::MD5->new->addfile(*FH1)->hexdigest;
    print "下载的文件${dfs_hash}的md5值是: $d_md5sum  \n";    
    close(FH1);
    if($c_md5sum eq $d_md5sum){
        print "上传下载文件一致 \n";
    }
 
    #检查redis中是否有fds-hash相同的文件,如果有,检查文件MD5值是否一致。如果不一致,则表示文件系统同
    #一个hash值代表了两个不同文件。可能是hash算法产出碰撞也可能是程序存在错误。
    if($redis->exists( $dfs_hash )){
        my $hash_value = $redis->get($dfs_hash);
        if ($hash_value eq "${file}:$d_md5sum" ){
            print "下载文件与已有文件一致 \n";
            print "当前文件: $hash_value \n";
            print "已有文件: ${file}:$d_md5sum \n";
        }else{
            print "error: 下载文件与已有文件不一致 \n";
            print "当前文件: $hash_value \n";
            print "已有文件: ${file}:$d_md5sum \n";            
        }
    }else{
        print "新文件: ${file}:$d_md5sum \n";    
        $redis->set($dfs_hash => "${file}:$d_md5sum");
        `rm -rf ${download_path}$dfs_hash`;
    }
}
第三个脚本:上传新文件(同文件名不同内容),主要在于检查如果在不同服务器同时上传同名不同内容文件是,是否会发生异常。

#!/usr/bin/perl
###############################################################################
# 文件系统测试脚本4–上传新文件(同文件名不同内容)
# 2012-11-22    V01.00.000  新建程序
###############################################################################
use strict;
use constant VERSION => "V01.00.000";          #版本号
use Data::Dumper;
use Digest::MD5;
use Redis;
 
die("usage: $0 <cnt>\n") if ($#ARGV != 0);
 
my $upload_path="/home/samename/";  #保存上传文件的目录。
my $download_path="/home/download/";  #保存下载文件的目录,文件名是上传的文件名。
my $file="samefilename.log";
 
my ($cnt) = @ARGV;
my $redis = Redis->new(server => '127.0.0.1:7900');
open IN,"/dev/urandom" or die "can't open file urandom !\n";
foreach (0..$cnt-1){
    #生成测试文件
    open FH,">$file" or die "can't create file $file !\n";
    foreach(1..int rand(10000)){
        my $tmp=<IN>;
        print FH $tmp;
    }
    close(FH);
    #计算文件md5值
    open FH,"$file" or die "can't create file $file !\n";   
    binmode(FH);
    my $c_md5sum = Digest::MD5->new->addfile(*FH)->hexdigest;
    print "\n\n———————-\n";
    print "生成的文件md5值是: $c_md5sum  \n";
    close(FH);
 
    #上传文件,并获取文件系统上面的hash值。
    my @upload_result = `/usr/local/cloudfs/bin/dfs-cli put $file`;    
    my $upload_result = join '', @upload_result;
    my $dfs_hash;
  
    print $upload_result;
    if($upload_result =~ /storageid:(.*)/){
        $dfs_hash=$1;
    }else{
        print "上传文件 ${file} 失败 /n";
    }
 
    #根据hash值下载文件,并计算文件MD5值验证是否同个文件。
    my @download_result = `/usr/local/cloudfs/bin/dfs-cli get $dfs_hash "${download_path}$dfs_hash"`;    
    my $download_result = join '', @download_result;
    print $download_result;
    open FH1,"${download_path}$dfs_hash" or die "can't read file ${download_path}$dfs_hash !\n";
    binmode(FH1);
    my $d_md5sum = Digest::MD5->new->addfile(*FH1)->hexdigest;
    print "下载的文件md5值是: $d_md5sum  \n"; 
    close(FH1);
    if($c_md5sum eq $d_md5sum){
        print "上传下载文件一致 \n";
    }else{
        print "上传下载文件内容不一致";
    }
 
    #检查redis中是否有fds-hash相同的文件,如果有,检查文件MD5值是否一致。如果不一致,则表示文件系统同一个hash值代表了两个不同文件。是否是hash算法产出碰撞,还是程序存在错误。
    if($redis->exists( $dfs_hash )){
        my $hash_value = $redis->get($dfs_hash);
        if ($hash_value eq "${file}:$d_md5sum" ){
            print "下载文件与已有文件一致 \n";
            print "当前文件: $hash_value \n";
            print "已有文件: ${file}:$d_md5sum \n";
        }else{
            print "error: 下载文件与已有文件不一致 \n";
            print "当前文件: $hash_value \n";
            print "已有文件: ${file}:$d_md5sum \n";            
        }
    }else{
        print "新文件: ${file}:$d_md5sum \n";          
        $redis->set($dfs_hash => "${file}:$d_md5sum");
        system("rm -rf ${download_path}$dfs_hash");
    }
}
 
 
 
第四个脚本:不同名同内容的文件上传,是否会发生异常。

#!/usr/bin/perl
###############################################################################
# 文件系统测试脚本4–上传新文件(不同文件同内容)
# 2012-11-22     V01.00.000  新建程序
###############################################################################
use strict;
use constant VERSION => "V01.00.000";          #版本号
use Data::Dumper;
use Digest::MD5;
use Redis;
 
die("usage: $0 <cnt>\n") if ($#ARGV != 0);
 
my $upload_path="/home/samename/";                   #保存上传文件的目录。
my $download_path="/home/download/";               #保存下载文件的目录,文件名是上传的文件名。
my $file="samefilename.log";
 
my ($cnt) = @ARGV;
my $redis = Redis->new(server => '127.0.0.1:7900');
foreach (0..$cnt-1){
 
 
 
    #计算文件md5值
    open FH,"$file" or die "can't create file $file !\n";   
    binmode(FH);
    my $c_md5sum = Digest::MD5->new->addfile(*FH)->hexdigest;
    print "\n\n———————-\n";
    print "生成的文件md5值是: $c_md5sum  \n";
    close(FH);
 
    #上传文件,并获取文件系统上面的hash值。
    my @upload_result = `/usr/local/cloudfs/bin/dfs-cli put $file`;    
    my $upload_result = join '', @upload_result;
    my $dfs_hash;
  
    print $upload_result;
    if($upload_result =~ /storageid:(.*)/){
        $dfs_hash=$1;
    }else{
        print "上传文件 ${file} 失败 /n";
    }
 
    #根据hash值下载文件,并计算文件MD5值验证是否同个文件。
    my @download_result = `/usr/local/cloudfs/bin/dfs-cli get $dfs_hash "${download_path}$dfs_hash"`;    
    my $download_result = join '', @download_result;
    print $download_result;
    open FH1,"${download_path}$dfs_hash" or die "can't read file ${download_path}$dfs_hash !\n";
    binmode(FH1);
    my $d_md5sum = Digest::MD5->new->addfile(*FH1)->hexdigest;
    print "下载的文件md5值是: $d_md5sum  \n"; 
    close(FH1);
    if($c_md5sum eq $d_md5sum){
        print "上传下载文件一致 \n";
    }else{
        print "上传下载文件内容不一致";
    }
 
    #检查redis中是否有fds-hash相同的文件,如果有,检查文件MD5值是否一致。如果不一致,则表示文件系统同一个hash值代表了两个不同文件。是否是hash算法产出碰撞,还是程序存在错误。
    if($redis->exists( $dfs_hash )){
        my $hash_value = $redis->get($dfs_hash);
        if ($hash_value eq "${file}:$d_md5sum" ){
            print "下载文件与已有文件一致 \n";
            print "当前文件: $hash_value \n";
            print "已有文件: ${file}:$d_md5sum \n";
        }else{
            print "error: 下载文件与已有文件不一致 \n";
            print "当前文件: $hash_value \n";
            print "已有文件: ${file}:$d_md5sum \n";            
        }
    }else{
        print "新文件: ${file}:$d_md5sum \n";          
        $redis->set($dfs_hash => "${file}:$d_md5sum");
        system("rm -rf ${download_path}$dfs_hash");
    }
}
 
第五个脚本:删除文件系统上存在的文件,随机从redis获取一个storageid,然后删除。
#!/usr/bin/perl
###############################################################################
# 文件系统测试脚本5–删除文件系统上存在的文件
# 2012-11-26    V01.00.000  新建程序
###############################################################################
use strict;
use constant VERSION => "V01.00.000";          #版本号
use Data::Dumper;
use Digest::MD5;
use Redis;
 
die("usage: $0  <cnt>\n") if ($#ARGV != 0);
 
my $download_path="/home/download/";
my $redis = Redis->new(server => '127.0.0.1:7900');
my ($cnt) = @ARGV;
 
 
foreach (0..$cnt-1){
    #随机获取一个storage id
    my $dfs_hash = $redis->randomkey;
    my $hash_value = $redis->get($dfs_hash);
    print "REDIS保存的md5值是: $hash_value  \n";    
 
    #根据hash值下载文件,并计算文件MD5值验证是否同个文件。
    my @download_result = `/usr/local/cloudfs/bin/dfs-cli get $dfs_hash "${download_path}$dfs_hash"`;    
    my $download_result = join '', @download_result;
    print $download_result;
    open FH1,"${download_path}$dfs_hash" or die "can't read file ${download_path}$dfs_hash !\n";
    binmode(FH1);
    my $d_md5sum = Digest::MD5->new->addfile(*FH1)->hexdigest;
    print "下载的文件${dfs_hash}的md5值是: $d_md5sum  \n";    
    close(FH1);
    if($hash_value =~ /$d_md5sum/){
        print "文件一致 \n";
        `rm -rf "${download_path}$dfs_hash"`;
        $redis->del($dfs_hash);
    }else{
    print "error: 上传文件和以前保存的文件值不一致。 \n"
    }
}
 

 

然后明月用了一个脚本来调用这几个脚本:

#!/usr/bin/perl
###############################################################################
# 文件系统测试脚本–开多进程
# 2012-11-23   V01.00.000  新建程序
###############################################################################
use strict;
use constant VERSION => "V01.00.000";          #版本号
use Data::Dumper;
 
#新建一批文件上传
my $ident='a';
my $cnt=1000;
foreach(1..20){
    system("perl /home/dfs_newfile.pl $ident $cnt > /home/runlog/${ident}_${cnt}.log & ");
    $ident++;
}
 
sleep(60);
#已上传文件再次上传
my $cnt2=1000;
foreach(1..20){
    system("perl /home/dfs_oldfolder.pl /home/upload $cnt2 > /home/runlog/upload_${cnt2}.log & ")
}
 
#同名不同内容的文件上传
my $cnt3=1000;
foreach(1..5){
    system("perl /home/dfs_oldfolder.pl /home/samecontent $cnt3 > /home/runlog/samecontent_${cnt3}.log & ")
}
 
#不同名同内容的文件上传
my $cnt4=1000;
foreach(1..10){
    system("perl /home/dfs_samefile.pl  $cnt4 > /home/runlog/samename${cnt4}.log & ")
}
 
 
#删除已上传文件
my $cnt5=1000;
foreach(1..20){
    system("perl /home/dfs_delfile.pl  $cnt5 > /home/runlog/del${cnt5}.log & ")
}
 
 

原创文章,转载请注明: 转载自肚腩照明月'blog

本文链接地址: 分布式文件系统底层功能测试【原创】

文章的脚注信息由WordPress的wp-posturl插件自动生成


  1. 本文目前尚无任何评论.

SEO Powered by Platinum SEO from Techblissonline