123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126(*
* Copyright (C) 2011-2013 Citrix Inc
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; version 2.1 only. with the special
* exception on linking described in file LICENSE.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*)(* Interesting set of I/O patterns for testing a vhd implementation *)letkib=1024Lletmib=Int64.(mul1024Lkib)letgib=Int64.(mul1024Lmib)letmax_disk_size=Int64.(mul2040Lgib)(* Interesting virtual sizes of disks *)letsizes=[0L;(* edge case: minimum size *)4194304L;(* common case: 2 blocks *)max_disk_size;(* edge case: maximum size *)](* Places within an array (either a sector bitmap or BAT) *)typechoice=|First(* edge case: first entry *)|Last(* edge case: last entry *)letchoices=[First;Last]letstring_of_choice=function|First->"first"|Last->"last"(* Position to read or write in a vhd *)typeposition={block:choice;sector:choice;}letrecallpairsxsys=matchxswith|[]->[]|x::xs->List.map(funy->x,y)ys@(allpairsxsys)letpositions=List.map(fun(block,sector)->{block;sector})(allpairschoiceschoices)(* Individual step *)typeoperation=|Createofint64(* Create a vhd of a given size; open file for I/O *)|Snapshot(* Snapshot current file; open new file for I/O *)|Writeof(position*string)(* Write copies of a given string over a specific sector *)letdescr_of_operation=function|Createx->[Printf.sprintf"filename := Vhd.create(size = %Ld)"x;"current := Vhd.open(filename)"]|Snapshot->["filename := Vhd.snapshot(current)";"current := Vhd.open(filename)"]|Write(p,message)->[Printf.sprintf"Vhd.write(current, block = %s, sector = %s, data = \"%s\")"(string_of_choicep.block)(string_of_choicep.sector)(String.escapedmessage)]typeprogram=operationlistletstring_of_operation=function|Createx->Printf.sprintf"Create:%Ld"x|Snapshot->"Snapshot"|Write(p,_)->Printf.sprintf"Write:%s:%s"(string_of_choicep.block)(string_of_choicep.sector)letdescr_of_programp=letlines=List.concat_mapdescr_of_operationpinList.rev(fst(List.fold_left(fun(sofar,next)line->Printf.sprintf"%d %s"(next*10)line::sofar,next+1)([],1)lines))letstring_of_programp=String.concat"_"(List.mapstring_of_operationp)letfirst_write_message="This is a sector which contains simple data.\n"letsecond_write_message="All work and no play makes Dave a dull boy.\n"letfirst_writep=Write(p,first_write_message)letsecond_writep=Write(p,second_write_message)(* Check writing and then reading back works *)letcreate_write_read=List.map(fun(size,p)->[Createsize;first_writep])(allpairssizespositions)(* Check writing and then reading back works in a simple chain *)letcreate_write_read_leaf=List.map(fun(size,p)->[Createsize;Snapshot;first_writep])(allpairssizespositions)(* Check writing and then reading back works in a chain where the writes are in the parent *)letcreate_write_read_parent=List.map(fun(size,p)->[Createsize;first_writep;Snapshot])(allpairssizespositions)(* Check writing and then reading back works in a chain where there are writes in both parent and leaf *)letcreate_write_overwrite=List.map(fun(size,(p1,p2))->[Createsize;first_writep1;Snapshot;second_writep2])(allpairssizes(allpairspositionspositions))(* TODO: ... and all of that again with a larger leaf *)letprograms=List.concat[create_write_read;create_write_read_leaf;create_write_read_parent;create_write_overwrite;]