nano-smart-lib 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 3ec09cb5c3f58464babe2db65f3da483fd886681ff9833e77e4bf99e19af42b0
4
+ data.tar.gz: 8a1ab3d749cb4de6baa8326682e2518eda99e02844d3b870316366b8f2d040e1
5
+ SHA512:
6
+ metadata.gz: 5d225b4f0c52899e1e628dfe9a7b725ee0b9c7f51337e189ab7f25706205f883215cd4d82c53cff27deafb70d12f0ec24a3d9419f9a9bc1324cc549754198d9b
7
+ data.tar.gz: faa662213b9fe69b4853a0d276695a48d7260ed1ec382fdba551e9fea98341aae98f5d7bd74455d450a568278b705500124882cc120ec4bb4910993361c096fa
@@ -0,0 +1,12 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = "nano-smart-lib"
3
+ s.version = "0.0.1"
4
+ s.summary = "Research test"
5
+ s.description = "University research based on timecop"
6
+ s.authors = ["Andrey78"]
7
+ s.email = ["cakoc614@gmail.com"]
8
+ s.files = Dir.glob("**/*").reject { |f| f.end_with?('.gem') }
9
+ s.homepage = "https://rubygems.org/profiles/Andrey78"
10
+ s.license = "MIT"
11
+ s.metadata = { "source_code_uri" => "https://github.com/Andrey78/nano-smart-lib" }
12
+ end
@@ -0,0 +1,22 @@
1
+ (The MIT License)
2
+
3
+ Copyright (c) 2019 — Travis Jeffery, John Trupiano
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ 'Software'), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,162 @@
1
+ # timecop
2
+
3
+ [![Gem Version](https://badge.fury.io/rb/timecop.svg)](https://rubygems.org/gems/timecop)
4
+ [![Build Status](https://github.com/travisjeffery/timecop/workflows/CI/badge.svg)](https://github.com/travisjeffery/timecop/actions?query=workflow%3ACI)
5
+
6
+ ## DESCRIPTION
7
+
8
+ A gem providing "time travel" and "time freezing" capabilities, making it dead simple to test time-dependent code. It provides a unified method to mock `Time.now`, `Date.today`, `DateTime.now`, and `Process.clock_gettime` in a single call.
9
+
10
+ ## INSTALL
11
+
12
+ `bundle add timecop`
13
+
14
+ ## FEATURES
15
+
16
+ - Freeze time to a specific point.
17
+ - Travel back to a specific point in time, but allow time to continue moving forward from there.
18
+ - Scale time by a given scaling factor that will cause time to move at an accelerated pace.
19
+ - No dependencies, can be used with _any_ ruby project
20
+ - Timecop api allows arguments to be passed into `#freeze` and `#travel` as one of the following:
21
+ - Time instance
22
+ - DateTime instance
23
+ - Date instance
24
+ - individual arguments (year, month, day, hour, minute, second)
25
+ - a single integer argument that is interpreted as an offset in seconds from `Time.now`
26
+ - Nested calls to `Timecop#travel` and `Timecop#freeze` are supported -- each block will maintain its interpretation of now.
27
+ - Works with regular Ruby projects, and Ruby on Rails projects
28
+
29
+ ## USAGE
30
+
31
+ Run a time-sensitive test
32
+
33
+ ```ruby
34
+ joe = User.find(1)
35
+ joe.purchase_home()
36
+ assert !joe.mortgage_due?
37
+ # move ahead a month and assert that the mortgage is due
38
+ Timecop.freeze(Date.today + 30) do
39
+ assert joe.mortgage_due?
40
+ end
41
+ ```
42
+
43
+ You can mock the time for a set of tests easily via setup/teardown methods
44
+
45
+ ```ruby
46
+ describe "some set of tests to mock" do
47
+ before do
48
+ Timecop.freeze(Time.local(1990))
49
+ end
50
+
51
+ after do
52
+ Timecop.return
53
+ end
54
+
55
+ it "should do blah blah blah" do
56
+ end
57
+ end
58
+ ```
59
+
60
+ Set the time for the test environment of a rails app -- this is particularly
61
+ helpful if your whole application is time-sensitive. It allows you to build
62
+ your test data at a single point in time, and to move in/out of that time as
63
+ appropriate (within your tests)
64
+
65
+ in `config/environments/test.rb`
66
+
67
+ ```ruby
68
+ config.after_initialize do
69
+ # Set Time.now to September 1, 2008 10:05:00 AM (at this instant), but allow it to move forward
70
+ t = Time.local(2008, 9, 1, 10, 5, 0)
71
+ Timecop.travel(t)
72
+ end
73
+ ```
74
+
75
+ ### The difference between Timecop.freeze and Timecop.travel
76
+
77
+ `freeze` is used to statically mock the concept of now. As your program executes,
78
+ `Time.now` will not change unless you make subsequent calls into the Timecop API.
79
+ `travel`, on the other hand, computes an offset between what we currently think
80
+ `Time.now` is (recall that we support nested traveling) and the time passed in.
81
+ It uses this offset to simulate the passage of time. To demonstrate, consider
82
+ the following code snippets:
83
+
84
+ ```ruby
85
+ new_time = Time.local(2008, 9, 1, 12, 0, 0)
86
+ Timecop.freeze(new_time)
87
+ sleep(10)
88
+ new_time == Time.now # ==> true
89
+
90
+ Timecop.return # "turn off" Timecop
91
+ Timecop.travel(new_time)
92
+ sleep(10)
93
+ new_time == Time.now # ==> false
94
+ ```
95
+
96
+ ### Timecop.scale
97
+
98
+ Let's say you want to test a "live" integration wherein entire days could pass by
99
+ in minutes while you're able to simulate "real" activity. For example, one such use case
100
+ is being able to test reports and invoices that run in 30 day cycles in very little time, while also
101
+ being able to simulate activity via subsequent calls to your application.
102
+
103
+ ```ruby
104
+ # seconds will now seem like hours
105
+ Timecop.scale(3600)
106
+ Time.now
107
+ # => 2012-09-20 21:23:25 -0500
108
+ # seconds later, hours have passed and it's gone from 9pm at night to 6am in the morning
109
+ Time.now
110
+ # => 2012-09-21 06:22:59 -0500
111
+ ```
112
+
113
+ See [#42](https://github.com/travisjeffery/timecop/pull/42) for more information, thanks to Ken Mayer, David Holcomb, and Pivotal Labs.
114
+
115
+ ### Timecop.safe_mode
116
+
117
+ Safe mode forces you to use Timecop with the block syntax since it always puts time back the way it was. If you are running in safe mode and use Timecop without the block syntax `Timecop::SafeModeException` will be raised to tell the user they are not being safe.
118
+
119
+ ``` ruby
120
+ # turn on safe mode
121
+ Timecop.safe_mode = true
122
+
123
+ # check if you are in safe mode
124
+ Timecop.safe_mode?
125
+ # => true
126
+
127
+ # using method without block
128
+ Timecop.freeze
129
+ # => Timecop::SafeModeException: Safe mode is enabled, only calls passing a block are allowed.
130
+ ```
131
+
132
+ ### Configuring Mocking Process.clock_gettime
133
+
134
+ By default Timecop does not mock Process.clock_gettime. You must enable it like this:
135
+
136
+ ``` ruby
137
+ # turn on
138
+ Timecop.mock_process_clock = true
139
+ ```
140
+
141
+ ### Rails v Ruby Date/Time libraries
142
+
143
+ Sometimes [Rails Date/Time methods don't play nicely with Ruby Date/Time methods.](https://rails.lighthouseapp.com/projects/8994/tickets/6410-dateyesterday-datetoday)
144
+
145
+ Be careful mixing Ruby `Date.today` with Rails `Date.tomorrow` / `Date.yesterday` as things might break.
146
+
147
+ ## Contribute
148
+
149
+ timecop is maintained by [travisjeffery](http://github.com/travisjeffery), and
150
+ was created by [jtrupiano](https://github.com/jtrupiano).
151
+
152
+ Here's the most direct way to get your work merged into the project.
153
+
154
+ - Fork the project
155
+ - Clone down your fork
156
+ - Create a feature branch
157
+ - Hack away and add tests, not necessarily in that order
158
+ - Make sure everything still passes by running tests
159
+ - If necessary, rebase your commits into logical chunks without errors
160
+ - Push the branch up to your fork
161
+ - Send a pull request for your branch
162
+
@@ -0,0 +1,34 @@
1
+ require 'bundler/setup'
2
+ require 'bundler/gem_tasks'
3
+ require 'rake/testtask'
4
+ require 'rdoc/task'
5
+
6
+ Rake::RDocTask.new do |rdoc|
7
+ if File.exist?('VERSION')
8
+ version = File.read('VERSION')
9
+ else
10
+ version = ""
11
+ end
12
+
13
+ rdoc.rdoc_dir = 'rdoc'
14
+ rdoc.options << '--line-numbers' << '--inline-source'
15
+ rdoc.title = "timecop #{version}"
16
+ rdoc.rdoc_files.include('README*')
17
+ rdoc.rdoc_files.include('History.rdoc')
18
+ rdoc.rdoc_files.include('lib/**/*.rb')
19
+ end
20
+
21
+ task :test do
22
+ failed = Dir["test/*_test.rb"].map do |test|
23
+ command = "ruby #{test}"
24
+ puts
25
+ puts command
26
+ command unless system(command)
27
+ end.compact
28
+ if failed.any?
29
+ abort "#{failed.count} Tests failed\n#{failed.join("\n")}"
30
+ end
31
+ end
32
+
33
+ desc 'Default: run tests'
34
+ task :default => [:test]
@@ -0,0 +1,235 @@
1
+ require 'time'
2
+ require 'date'
3
+
4
+ class Time #:nodoc:
5
+ class << self
6
+ def mock_time
7
+ mocked_time_stack_item = Timecop.top_stack_item
8
+ mocked_time_stack_item.nil? ? nil : mocked_time_stack_item.time(self)
9
+ end
10
+
11
+ alias_method :now_without_mock_time, :now
12
+
13
+ def now_with_mock_time
14
+ mock_time || now_without_mock_time
15
+ end
16
+
17
+ alias_method :now, :now_with_mock_time
18
+
19
+ alias_method :new_without_mock_time, :new
20
+
21
+ def new_with_mock_time(*args, **kwargs)
22
+ if args.empty? && kwargs.empty?
23
+ now
24
+ elsif kwargs.any?
25
+ new_without_mock_time(*args, **kwargs)
26
+ else
27
+ new_without_mock_time(*args)
28
+ end
29
+ end
30
+
31
+ alias_method :new, :new_with_mock_time
32
+ end
33
+ end
34
+
35
+ class Date #:nodoc:
36
+ class << self
37
+ def mock_date
38
+ mocked_time_stack_item.nil? ? nil : mocked_time_stack_item.date(self)
39
+ end
40
+
41
+ alias_method :today_without_mock_date, :today
42
+
43
+ def today_with_mock_date
44
+ mock_date || today_without_mock_date
45
+ end
46
+
47
+ alias_method :today, :today_with_mock_date
48
+
49
+ alias_method :strptime_without_mock_date, :strptime
50
+
51
+ def strptime_with_mock_date(str = '-4712-01-01', fmt = '%F', start = Date::ITALY)
52
+ #If date is not valid the following line raises
53
+ Date.strptime_without_mock_date(str, fmt, start)
54
+
55
+ d = Date._strptime(str, fmt)
56
+ now = Time.now.to_date
57
+
58
+ # If "current" time falls near a year boundary, with a year-ambiguous str, we need to explicitly handle it
59
+ cwday = d[:cwday] && (now + (d[:cwday] - now.wday))
60
+ wday = d[:wday] && (now + (d[:wday] - now.wday))
61
+
62
+ year = d[:year] || d[:cwyear] || (cwday || wday || now).year
63
+ mon = d[:mon] || now.mon
64
+ if d.keys == [:year]
65
+ Date.new(year, 1, 1, start)
66
+ elsif d[:mday]
67
+ Date.new(year, mon, d[:mday], start)
68
+ elsif d[:yday]
69
+ Date.new(year, 1, 1, start).next_day(d[:yday] - 1)
70
+ elsif d[:cwyear] || d[:cweek] || d[:wnum0] || d[:wnum1] || d[:wday] || d[:cwday]
71
+ # When only a day (wday/cwday) is present, derive the week from the resolved date; otherwise fall back to now's week
72
+ week = d[:cweek] || d[:wnum1] || d[:wnum0] || (cwday || wday || now).strftime('%W').to_i
73
+ if d[:wnum0] #Week of year where week starts on sunday
74
+ if d[:cwday] #monday based day of week
75
+ Date.strptime_without_mock_date("#{year} #{week} #{d[:cwday]}", '%Y %U %u', start)
76
+ else
77
+ Date.strptime_without_mock_date("#{year} #{week} #{d[:wday] || 0}", '%Y %U %w', start)
78
+ end
79
+ else #Week of year where week starts on monday
80
+ if d[:wday] #sunday based day of week
81
+ Date.strptime_without_mock_date("#{year} #{week} #{d[:wday]}", '%Y %W %w', start)
82
+ else
83
+ Date.strptime_without_mock_date("#{year} #{week} #{d[:cwday] || 1}", '%Y %W %u', start)
84
+ end
85
+ end
86
+ elsif d[:seconds]
87
+ Time.at(d[:seconds]).to_date
88
+ else
89
+ Date.new(year, mon, 1, start)
90
+ end
91
+ end
92
+
93
+ alias_method :strptime, :strptime_with_mock_date
94
+
95
+ def parse_with_mock_date(*args)
96
+ parsed_date = parse_without_mock_date(*args)
97
+ return parsed_date unless mocked_time_stack_item
98
+ date_hash = Date._parse(*args)
99
+
100
+ case
101
+ when date_hash[:year] && date_hash[:mon]
102
+ parsed_date
103
+ when date_hash[:mon] && date_hash[:mday]
104
+ Date.new(mocked_time_stack_item.year, date_hash[:mon], date_hash[:mday])
105
+ when date_hash[:mday]
106
+ Date.new(mocked_time_stack_item.year, mocked_time_stack_item.month, date_hash[:mday])
107
+ when date_hash[:wday]
108
+ closest_wday(date_hash[:wday])
109
+ else
110
+ parsed_date + mocked_time_stack_item.travel_offset_days
111
+ end
112
+ end
113
+
114
+ alias_method :parse_without_mock_date, :parse
115
+ alias_method :parse, :parse_with_mock_date
116
+
117
+ def mocked_time_stack_item
118
+ Timecop.top_stack_item
119
+ end
120
+
121
+ def closest_wday(wday)
122
+ today = Date.today
123
+ result = today - today.wday
124
+ result += 1 until wday == result.wday
125
+ result
126
+ end
127
+ end
128
+ end
129
+
130
+ class DateTime #:nodoc:
131
+ class << self
132
+ def mock_time
133
+ mocked_time_stack_item.nil? ? nil : mocked_time_stack_item.datetime(self)
134
+ end
135
+
136
+ def now_with_mock_time
137
+ mock_time || now_without_mock_time
138
+ end
139
+
140
+ alias_method :now_without_mock_time, :now
141
+
142
+ alias_method :now, :now_with_mock_time
143
+
144
+ def parse_with_mock_date(*args)
145
+ parsed_date = parse_without_mock_date(*args)
146
+ return parsed_date unless mocked_time_stack_item
147
+ date_hash = DateTime._parse(*args)
148
+
149
+ case
150
+ when date_hash[:year] && date_hash[:mon]
151
+ parsed_date
152
+ when date_hash[:mon] && date_hash[:mday]
153
+ DateTime.new(mocked_time_stack_item.year, date_hash[:mon], date_hash[:mday])
154
+ when date_hash[:mday]
155
+ DateTime.new(mocked_time_stack_item.year, mocked_time_stack_item.month, date_hash[:mday])
156
+ when date_hash[:wday] && date_hash[:hour] && date_hash[:min]
157
+ closest_date = Date.closest_wday(date_hash[:wday]).to_datetime
158
+
159
+ DateTime.new(
160
+ closest_date.year, closest_date.month, closest_date.day,
161
+ date_hash[:hour], date_hash[:min]
162
+ )
163
+ when date_hash[:wday]
164
+ Date.closest_wday(date_hash[:wday]).to_datetime
165
+ when date_hash[:hour] && date_hash[:min] && date_hash[:sec]
166
+ DateTime.new(mocked_time_stack_item.year, mocked_time_stack_item.month, mocked_time_stack_item.day, date_hash[:hour], date_hash[:min], date_hash[:sec])
167
+ when date_hash[:hour] && date_hash[:min]
168
+ DateTime.new(mocked_time_stack_item.year, mocked_time_stack_item.month, mocked_time_stack_item.day, date_hash[:hour], date_hash[:min], 0)
169
+ else
170
+ parsed_date + mocked_time_stack_item.travel_offset_days
171
+ end
172
+ end
173
+
174
+ alias_method :parse_without_mock_date, :parse
175
+ alias_method :parse, :parse_with_mock_date
176
+
177
+ def mocked_time_stack_item
178
+ Timecop.top_stack_item
179
+ end
180
+ end
181
+ end
182
+
183
+ module Process #:nodoc:
184
+ class << self
185
+ alias_method :clock_gettime_without_mock, :clock_gettime
186
+
187
+ def clock_gettime_mock_time(clock_id, unit = :float_second)
188
+ mock_time = case clock_id
189
+ when Process::CLOCK_MONOTONIC
190
+ mock_time_monotonic
191
+ when Process::CLOCK_REALTIME
192
+ mock_time_realtime
193
+ end
194
+
195
+ return clock_gettime_without_mock(clock_id, unit) unless Timecop.mock_process_clock? && mock_time
196
+
197
+ divisor = case unit
198
+ when :float_second
199
+ 1_000_000_000.0
200
+ when :second
201
+ 1_000_000_000
202
+ when :float_millisecond
203
+ 1_000_000.0
204
+ when :millisecond
205
+ 1_000_000
206
+ when :float_microsecond
207
+ 1000.0
208
+ when :microsecond
209
+ 1000
210
+ when :nanosecond
211
+ 1
212
+ end
213
+
214
+ (mock_time / divisor)
215
+ end
216
+
217
+ alias_method :clock_gettime, :clock_gettime_mock_time
218
+
219
+ private
220
+
221
+ def mock_time_monotonic
222
+ mocked_time_stack_item = Timecop.top_stack_item
223
+ mocked_time_stack_item.nil? ? nil : mocked_time_stack_item.monotonic
224
+ end
225
+
226
+ def mock_time_realtime
227
+ mocked_time_stack_item = Timecop.top_stack_item
228
+
229
+ return nil if mocked_time_stack_item.nil?
230
+
231
+ t = mocked_time_stack_item.time
232
+ t.to_i * 1_000_000_000 + t.nsec
233
+ end
234
+ end
235
+ end
@@ -0,0 +1,169 @@
1
+ class Timecop
2
+ # A data class for carrying around "time movement" objects. Makes it easy to keep track of the time
3
+ # movements on a simple stack.
4
+ class TimeStackItem #:nodoc:
5
+ attr_reader :mock_type
6
+
7
+ def initialize(mock_type, *args)
8
+ raise "Unknown mock_type #{mock_type}" unless [:freeze, :travel, :scale].include?(mock_type)
9
+ @travel_offset = @scaling_factor = nil
10
+ @scaling_factor = args.shift if mock_type == :scale
11
+ @mock_type = mock_type
12
+ @monotonic = parse_monotonic_time(*args)
13
+ @time = parse_time(*args)
14
+ @time_was = Time.now_without_mock_time
15
+ @travel_offset = compute_travel_offset
16
+ end
17
+
18
+ def year
19
+ time.year
20
+ end
21
+
22
+ def month
23
+ time.month
24
+ end
25
+
26
+ def day
27
+ time.day
28
+ end
29
+
30
+ def hour
31
+ time.hour
32
+ end
33
+
34
+ def min
35
+ time.min
36
+ end
37
+
38
+ def sec
39
+ time.sec
40
+ end
41
+
42
+ def utc_offset
43
+ time.utc_offset
44
+ end
45
+
46
+ def travel_offset
47
+ @travel_offset unless mock_type == :freeze
48
+ end
49
+
50
+ def travel_offset_days
51
+ (@travel_offset / 60 / 60 / 24).round
52
+ end
53
+
54
+ def scaling_factor
55
+ @scaling_factor
56
+ end
57
+
58
+ def monotonic
59
+ if travel_offset.nil?
60
+ @monotonic
61
+ elsif scaling_factor.nil?
62
+ current_monotonic + travel_offset * (10 ** 9)
63
+ else
64
+ (@monotonic + (current_monotonic - @monotonic) * scaling_factor).to_i
65
+ end
66
+ end
67
+
68
+ def current_monotonic
69
+ Process.clock_gettime_without_mock(Process::CLOCK_MONOTONIC, :nanosecond)
70
+ end
71
+
72
+ def current_monotonic_with_mock
73
+ Process.clock_gettime_mock_time(Process::CLOCK_MONOTONIC, :nanosecond)
74
+ end
75
+
76
+ def time(time_klass = Time) #:nodoc:
77
+ if @time.respond_to?(:in_time_zone)
78
+ time = time_klass.at(@time.dup.localtime)
79
+ else
80
+ time = time_klass.at(@time)
81
+ end
82
+
83
+ if travel_offset.nil?
84
+ time
85
+ elsif scaling_factor.nil?
86
+ time_klass.at(Time.now_without_mock_time + travel_offset)
87
+ else
88
+ time_klass.at(scaled_time)
89
+ end
90
+ end
91
+
92
+ def scaled_time
93
+ (@time + (Time.now_without_mock_time - @time_was) * scaling_factor).to_f
94
+ end
95
+
96
+ def date(date_klass = Date)
97
+ date_klass.jd(time.__send__(:to_date).jd)
98
+ end
99
+
100
+ def datetime(datetime_klass = DateTime)
101
+ if Float.method_defined?(:to_r)
102
+ fractions_of_a_second = time.to_f % 1
103
+ datetime_klass.new(year, month, day, hour, min, (fractions_of_a_second + sec), utc_offset_to_rational(utc_offset))
104
+ else
105
+ datetime_klass.new(year, month, day, hour, min, sec, utc_offset_to_rational(utc_offset))
106
+ end
107
+ end
108
+
109
+ private
110
+
111
+ def rational_to_utc_offset(rational)
112
+ ((24.0 / rational.denominator) * rational.numerator) * (60 * 60)
113
+ end
114
+
115
+ def utc_offset_to_rational(utc_offset)
116
+ Rational(utc_offset, 24 * 60 * 60)
117
+ end
118
+
119
+ def parse_monotonic_time(*args)
120
+ arg = args.shift
121
+ offset_in_nanoseconds = if args.empty? && (arg.kind_of?(Integer) || arg.kind_of?(Float))
122
+ arg * 1_000_000_000
123
+ else
124
+ 0
125
+ end
126
+ current_monotonic_with_mock + offset_in_nanoseconds
127
+ end
128
+
129
+ def parse_time(*args)
130
+ arg = args.shift
131
+ if arg.is_a?(Time)
132
+ arg
133
+ elsif Object.const_defined?(:DateTime) && arg.is_a?(DateTime)
134
+ time_klass.at(arg.to_time.to_f).getlocal
135
+ elsif Object.const_defined?(:Date) && arg.is_a?(Date)
136
+ time_klass.local(arg.year, arg.month, arg.day, 0, 0, 0)
137
+ elsif args.empty? && (arg.kind_of?(Integer) || arg.kind_of?(Float))
138
+ time_klass.now + arg
139
+ elsif arg.nil?
140
+ time_klass.now
141
+ else
142
+ if arg.is_a?(String) && Time.respond_to?(:parse)
143
+ time_klass.parse(arg)
144
+ else
145
+ # we'll just assume it's a list of y/m/d/h/m/s
146
+ year = arg || 2000
147
+ month = args.shift || 1
148
+ day = args.shift || 1
149
+ hour = args.shift || 0
150
+ minute = args.shift || 0
151
+ second = args.shift || 0
152
+ time_klass.local(year, month, day, hour, minute, second)
153
+ end
154
+ end
155
+ end
156
+
157
+ def compute_travel_offset
158
+ time - Time.now_without_mock_time
159
+ end
160
+
161
+ def times_are_equal_within_epsilon t1, t2, epsilon_in_seconds
162
+ (t1 - t2).abs < epsilon_in_seconds
163
+ end
164
+
165
+ def time_klass
166
+ Time.respond_to?(:zone) && Time.zone ? Time.zone : Time
167
+ end
168
+ end
169
+ end
@@ -0,0 +1,264 @@
1
+ require 'singleton'
2
+ require File.join(File.dirname(__FILE__), "time_stack_item")
3
+
4
+ # Timecop
5
+ # * Wrapper class for manipulating the extensions to the Time, Date, and DateTime objects
6
+ # * Allows us to "freeze" time in our Ruby applications.
7
+ # * Optionally allows time travel to simulate a running clock, such time is not technically frozen.
8
+ #
9
+ # This is very useful when your app's functionality is dependent on time (e.g.
10
+ # anything that might expire). This will allow us to alter the return value of
11
+ # Date.today, Time.now, and DateTime.now, such that our application code _never_ has to change.
12
+ class Timecop
13
+ include Singleton
14
+
15
+ class << self
16
+ private :instance
17
+
18
+ # Allows you to run a block of code and "fake" a time throughout the execution of that block.
19
+ # This is particularly useful for writing test methods where the passage of time is critical to the business
20
+ # logic being tested. For example:
21
+ #
22
+ # joe = User.find(1)
23
+ # joe.purchase_home()
24
+ # assert !joe.mortgage_due?
25
+ # Timecop.freeze(2008, 10, 5) do
26
+ # assert joe.mortgage_due?
27
+ # end
28
+ #
29
+ # freeze and travel will respond to several different arguments:
30
+ # 1. Timecop.freeze(time_inst)
31
+ # 2. Timecop.freeze(datetime_inst)
32
+ # 3. Timecop.freeze(date_inst)
33
+ # 4. Timecop.freeze(offset_in_seconds)
34
+ # 5. Timecop.freeze(year, month, day, hour=0, minute=0, second=0)
35
+ # 6. Timecop.freeze() # Defaults to Time.now
36
+ #
37
+ # When a block is also passed, Time.now, DateTime.now and Date.today are all reset to their
38
+ # previous values after the block has finished executing. This allows us to nest multiple
39
+ # calls to Timecop.travel and have each block maintain it's concept of "now."
40
+ #
41
+ # The Process.clock_gettime call mocks both CLOCK::MONOTIC and CLOCK::REALTIME
42
+ #
43
+ # CLOCK::MONOTONIC works slightly differently than other clocks. This clock cannot move to a
44
+ # particular date/time. So the only option that changes this clock is #4 which will move the
45
+ # clock the requested offset. Otherwise the clock is frozen to the current tick.
46
+ #
47
+ # * Note: Timecop.freeze will actually freeze time. This can cause unanticipated problems if
48
+ # benchmark or other timing calls are executed, which implicitly expect Time to actually move
49
+ # forward.
50
+ #
51
+ # * Rails Users: Be especially careful when setting this in your development environment in a
52
+ # rails project. Generators will load your environment, including the migration generator,
53
+ # which will lead to files being generated with the timestamp set by the Timecop.freeze call
54
+ # in your dev environment
55
+ #
56
+ # Returns the value of the block if one is given, or the mocked time.
57
+ def freeze(*args, &block)
58
+ send_travel(:freeze, *args, &block)
59
+ end
60
+
61
+ # Allows you to run a block of code and "fake" a time throughout the execution of that block.
62
+ # See Timecop#freeze for a sample of how to use (same exact usage syntax)
63
+ #
64
+ # * Note: Timecop.travel will not freeze time (as opposed to Timecop.freeze). This is a particularly
65
+ # good candidate for use in environment files in rails projects.
66
+ #
67
+ # Returns the value of the block if one is given, or the mocked time.
68
+ def travel(*args, &block)
69
+ send_travel(:travel, *args, &block)
70
+ end
71
+
72
+ # Allows you to run a block of code and "scale" a time throughout the execution of that block.
73
+ # The first argument is a scaling factor, for example:
74
+ # Timecop.scale(2) do
75
+ # ... time will 'go' twice as fast here
76
+ # end
77
+ # See Timecop#freeze for exact usage of the other arguments
78
+ #
79
+ # Returns the value of the block if one is given, or the mocked time.
80
+ def scale(*args, &block)
81
+ send_travel(:scale, *args, &block)
82
+ end
83
+
84
+ def baseline
85
+ instance.baseline
86
+ end
87
+
88
+ def baseline=(baseline)
89
+ instance.baseline = baseline
90
+ end
91
+
92
+ # Reverts back to system's Time.now, Date.today and DateTime.now (if it exists) permamently when
93
+ # no block argument is given, or temporarily reverts back to the system's time temporarily for
94
+ # the given block.
95
+ def return(&block)
96
+ if block_given?
97
+ instance.return(&block)
98
+ else
99
+ instance.unmock!
100
+ nil
101
+ end
102
+ end
103
+ alias :unfreeze :return
104
+
105
+ def return_to_baseline
106
+ instance.return_to_baseline
107
+ Time.now
108
+ end
109
+
110
+ def top_stack_item #:nodoc:
111
+ instance.stack.last
112
+ end
113
+
114
+ def safe_mode=(safe)
115
+ @safe_mode = safe
116
+ end
117
+
118
+ def safe_mode?
119
+ @safe_mode ||= false
120
+ end
121
+
122
+ def thread_safe=(t)
123
+ instance.thread_safe = t
124
+ end
125
+
126
+ def thread_safe
127
+ instance.thread_safe
128
+ end
129
+
130
+ # Returns whether or not Timecop is currently frozen
131
+ def frozen?
132
+ !instance.stack.empty? && instance.stack.last.mock_type == :freeze
133
+ end
134
+
135
+ # Returns whether or not Timecop is currently travelled
136
+ def travelled?
137
+ !instance.stack.empty? && instance.stack.last.mock_type == :travel
138
+ end
139
+
140
+ # Returns whether or not Timecop is currently scaled
141
+ def scaled?
142
+ !instance.stack.empty? && instance.stack.last.mock_type == :scale
143
+ end
144
+
145
+ def mock_process_clock=(mock)
146
+ @mock_process_clock = mock
147
+ end
148
+
149
+ def mock_process_clock?
150
+ @mock_process_clock ||= false
151
+ end
152
+
153
+ private
154
+ def send_travel(mock_type, *args, &block)
155
+ val = instance.travel(mock_type, *args, &block)
156
+ block_given? ? val : Time.now
157
+ end
158
+ end
159
+
160
+ def baseline=(b)
161
+ set_baseline(b)
162
+ stack << TimeStackItem.new(:travel, b)
163
+ end
164
+
165
+ def baseline
166
+ if @thread_safe
167
+ Thread.current[:timecop_baseline]
168
+ else
169
+ @baseline
170
+ end
171
+ end
172
+
173
+ def set_baseline(b)
174
+ if @thread_safe
175
+ Thread.current[:timecop_baseline] = b
176
+ else
177
+ @baseline = b
178
+ end
179
+ end
180
+
181
+ def stack
182
+ if @thread_safe
183
+ Thread.current[:timecop_stack] ||= []
184
+ Thread.current[:timecop_stack]
185
+ else
186
+ @stack
187
+ end
188
+ end
189
+
190
+ def set_stack(s)
191
+ if @thread_safe
192
+ Thread.current[:timecop_stack] = s
193
+ else
194
+ @stack = s
195
+ end
196
+ end
197
+
198
+ def initialize #:nodoc:
199
+ @stack = []
200
+ @safe = nil
201
+ @thread_safe = false
202
+ end
203
+
204
+ def thread_safe=(t)
205
+ initialize
206
+ @thread_safe = t
207
+ end
208
+
209
+ def thread_safe
210
+ @thread_safe
211
+ end
212
+
213
+ def travel(mock_type, *args, &block) #:nodoc:
214
+ raise SafeModeException if Timecop.safe_mode? && !block_given? && !@safe
215
+
216
+ stack_item = TimeStackItem.new(mock_type, *args)
217
+
218
+ stack_backup = stack.dup
219
+ stack << stack_item
220
+
221
+ if block_given?
222
+ safe_backup = @safe
223
+ @safe = true
224
+ begin
225
+ yield stack_item.time
226
+ ensure
227
+ stack.replace stack_backup
228
+ @safe = safe_backup
229
+ end
230
+ end
231
+ end
232
+
233
+ def return(&block)
234
+ current_stack = stack
235
+ current_baseline = baseline
236
+ unmock!
237
+ yield
238
+ ensure
239
+ set_stack current_stack
240
+ set_baseline current_baseline
241
+ end
242
+
243
+ def unmock! #:nodoc:
244
+ set_baseline nil
245
+ set_stack []
246
+ end
247
+
248
+ def return_to_baseline
249
+ if baseline
250
+ set_stack [stack.shift]
251
+ else
252
+ unmock!
253
+ end
254
+ end
255
+
256
+ class SafeModeException < StandardError
257
+ def initialize
258
+ super "Safe mode is enabled, only calls passing a block are allowed."
259
+ end
260
+ end
261
+ end
262
+
263
+ # This must be done after TimeCop is available
264
+ require File.join(File.dirname(__FILE__), "time_extensions")
@@ -0,0 +1,3 @@
1
+ class Timecop
2
+ VERSION = "0.9.11"
3
+ end
@@ -0,0 +1,2 @@
1
+ require File.join(File.dirname(__FILE__), "timecop", "timecop")
2
+ require File.join(File.dirname(__FILE__), "timecop", "version")
metadata ADDED
@@ -0,0 +1,50 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: nano-smart-lib
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Andrey78
8
+ bindir: bin
9
+ cert_chain: []
10
+ date: 2026-07-06 00:00:00.000000000 Z
11
+ dependencies: []
12
+ description: University research based on timecop
13
+ email:
14
+ - cakoc614@gmail.com
15
+ executables: []
16
+ extensions: []
17
+ extra_rdoc_files: []
18
+ files:
19
+ - nano-smart-lib.gemspec
20
+ - timecop-0.9.11/LICENSE
21
+ - timecop-0.9.11/README.markdown
22
+ - timecop-0.9.11/Rakefile
23
+ - timecop-0.9.11/lib/timecop.rb
24
+ - timecop-0.9.11/lib/timecop/time_extensions.rb
25
+ - timecop-0.9.11/lib/timecop/time_stack_item.rb
26
+ - timecop-0.9.11/lib/timecop/timecop.rb
27
+ - timecop-0.9.11/lib/timecop/version.rb
28
+ homepage: https://rubygems.org/profiles/Andrey78
29
+ licenses:
30
+ - MIT
31
+ metadata:
32
+ source_code_uri: https://github.com/Andrey78/nano-smart-lib
33
+ rdoc_options: []
34
+ require_paths:
35
+ - lib
36
+ required_ruby_version: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ required_rubygems_version: !ruby/object:Gem::Requirement
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ requirements: []
47
+ rubygems_version: 3.6.2
48
+ specification_version: 4
49
+ summary: Research test
50
+ test_files: []