PageRenderTime 46ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/XML-Simple-2.20/t/3_Storable.t

#
Unknown | 235 lines | 183 code | 52 blank | 0 comment | 0 complexity | 23a0a352053331ac023ad974ccf08049 MD5 | raw file
Possible License(s): AGPL-1.0
  1. use strict;
  2. use warnings;
  3. use Test::More;
  4. use File::Spec;
  5. eval { require Storable; };
  6. unless($INC{'Storable.pm'}) {
  7. plan skip_all => 'no Storable.pm';
  8. }
  9. unless(UNIVERSAL::can(Storable => 'lock_nstore')) {
  10. plan skip_all => 'Storable.pm is too old - no file locking support';
  11. }
  12. # Initialise filenames and check they're there
  13. my $SrcFile = File::Spec->catfile('t', 'desertnet.src');
  14. my $XMLFile = File::Spec->catfile('t', 'desertnet.xml');
  15. my $CacheFile = File::Spec->catfile('t', 'desertnet.stor');
  16. unless(-e $SrcFile) {
  17. plan skip_all => 'test data missing';
  18. }
  19. # Make sure we can write to the filesystem and check it uses the same
  20. # clock as the machine we're running on.
  21. my $t0 = time();
  22. unless(open(XML, ">$XMLFile")) {
  23. plan skip_all => "can't create test file: $!";
  24. }
  25. close(XML);
  26. my $t1 = (stat($XMLFile))[9];
  27. my $t2 = time();
  28. if($t1 < $t0 or $t2 < $t1) {
  29. plan skip_all => 'time moved backwards!'
  30. }
  31. plan tests => 23;
  32. ##############################################################################
  33. # S U P P O R T R O U T I N E S
  34. ##############################################################################
  35. ##############################################################################
  36. # Copy a file
  37. #
  38. sub CopyFile {
  39. my($Src, $Dst) = @_;
  40. open(IN, $Src) || return(undef);
  41. local($/) = undef;
  42. my $Data = <IN>;
  43. close(IN);
  44. open(OUT, ">$Dst") || return(undef);
  45. print OUT $Data;
  46. close(OUT);
  47. return(1);
  48. }
  49. ##############################################################################
  50. # Delete a file - portably
  51. #
  52. sub DeleteFile {
  53. my($Filename) = @_;
  54. if ('VMS' eq $^O) {
  55. 1 while (unlink($Filename));
  56. } else {
  57. unlink($Filename);
  58. }
  59. }
  60. ##############################################################################
  61. # Create a file, making sure that its timestamp is newer than another
  62. # existing file.
  63. #
  64. sub MakeNewerFile {
  65. my($File1, $File2, $CodeRef) = @_;
  66. my $t0 = (stat($File1))[9];
  67. while(1) {
  68. unlink($File2);
  69. $CodeRef->();
  70. return if (stat($File2))[9] > $t0;
  71. sleep(1);
  72. }
  73. }
  74. ##############################################################################
  75. # Wait until the current time is greater than the supplied value
  76. #
  77. sub PassTime {
  78. my($Target) = @_;
  79. while(time <= $Target) {
  80. sleep 1;
  81. }
  82. }
  83. ##############################################################################
  84. # T E S T R O U T I N E S
  85. ##############################################################################
  86. use XML::Simple;
  87. # Initialise test data
  88. my $Expected = {
  89. 'server' => {
  90. 'sahara' => {
  91. 'osversion' => '2.6',
  92. 'osname' => 'solaris',
  93. 'address' => [
  94. '10.0.0.101',
  95. '10.0.1.101'
  96. ]
  97. },
  98. 'gobi' => {
  99. 'osversion' => '6.5',
  100. 'osname' => 'irix',
  101. 'address' => '10.0.0.102'
  102. },
  103. 'kalahari' => {
  104. 'osversion' => '2.0.34',
  105. 'osname' => 'linux',
  106. 'address' => [
  107. '10.0.0.103',
  108. '10.0.1.103'
  109. ]
  110. }
  111. }
  112. };
  113. ok(CopyFile($SrcFile, $XMLFile), 'copied known good source file');
  114. unlink($CacheFile);
  115. ok(! -e $CacheFile, 'no cache files lying around');
  116. my $opt = XMLin($XMLFile);
  117. is_deeply($opt, $Expected, 'parsed expected data from file');
  118. ok(! -e $CacheFile, 'and no cache file was created');
  119. PassTime(time()); # Ensure cache file will be newer
  120. $opt = XMLin($XMLFile, cache => 'storable');
  121. is_deeply($opt, $Expected, 'parsed expected data from file (again)');
  122. ok(-e $CacheFile, 'but this time a cache file was created');
  123. $t0 = (stat($CacheFile))[9]; # Remember cache timestamp
  124. PassTime($t0);
  125. $opt = XMLin($XMLFile, cache => ['storable']);
  126. is_deeply($opt, $Expected, 'got expected data from cache');
  127. $t1 = (stat($CacheFile))[9];
  128. is($t0, $t1, 'and cache timestamp has not changed');
  129. PassTime(time());
  130. $t0 = time();
  131. open(FILE, ">>$XMLFile"); # Touch the XML file
  132. print FILE "\n";
  133. close(FILE);
  134. $opt = XMLin($XMLFile, cache => 'storable');
  135. is_deeply($opt, $Expected, 'parsed in expected value again');
  136. $t2 = (stat($CacheFile))[9];
  137. isnt($t1, $t2, 'and this time the cache timestamp has changed');
  138. DeleteFile($XMLFile);
  139. ok(! -e $XMLFile, 'deleted the source file');
  140. open(FILE, ">$XMLFile"); # Re-create it (empty)
  141. close(FILE);
  142. ok(-e $XMLFile, 'recreated the source file');
  143. is(-s $XMLFile, 0, 'but with nothing in it');
  144. MakeNewerFile($XMLFile, $CacheFile, sub { # Make sure cache file is newer
  145. Storable::nstore($Expected, $CacheFile);
  146. });
  147. $opt = XMLin($XMLFile, cache => 'storable');
  148. is_deeply($opt, $Expected, 'got the expected data from the cache');
  149. $t2 = (stat($CacheFile))[9];
  150. PassTime($t2);
  151. open(FILE, ">$XMLFile") || # Write some new data to the XML file
  152. die "open(>$XMLFile): $!\n";
  153. print FILE qq(<opt one="1" two="2"></opt>\n);
  154. close(FILE);
  155. $opt = XMLin($XMLFile); # Parse with no caching
  156. is_deeply($opt, { one => 1, two => 2}, 'parsed in expected data from file');
  157. $t0 = (stat($CacheFile))[9]; # And timestamp on cache file
  158. my $s0 = (-s $CacheFile);
  159. is($t0, $t2, 'and the cache file was not touched');
  160. # Parse again with caching enabled
  161. $opt = XMLin($XMLFile, cache => 'storable');
  162. is_deeply($opt, { one => 1, two => 2}, 'parsed expected data through cache');
  163. $t1 = (stat($CacheFile))[9];
  164. my $s1 = (-s $CacheFile);
  165. ok(($t0 != $t1) || ($s0 != $s1),
  166. 'and the cache was updated'); # Content changes but date may not on Win32
  167. ok(CopyFile($SrcFile, $XMLFile), 'copied back the original file');
  168. PassTime($t1);
  169. $opt = XMLin($XMLFile, cache => 'storable');
  170. is_deeply($opt, $Expected, 'parsed expected data in through cache');
  171. # Make sure scheme name is case-insensitive
  172. $opt = XMLin($XMLFile, cache => 'Storable');
  173. is_deeply($opt, $Expected, 'scheme name is case-insensitive');
  174. # Make sure bad scheme names are trapped
  175. $@='';
  176. $_ = eval { XMLin($XMLFile, cache => 'Storubble'); };
  177. is($_, undef, 'bad cache scheme names are trapped');
  178. like($@, qr/Unsupported caching scheme: storubble/,
  179. 'with correct error message');
  180. # Clean up and go
  181. unlink($CacheFile);
  182. unlink($XMLFile);
  183. exit(0);