|
| 1 | +describe :update_time, shared: true do |
| 2 | + before :all do |
| 3 | + @time_is_float = platform_is :windows |
| 4 | + end |
| 5 | + |
| 6 | + before :each do |
| 7 | + @atime = Time.now |
| 8 | + @mtime = Time.now |
| 9 | + @file1 = tmp("specs_file_utime1") |
| 10 | + @file2 = tmp("specs_file_utime2") |
| 11 | + touch @file1 |
| 12 | + touch @file2 |
| 13 | + end |
| 14 | + |
| 15 | + after :each do |
| 16 | + rm_r @file1, @file2 |
| 17 | + end |
| 18 | + |
| 19 | + it "sets the access and modification time of each file" do |
| 20 | + File.send(@method, @atime, @mtime, @file1, @file2) |
| 21 | + |
| 22 | + if @time_is_float |
| 23 | + File.atime(@file1).should be_close(@atime, 0.0001) |
| 24 | + File.mtime(@file1).should be_close(@mtime, 0.0001) |
| 25 | + File.atime(@file2).should be_close(@atime, 0.0001) |
| 26 | + File.mtime(@file2).should be_close(@mtime, 0.0001) |
| 27 | + else |
| 28 | + File.atime(@file1).to_i.should be_close(@atime.to_i, TIME_TOLERANCE) |
| 29 | + File.mtime(@file1).to_i.should be_close(@mtime.to_i, TIME_TOLERANCE) |
| 30 | + File.atime(@file2).to_i.should be_close(@atime.to_i, TIME_TOLERANCE) |
| 31 | + File.mtime(@file2).to_i.should be_close(@mtime.to_i, TIME_TOLERANCE) |
| 32 | + end |
| 33 | + end |
| 34 | + |
| 35 | + it "uses the current times if two nil values are passed" do |
| 36 | + tn = Time.now |
| 37 | + File.send(@method, nil, nil, @file1, @file2) |
| 38 | + |
| 39 | + if @time_is_float |
| 40 | + File.atime(@file1).should be_close(tn, 0.050) |
| 41 | + File.mtime(@file1).should be_close(tn, 0.050) |
| 42 | + File.atime(@file2).should be_close(tn, 0.050) |
| 43 | + File.mtime(@file2).should be_close(tn, 0.050) |
| 44 | + else |
| 45 | + File.atime(@file1).to_i.should be_close(Time.now.to_i, TIME_TOLERANCE) |
| 46 | + File.mtime(@file1).to_i.should be_close(Time.now.to_i, TIME_TOLERANCE) |
| 47 | + File.atime(@file2).to_i.should be_close(Time.now.to_i, TIME_TOLERANCE) |
| 48 | + File.mtime(@file2).to_i.should be_close(Time.now.to_i, TIME_TOLERANCE) |
| 49 | + end |
| 50 | + end |
| 51 | + |
| 52 | + it "accepts an object that has a #to_path method" do |
| 53 | + File.send(@method, @atime, @mtime, mock_to_path(@file1), mock_to_path(@file2)) |
| 54 | + end |
| 55 | + |
| 56 | + it "accepts numeric atime and mtime arguments" do |
| 57 | + if @time_is_float |
| 58 | + File.send(@method, @atime.to_f, @mtime.to_f, @file1, @file2) |
| 59 | + |
| 60 | + File.atime(@file1).should be_close(@atime, 0.0001) |
| 61 | + File.mtime(@file1).should be_close(@mtime, 0.0001) |
| 62 | + File.atime(@file2).should be_close(@atime, 0.0001) |
| 63 | + File.mtime(@file2).should be_close(@mtime, 0.0001) |
| 64 | + else |
| 65 | + File.send(@method, @atime.to_i, @mtime.to_i, @file1, @file2) |
| 66 | + |
| 67 | + File.atime(@file1).to_i.should be_close(@atime.to_i, TIME_TOLERANCE) |
| 68 | + File.mtime(@file1).to_i.should be_close(@mtime.to_i, TIME_TOLERANCE) |
| 69 | + File.atime(@file2).to_i.should be_close(@atime.to_i, TIME_TOLERANCE) |
| 70 | + File.mtime(@file2).to_i.should be_close(@mtime.to_i, TIME_TOLERANCE) |
| 71 | + end |
| 72 | + end |
| 73 | + |
| 74 | + it "may set nanosecond precision" do |
| 75 | + t = Time.utc(2007, 11, 1, 15, 25, 0, 123456.789r) |
| 76 | + File.send(@method, t, t, @file1) |
| 77 | + |
| 78 | + File.atime(@file1).nsec.should.between?(0, 123500000) |
| 79 | + File.mtime(@file1).nsec.should.between?(0, 123500000) |
| 80 | + end |
| 81 | + |
| 82 | + it "returns the number of filenames in the arguments" do |
| 83 | + File.send(@method, @atime.to_f, @mtime.to_f, @file1, @file2).should == 2 |
| 84 | + end |
| 85 | + |
| 86 | + platform_is :linux do |
| 87 | + platform_is wordsize: 64 do |
| 88 | + it "allows Time instances in the far future to set mtime and atime (but some filesystems limit it up to 2446-05-10 or 2038-01-19 or 2486-07-02)" do |
| 89 | + # https://ext4.wiki.kernel.org/index.php/Ext4_Disk_Layout#Inode_Timestamps |
| 90 | + # "Therefore, timestamps should not overflow until May 2446." |
| 91 | + # https://lwn.net/Articles/804382/ |
| 92 | + # "On-disk timestamps hitting the y2038 limit..." |
| 93 | + # The problem seems to be being improved, but currently it actually fails on XFS on RHEL8 |
| 94 | + # https://rubyci.org/logs/rubyci.s3.amazonaws.com/rhel8/ruby-master/log/20201112T123004Z.fail.html.gz |
| 95 | + # Amazon Linux 2023 returns 2486-07-02 in this example |
| 96 | + # http://rubyci.s3.amazonaws.com/amazon2023/ruby-master/log/20230322T063004Z.fail.html.gz |
| 97 | + time = Time.at(1<<44) |
| 98 | + File.send(@method, time, time, @file1) |
| 99 | + |
| 100 | + [559444, 2486, 2446, 2038].should.include? File.atime(@file1).year |
| 101 | + [559444, 2486, 2446, 2038].should.include? File.mtime(@file1).year |
| 102 | + end |
| 103 | + end |
| 104 | + end |
| 105 | +end |
0 commit comments