mirror of
https://github.com/wolfcw/libfaketime.git
synced 2026-05-24 04:06:13 +03:00
Compare commits
38 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dac5d28af2 | ||
|
|
84f61b75b3 | ||
|
|
ec89c44011 | ||
|
|
837e2c7e62 | ||
|
|
e72d8e0419 | ||
|
|
4acfdddc89 | ||
|
|
0a1c887a8a | ||
|
|
18adec4fae | ||
|
|
f07939d948 | ||
|
|
68ccdb74b5 | ||
|
|
a5896e3dcb | ||
|
|
54bc41ffaf | ||
|
|
9099c4ab85 | ||
|
|
ea15324e30 | ||
|
|
e4cfb671dd | ||
|
|
ab66fd5237 | ||
|
|
86f738b25e | ||
|
|
f2ba5c7750 | ||
|
|
74852f1682 | ||
|
|
3c24c524b3 | ||
|
|
eb59447a6d | ||
|
|
ed25084970 | ||
|
|
2a384f70ba | ||
|
|
4991c61b77 | ||
|
|
b6ca32ed23 | ||
|
|
bb9b292a41 | ||
|
|
9763cdebd2 | ||
|
|
8c6c487b24 | ||
|
|
5fa942b4cf | ||
|
|
d2108361c0 | ||
|
|
403d240444 | ||
|
|
9b62bb4f38 | ||
|
|
52c30f866d | ||
|
|
cf0ccef687 | ||
|
|
9234f5df86 | ||
|
|
cd0667a7a6 | ||
|
|
46f6bd5b9b | ||
|
|
5bbb393e07 |
7
.gitignore
vendored
Normal file
7
.gitignore
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
*.o
|
||||
*.so.1
|
||||
timetest
|
||||
|
||||
src/libfaketime.dylib.1
|
||||
src/core
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
@@ -15,7 +15,7 @@ software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Library General Public License instead.) You can apply it to
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
@@ -55,7 +55,8 @@ patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
@@ -109,6 +110,7 @@ above, provided that you also meet all of these conditions:
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
@@ -166,6 +168,7 @@ access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
@@ -222,6 +225,7 @@ impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
@@ -251,7 +255,7 @@ make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
@@ -273,8 +277,9 @@ YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
How to Apply These Terms to Your New Programs
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
@@ -298,17 +303,16 @@ the "copyright" line and a pointer to where the full notice is found.
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
@@ -331,5 +335,5 @@ necessary. Here is a sample; alter the names:
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Library General
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License.
|
||||
30
Makefile
Normal file
30
Makefile
Normal file
@@ -0,0 +1,30 @@
|
||||
all:
|
||||
$(MAKE) -C src all
|
||||
$(MAKE) -C test all
|
||||
|
||||
test:
|
||||
$(MAKE) -C test all
|
||||
|
||||
install:
|
||||
$(MAKE) -C src install
|
||||
$(MAKE) -C man install
|
||||
$(INSTALL) -dm0755 "${DESTDIR}${PREFIX}/share/doc/faketime/"
|
||||
$(INSTALL) -m0644 README "${DESTDIR}${PREFIX}/share/doc/faketime/README"
|
||||
$(INSTALL) -m0644 NEWS "${DESTDIR}${PREFIX}/share/doc/faketime/NEWS"
|
||||
|
||||
uninstall:
|
||||
$(MAKE) -C src uninstall
|
||||
$(MAKE) -C man uninstall
|
||||
rm -f "${DESTDIR}${PREFIX}/share/doc/faketime/README"
|
||||
rm -f "${DESTDIR}${PREFIX}/share/doc/faketime/NEWS"
|
||||
rmdir "${DESTDIR}${PREFIX}/share/doc/faketime"
|
||||
|
||||
clean:
|
||||
$(MAKE) -C src clean
|
||||
$(MAKE) -C test clean
|
||||
|
||||
distclean:
|
||||
$(MAKE) -C src distclean
|
||||
$(MAKE) -C test distclean
|
||||
|
||||
.PHONY: all test install uninstall clean distclean
|
||||
@@ -1,6 +1,30 @@
|
||||
Since 0.8.2:
|
||||
- Added support for "limited faking".
|
||||
You can optionally specify when libfaketime starts to fake the
|
||||
returned timestamps and when it shall stop doing so. For example,
|
||||
a program can be started regularly, and after 5 minutes run-time
|
||||
it will be sent two years into the future. Those limiting
|
||||
start and stop times can be specified in seconds or as the
|
||||
number of any time-related function calls within the program.
|
||||
- Added a feature to spawn an external process after x seconds
|
||||
or y time-related system calls. This can, for example, be used
|
||||
to execute an arbitrary shell script x seconds after a program
|
||||
has been started.
|
||||
|
||||
Since 0.8.1:
|
||||
- Added a MacOS port.
|
||||
Thanks to Derrick Brashear!
|
||||
- Added a functional test framework that aids in automatically
|
||||
determining whether libfaketime works properly on the current
|
||||
machine. Thanks to Don Fong!
|
||||
|
||||
Since 0.8:
|
||||
- Changed directory layout and Makefile structure.
|
||||
Thanks to Lukas Fleischer!
|
||||
|
||||
Since 0.7:
|
||||
- Added support for fstatat() and fstatat64() which were introduced in
|
||||
Linux kernel 2.6.16 and used in recent coreutils.
|
||||
Linux kernel 2.6.16 and used in recent coreutils.
|
||||
Thanks to Daniel Kahn Gillmor for the report!
|
||||
This can be disabled by passing -DNO_ATFILE in the Makefile.
|
||||
- Added a simple wrapper shell script and a man page for it. Makes it
|
||||
@@ -9,7 +33,7 @@ Since 0.7:
|
||||
please adjust this path if necessary. The "install" target in the
|
||||
Makefile has been adapted accordingly.
|
||||
- Added support for fractional time offsets, such as FAKETIME="+1,5h".
|
||||
Please note that either , or . has to be used as a delimiter
|
||||
Please note that either , or . has to be used as a delimiter
|
||||
depending on your locale. Thanks to Karl Chen!
|
||||
- Added support for speeding the clock up or slowing it down. For
|
||||
example, FAKETIME="+5d x2,0" will set the faked time 5 days into
|
||||
@@ -18,7 +42,7 @@ Since 0.7:
|
||||
Again, the delimiter to use for the fraction depends on your locale.
|
||||
Thanks to Karl Chen!
|
||||
|
||||
Since 0.6:
|
||||
Since 0.6:
|
||||
Main version 0.7 contributions by David North, TDI:
|
||||
- Added ability to 'start clock at' a specific time.
|
||||
- Added pthread synchronization support
|
||||
@@ -31,22 +55,22 @@ Since 0.6:
|
||||
- Repaired a bug w.r.t. strptime/mktime wherein 'isdst' was uninitialized
|
||||
which led to pseudorandom +/- 1 hour results being returned in 'start at'
|
||||
or absolute time modes
|
||||
|
||||
Other enhancements:
|
||||
|
||||
Other enhancements:
|
||||
- Fixed missing interceptions to libc-internal functions and added notes
|
||||
about a workaround for running Java programs with faked times in the
|
||||
future (they worked properly, but often locked up at exiting). Thanks to
|
||||
Jamie Cameron of Google for in-depth analysis and prototype solution!
|
||||
|
||||
Since 0.5:
|
||||
- Performance enhancements by means of caching the data read
|
||||
- Performance enhancements by means of caching the data read
|
||||
e.g. from $HOME/.faketimerc for 10 seconds.
|
||||
- Several file timestamp related system calls such as fstat() will be
|
||||
intercepted now. See the README file on how to turn this off if you
|
||||
do not need it. Thanks to Philipp Hachtmann!
|
||||
- A system-wide /etc/faketimerc file will now be used if no FAKETIME
|
||||
environment variable has been set and no $HOME/.faketimerc is present.
|
||||
Thanks to David Burley, Jacob Moorman, and Wayne Davison of
|
||||
Thanks to David Burley, Jacob Moorman, and Wayne Davison of
|
||||
SourceForge, Inc.!
|
||||
- Added trivial Makefile targets clean/distclean/install
|
||||
- Changed Makefile target test to run new test.sh script
|
||||
@@ -64,4 +88,4 @@ Since 0.2:
|
||||
Since 0.1:
|
||||
- Fixed segfault when calling time(NULL). Thanks to Andres Ojamaa!
|
||||
- Added additional sanity checks.
|
||||
|
||||
|
||||
121
README
121
README
@@ -1,6 +1,6 @@
|
||||
===================================================
|
||||
FakeTime Preload Library, version 0.8 (August 2008)
|
||||
===================================================
|
||||
=====================================================
|
||||
FakeTime Preload Library, version 0.9 (February 2011)
|
||||
=====================================================
|
||||
|
||||
|
||||
Content of this file:
|
||||
@@ -17,6 +17,8 @@ Content of this file:
|
||||
e) Advanced features and caveats
|
||||
f) Faking the date and time system-wide
|
||||
g) Using the "faketime" wrapper script
|
||||
h) "Limiting" libfaketime
|
||||
i) Spawning an external process
|
||||
5. License
|
||||
6. Contact
|
||||
|
||||
@@ -81,11 +83,12 @@ it then also executes.
|
||||
|
||||
If the test works fine, you should copy the FTPL libraries (libfaketime.so.1,
|
||||
and libfaketimeMT.so.1) to the place you want them in. Running "make install"
|
||||
will attempt to place them in /usr/lib/faketime and will install the wrapper
|
||||
shell script "faketime" in /usr/bin, both of which most likely will require
|
||||
will attempt to place them in /usr/local/lib/faketime and will install the wrapper
|
||||
shell script "faketime" in /usr/local/bin, both of which most likely will require
|
||||
root privileges; however, from a technical point of view, there is no
|
||||
necessity for a system-wide installation, so you can use FTPL also on machines
|
||||
where you do not have root privileges.
|
||||
where you do not have root privileges. You may want to adjust the PREFIX
|
||||
variable in the Makefiles accordingly.
|
||||
|
||||
Since version 0.6, system calls to file timestamps are also intercepted now,
|
||||
thanks to a contribution by Philipp Hachtmann. This is especially useful in
|
||||
@@ -95,6 +98,12 @@ not need this feature or if it confuses the application you want to use FTPL
|
||||
with, define the environment variable NO_FAKE_STAT, and the intercepted stat
|
||||
calls will be passed through unaltered.
|
||||
|
||||
On MacOS, it is necessary to compile differently, due to the different
|
||||
behavior dyld has. Use the Makefile.MacOS provided to compile
|
||||
libfaketime.dylib.1. Additionally, instead of using LD_PRELOAD,
|
||||
the variable DYLD_INSERT_LIBRARIES should be set to the path to
|
||||
libfaketime.dylib.1, and the variable DYLD_FORCE_FLAT_NAMESPACE should be
|
||||
set (to anything).
|
||||
|
||||
4. Usage
|
||||
--------
|
||||
@@ -311,6 +320,104 @@ faketime '2008-12-24 08:15:42' /bin/date
|
||||
Thanks to Daniel Kahn Gillmor for providing these suggestions!
|
||||
|
||||
|
||||
4h) "Limiting" libfaketime
|
||||
--------------------------
|
||||
|
||||
Starting with version 0.9, libfaketime can be configured to not be continuously
|
||||
active, but only during a certain time interval.
|
||||
|
||||
For example, you might want to start a program with the real current time, but
|
||||
after 5 minutes of usage, you might want it to see a faked time, e.g., a year
|
||||
in the future.
|
||||
|
||||
Dynamic changes to the faked time are alternatively possible by
|
||||
|
||||
- changing the FAKETIME environment variable at run-time; this is the preferred
|
||||
way if you use libfaketime for debugging and testing as a programmer, as it
|
||||
gives you the most direct control of libfaketime without any performance
|
||||
penalities.
|
||||
|
||||
- not using the FAKETIME environment variable, but specifying the fake time in a
|
||||
file (such as ~/.faketimerc). You can change the content of this file at
|
||||
run-time. This works best with caching disabled (see Makefile), but comes at a
|
||||
performance cost because this file has to be read and evaluated each time.
|
||||
|
||||
The feature described here works based on two pairs of environment variables,
|
||||
|
||||
FAKETIME_START_AFTER_SECONDS and FAKETIME_STOP_AFTER_SECONDS, and
|
||||
FAKETIME_START_AFTER_NUMCALLS and FAKETIME_STOP_AFTER_NUMCALLS
|
||||
|
||||
The default value for each of these environment variables is -1, which means
|
||||
"ignore this value".
|
||||
|
||||
If you want libfaketime to be only active during the run-time minutes 2 to 5
|
||||
of your application, you would set
|
||||
|
||||
FAKETIME_START_AFTER_SECONDS=60
|
||||
FAKETIME_STOP_AFTER_SECONDS=300
|
||||
|
||||
This means that your application will work with the real time from start (second
|
||||
0) up to second 60. It will then see a faked time from run-time seconds 60 to
|
||||
300 (minutes 2, 3, 4, and 5). After run-time second 600, it will again see the
|
||||
real (not-faked) time.
|
||||
|
||||
This approach is not as flexible as changing the FAKETIME environment variable
|
||||
during runtime, but may be easier to use, works on a per-program (and not a
|
||||
per-user or system-wide) scope, and has only a minor performance overhead.
|
||||
|
||||
Using the other pair of environment variables, you can limit the activity time
|
||||
of libfaketime not based on wall-clock seconds, but on the number of
|
||||
time-related function calls the started program performs. This alternative is
|
||||
probably only suitable for programmers who either know the code of the program
|
||||
in order to determine useful start/stop values or want to perform fuzzing
|
||||
tests.
|
||||
|
||||
Both pairs of environment variables can be combined to further restrict
|
||||
libfaketime activity, although this is only useful in very few scenarios.
|
||||
|
||||
Limiting libfaketime activity in this way is not recommended in general. Many
|
||||
programs will break when they are subject to sudden changes in time, especially
|
||||
if they are started using the current (real) time and are then sent back into
|
||||
the past after, e.g., 5 minutes. For example, they may appear to be frozen or
|
||||
stuck because they are waiting until a certain point in time that, however, is
|
||||
never reached due to the delayed libfaketime activity. Avoid using this
|
||||
functionality unless you are sure you really need it and know what you are
|
||||
doing.
|
||||
|
||||
|
||||
4i) Spawning an external process
|
||||
--------------------------------
|
||||
|
||||
From version 0.9 on, libfaketime can execute a shell command once after an
|
||||
arbitrary number of seconds or number of time-related system calls of the
|
||||
program started. This has two limitations one needs to be aware of:
|
||||
|
||||
* Spawning the external process happens during a time-related system call
|
||||
of the original program. If you want the external process to be started
|
||||
5 seconds after program start, but this program does not make any time-
|
||||
related system calls before run-time second 8, the start of your external
|
||||
process will be delayed until run-time second 8.
|
||||
|
||||
* The original program is blocked until the external process is finished,
|
||||
because the intercepting time-related system call will not return earlier. If
|
||||
you need to start a long-running external process, make sure it forks into the
|
||||
background.
|
||||
|
||||
Spawning the external process is controlled using three environment variables:
|
||||
FAKETIME_SPAWN_TARGET, FAKETIME_SPAWN_SECONDS, FAKETIME_SPAWN_NUMCALLS.
|
||||
|
||||
Example (using bash on Linux):
|
||||
|
||||
(... usual libfaketime setup here, setting LD_PRELOAD and FAKETIME ...)
|
||||
export FAKETIME_SPAWN_TARGET="/bin/echo 'Hello world'"
|
||||
export FAKETIME_SPAWN_SECONDS=5
|
||||
/opt/local/bin/myprogram
|
||||
|
||||
This will run the "echo" command with the given parameter during the first
|
||||
time-related system function call that "myprogram" performs after running for 5
|
||||
seconds.
|
||||
|
||||
|
||||
5. License
|
||||
----------
|
||||
|
||||
@@ -327,3 +434,5 @@ appreciated.
|
||||
|
||||
Please send an email to: wolf /at/ code-wizards.com
|
||||
|
||||
git pull requests are welcome, see https://github.com/wolfcw/libfaketime
|
||||
|
||||
|
||||
98
README.OSX
Normal file
98
README.OSX
Normal file
@@ -0,0 +1,98 @@
|
||||
README file for libfaketime on Mac OS X
|
||||
=======================================
|
||||
|
||||
Support for Mac OS X is still preliminary. Development and tests are
|
||||
done under 10.7 Lion only currently.
|
||||
|
||||
Compiling and using libfaketime on OS X is slightly different than
|
||||
on Linux. Please make sure to read the README file for general
|
||||
setup and usage, and refer to this file only about OS X specifics.
|
||||
|
||||
|
||||
1) Compiling libfaketime on OS X
|
||||
--------------------------------
|
||||
|
||||
Use the OSX-specific Makefiles that are provided, e.g.:
|
||||
|
||||
cd src/
|
||||
make -f Makefile.MacOS
|
||||
|
||||
The resulting library will be named libfaketime.dylib.1
|
||||
|
||||
|
||||
2) Using libfaketime from the command line on OS X
|
||||
--------------------------------------------------
|
||||
|
||||
You will need to set three environment variables. In a Terminal.app
|
||||
or iTerm session, the following commands can be used:
|
||||
|
||||
export DYLD_FORCE_FLAT_NAMESPACE=1
|
||||
export DYLD_INSERT_LIBRARIES=/path/to/libfaketime.dylib.1
|
||||
export FAKETIME="your favorite faketime-spec here"
|
||||
|
||||
Please refer to the general README file concerning the format
|
||||
of the FAKETIME environment variable value and other environment
|
||||
variables that are related to it.
|
||||
|
||||
The "faketime" wrapper shell script has been adapted to OS X;
|
||||
it offers the same limited libfaketime functionality as on Linux
|
||||
in a simple-to-use manner without the need to manually set
|
||||
those environment variables.
|
||||
|
||||
|
||||
3) Integrating libfaketime with applications
|
||||
--------------------------------------------
|
||||
|
||||
Given the limited number of system calls libfaketime intercepts,
|
||||
it does not work too well with GUI applications on OS X. Crashes
|
||||
after a random time are common issues, some applications will
|
||||
not or at least not always see the faked time, and so on.
|
||||
|
||||
A safe way to try out whether a specific application works fine
|
||||
with libfaketime is to start it from the command line. Perform
|
||||
the steps outlined above and run the application by issuing the
|
||||
following command:
|
||||
|
||||
/Applications/ApplicationName.app/Contents/MacOS/ApplicationName
|
||||
|
||||
(Make sure to replace "ApplicationName" twice in that command with
|
||||
the name of your actual application.)
|
||||
|
||||
If it works fine, you can configure the application to permanently
|
||||
run with libfaketime by editing its Info.plist file. Add the
|
||||
LSEnvironment key unless it is already there and add a dictionary
|
||||
with the three keys like this:
|
||||
|
||||
<key>LSEnvironment</key>
|
||||
<dict>
|
||||
<key>DYLD_FORCE_FLAT_NAMESPACE</key>
|
||||
<string>1</string>
|
||||
<key>DYLD_INSERT_LIBRARIES</key>
|
||||
<string>/path/to/libfaketime.dylib.1</string>
|
||||
<key>FAKETIME</key>
|
||||
<string>value of FAKETIME here</string>
|
||||
</dict>
|
||||
|
||||
(If the application is installed in /Applications instead of in
|
||||
$HOME/Applications, you eventually will need root privileges. If
|
||||
the application's Info.plist is not in XML, but in binary format,
|
||||
use appropriate editing or conversion tools.)
|
||||
|
||||
Afterwards, you will probably need to run
|
||||
|
||||
/System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister -v -f /Applications/ApplicationName.app
|
||||
|
||||
to make sure the change to Info.plist does not go unnoticed.
|
||||
|
||||
Please note that modifications to Info.plist will be lost when the
|
||||
application is updated, so this process needs to be repeated after
|
||||
such updates, including own new builds when using Xcode.
|
||||
|
||||
|
||||
4) Notes for developers of OS X applications
|
||||
--------------------------------------------
|
||||
|
||||
The environment variable FAKETIME can be changed at application run-time
|
||||
and always takes precedence over other user-controlled settings. It can
|
||||
be re-set to 0 (zero) to work around potential incompatibilities.
|
||||
|
||||
7
TODO
Normal file
7
TODO
Normal file
@@ -0,0 +1,7 @@
|
||||
Open issues / next steps for libfaketime development
|
||||
|
||||
- add more functional tests that check more than the basic functionality
|
||||
- use the new testing framework to also implement unit tests
|
||||
- make the new "limiting" and "spawning" features more flexible to use
|
||||
and available through the wrapper shell script
|
||||
|
||||
14
man/Makefile
Normal file
14
man/Makefile
Normal file
@@ -0,0 +1,14 @@
|
||||
INSTALL = install
|
||||
|
||||
PREFIX = /usr/local
|
||||
|
||||
all:
|
||||
|
||||
install:
|
||||
$(INSTALL) -Dm0644 faketime.1 "${DESTDIR}${PREFIX}/share/man/man1/faketime.1"
|
||||
gzip -f "${DESTDIR}${PREFIX}/share/man/man1/faketime.1"
|
||||
|
||||
uninstall:
|
||||
rm -f "${DESTDIR}${PREFIX}/share/man/man1/faketime.1.gz"
|
||||
|
||||
.PHONY: all install uninstall
|
||||
58
src/Makefile
58
src/Makefile
@@ -30,6 +30,13 @@
|
||||
# frequently. Disabling the cache may negatively influence the
|
||||
# performance.
|
||||
#
|
||||
# LIMITEDFAKING
|
||||
# - Support environment variables that limit time faking to certain
|
||||
# time intervals or number of function calls.
|
||||
#
|
||||
# SPAWNSUPPORT
|
||||
# - Enable support for spawning an external process at a given
|
||||
# timestamp.
|
||||
#
|
||||
# * Compilation addition: second libMT target added for building the pthread-
|
||||
# enabled library as a separate library
|
||||
@@ -41,42 +48,45 @@
|
||||
#
|
||||
|
||||
CC = gcc
|
||||
INSTALL = install
|
||||
|
||||
all: lib libMT testprog test
|
||||
PREFIX = /usr/local
|
||||
|
||||
libs: lib libMT
|
||||
CFLAGS += -std=gnu99 -Wall -DFAKE_STAT -DFAKE_INTERNAL_CALLS -fPIC -DPOSIX_REALTIME -DLIMITEDFAKING -DSPAWNSUPPORT
|
||||
LDFLAGS += -shared -ldl -lm -lpthread
|
||||
|
||||
lib: faketime.c
|
||||
${CC} -DFAKE_STAT -DFAKE_INTERNAL_CALLS -shared -fPIC -Wl,-soname,libfaketime.so.1 -o libfaketime.so.1 faketime.c -ldl -lm -lpthread
|
||||
SRC = faketime.c
|
||||
OBJ = faketime.o faketimeMT.o
|
||||
|
||||
libMT: faketime.c
|
||||
${CC} -DFAKE_STAT -DFAKE_INTERNAL_CALLS -DPTHREAD -DPTHREAD_SINGLETHREADED_TIME -shared -fPIC -Wl,-soname,libfaketimeMT.so.1 -o libfaketimeMT.so.1 faketime.c -ldl -lm -lpthread
|
||||
SONAME = 1
|
||||
LIBS = libfaketime.so.${SONAME} libfaketimeMT.so.${SONAME}
|
||||
|
||||
testprog: timetest.c
|
||||
${CC} -DFAKE_STAT -o timetest timetest.c -lrt
|
||||
all: ${LIBS}
|
||||
|
||||
test: lib testprog
|
||||
@echo
|
||||
@./test.sh
|
||||
faketimeMT.o: EXTRA_FLAGS := -DPTHREAD -DPTHREAD_SINGLETHREADED_TIME
|
||||
|
||||
notest: lib libMT testprog
|
||||
@echo
|
||||
${OBJ}: faketime.c
|
||||
${CC} -o $@ -c ${CFLAGS} ${EXTRA_FLAGS} $<
|
||||
|
||||
lib%.so.${SONAME}: %.o
|
||||
${CC} -o $@ -Wl,-soname,$@ ${LDFLAGS} $<
|
||||
|
||||
clean:
|
||||
@rm -f libfaketime.so.1 libfaketimeMT.so.1 timetest
|
||||
@rm -f ${OBJ} ${LIBS}
|
||||
|
||||
distclean: clean
|
||||
@echo
|
||||
|
||||
install: libs
|
||||
install: ${LIBS}
|
||||
@echo
|
||||
@echo "Copying the libraries to /usr/lib/faketime and the wrapper script to /usr/bin ..."
|
||||
-mkdir -p /usr/lib/faketime
|
||||
cp libfaketime.so.1 libfaketimeMT.so.1 /usr/lib/faketime
|
||||
cp faketime /usr/bin
|
||||
cp faketime.1 /usr/share/man/man1/faketime.1
|
||||
gzip /usr/share/man/man1/faketime.1
|
||||
-mkdir -p /usr/share/doc/faketime
|
||||
cp README /usr/share/doc/faketime/README
|
||||
cp Changelog /usr/share/doc/faketime/Changelog
|
||||
@echo "Copying the faketime libraries to ${DESTDIR}${PREFIX}/lib/faketime and the faketime wrapper script to ${DESTDIR}${PREFIX}/bin ..."
|
||||
$(INSTALL) -dm0755 "${DESTDIR}${PREFIX}/lib/faketime/"
|
||||
$(INSTALL) -m0644 ${LIBS} "${DESTDIR}${PREFIX}/lib/faketime/"
|
||||
$(INSTALL) -Dm0755 faketime "${DESTDIR}${PREFIX}/bin/faketime"
|
||||
|
||||
uninstall:
|
||||
for f in ${LIBS}; do rm -f "${DESTDIR}${PREFIX}/lib/faketime/$$f"; done
|
||||
rmdir "${DESTDIR}${PREFIX}/lib/faketime"
|
||||
rm -f "${DESTDIR}${PREFIX}/bin/faketime"
|
||||
|
||||
.PHONY: all clean distclean install uninstall
|
||||
|
||||
91
src/Makefile.MacOS
Normal file
91
src/Makefile.MacOS
Normal file
@@ -0,0 +1,91 @@
|
||||
#
|
||||
# Notes:
|
||||
#
|
||||
# * Compilation Defines:
|
||||
#
|
||||
# FAKE_STAT
|
||||
# - Enables time faking also for files' timestamps.
|
||||
#
|
||||
# NO_ATFILE
|
||||
# - Disables support for the fstatat() group of functions
|
||||
#
|
||||
# PTHREAD
|
||||
# - Define this to enable multithreading support.
|
||||
#
|
||||
# PTHREAD_SINGLETHREADED_TIME
|
||||
# - Define this if you want to single-thread time() ... there ARE
|
||||
# possibile caching side-effects in a multithreaded environment
|
||||
# without this, but the performance impact may require you to
|
||||
# try it unsynchronized.
|
||||
#
|
||||
# FAKE_INTERNAL_CALLS
|
||||
# - Also intercept libc internal __functions, e.g. not just time(),
|
||||
# but also __time(). Enhances compatibility with applications
|
||||
# that make use of low-level system calls, such as Java Virtual
|
||||
# Machines.
|
||||
#
|
||||
# NO_CACHING
|
||||
# - Disables the caching of the fake time offset. Only disable caching
|
||||
# if you change the fake time offset during program runtime very
|
||||
# frequently. Disabling the cache may negatively influence the
|
||||
# performance.
|
||||
#
|
||||
# LIMITEDFAKING
|
||||
# - Support environment variables that limit time faking to certain
|
||||
# time intervals or number of function calls.
|
||||
#
|
||||
# SPAWNSUPPORT
|
||||
# - Enable support for spawning an external process at a given
|
||||
# timestamp.
|
||||
#
|
||||
#
|
||||
# * Compilation addition: second libMT target added for building the pthread-
|
||||
# enabled library as a separate library
|
||||
#
|
||||
# * Compilation switch change: previous versions compiled using '-nostartfiles'
|
||||
# This is no longer the case since there is a 'startup' constructor for the library
|
||||
# which is used to activate the start-at times when specified. This also initializes
|
||||
# the dynamic disabling of the FAKE_STAT calls.
|
||||
#
|
||||
|
||||
CC = gcc
|
||||
INSTALL = install
|
||||
|
||||
PREFIX = /usr/local
|
||||
|
||||
# If you get an error about an unsupported architecture, remove it. Some
|
||||
# versions of XCode support different subsets of architectures, depending on
|
||||
# age.
|
||||
# 10.5
|
||||
#CFLAGS = -dynamiclib -DFAKE_INTERNAL_CALLS -arch i386 -arch ppc
|
||||
# 10.6
|
||||
CFLAGS = -dynamiclib -DFAKE_INTERNAL_CALLS -arch i386 -arch x86_64 -DLIMITEDFAKING -DSPAWNSUPPORT
|
||||
SRC = faketime.c
|
||||
|
||||
SONAME = 1
|
||||
LIBS = libfaketime.dylib.${SONAME}
|
||||
|
||||
all: ${LIBS}
|
||||
|
||||
libfaketime.dylib.${SONAME}: ${SRC}
|
||||
${CC} -o $@ ${CFLAGS} $<
|
||||
|
||||
clean:
|
||||
@rm -f ${OBJ} ${LIBS}
|
||||
|
||||
distclean: clean
|
||||
@echo
|
||||
|
||||
install: ${LIBS}
|
||||
@echo
|
||||
@echo "Copying the faketime libraries to ${DESTDIR}${PREFIX}/lib/faketime and the faketime wrapper script to ${DESTDIR}${PREFIX}/bin ..."
|
||||
$(INSTALL) -dm0755 "${DESTDIR}${PREFIX}/lib/faketime/"
|
||||
$(INSTALL) -m0644 ${LIBS} "${DESTDIR}${PREFIX}/lib/faketime/"
|
||||
$(INSTALL) -Dm0755 faketime "${DESTDIR}${PREFIX}/bin/faketime"
|
||||
|
||||
uninstall:
|
||||
for f in ${LIBS}; do rm -f "${DESTDIR}${PREFIX}/lib/faketime/$$f"; done
|
||||
rmdir "${DESTDIR}${PREFIX}/lib/faketime"
|
||||
rm -f "${DESTDIR}${PREFIX}/bin/faketime"
|
||||
|
||||
.PHONY: all clean distclean install uninstall
|
||||
20
src/faketime
20
src/faketime
@@ -12,11 +12,16 @@
|
||||
# Acknowledgment: Parts of the functionality of this wrapper have been
|
||||
# inspired by Matthias Urlichs' datefudge 1.14.
|
||||
|
||||
# Configuration: Path where the libfaketime libraries can be found.
|
||||
# Configuration: Path where the libfaketime libraries can be found on Linux/UNIX.
|
||||
FTPL_PATH=/usr/lib/faketime
|
||||
|
||||
# For Mac OS X users: Full path and name to libfaketime.dylib.1
|
||||
MAC_FTPL_PATH=./libfaketime.dylib.1
|
||||
|
||||
offset="$1"
|
||||
|
||||
DATE_CMD=date
|
||||
|
||||
USEMT=0
|
||||
USEDIRECT=0
|
||||
|
||||
@@ -60,8 +65,15 @@ fi
|
||||
|
||||
shift
|
||||
|
||||
# Setting LD_PRELOAD ...
|
||||
# Check whether we are on Mac OS X (Darwin)
|
||||
UNAME=$(uname)
|
||||
if [ "$UNAME" = "Darwin" ] ; then
|
||||
export DYLD_FORCE_FLAT_NAMESPACE=1
|
||||
export DYLD_INSERT_LIBRARIES=$MAC_FTPL_PATH
|
||||
DATE_CMD=gdate
|
||||
fi
|
||||
|
||||
# Setting LD_PRELOAD ...
|
||||
if [ "$USEMT" -eq 0 ] ; then
|
||||
export LD_PRELOAD="${LD_PRELOAD}${LD_PRELOAD:+:}$FTPL_PATH/libfaketime.so.1"
|
||||
fi
|
||||
@@ -74,13 +86,13 @@ fi
|
||||
# Setting FAKETIME ...
|
||||
|
||||
if [ "$USEDIRECT" -eq 0 ] ; then
|
||||
seconds=$(date -d "$offset" '+%s')
|
||||
seconds=$($DATE_CMD -d "$offset" '+%s')
|
||||
if [ $? -ne 0 ] ; then
|
||||
echo "Error: Timestamp to fake not recognized, please re-try with a different timestamp."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
offset=$(expr $seconds - $(date '+%s'))
|
||||
offset=$(expr $seconds - $($DATE_CMD '+%s'))
|
||||
if [ $? -ne 0 ] ; then
|
||||
echo "Error: Cannot calculate the faketime offset in seconds, please re-try with a different timestamp."
|
||||
exit 1
|
||||
|
||||
205
src/faketime.c
205
src/faketime.c
@@ -1,6 +1,4 @@
|
||||
/*
|
||||
* Copyright (C) 2003,2004,2005,2006,2007,2008 Wolfgang Hommel
|
||||
*
|
||||
* This file is part of the FakeTime Preload Library, version 0.8.
|
||||
*
|
||||
* The FakeTime Preload Library is free software; you can redistribute it
|
||||
@@ -60,7 +58,9 @@ static pthread_mutex_t once_mutex=PTHREAD_MUTEX_INITIALIZER;
|
||||
time_t fake_time(time_t *time_tptr);
|
||||
int fake_ftime(struct timeb *tp);
|
||||
int fake_gettimeofday(struct timeval *tv, void *tz);
|
||||
#ifdef POSIX_REALTIME
|
||||
int fake_clock_gettime(clockid_t clk_id, struct timespec *tp);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Intercepted system calls:
|
||||
@@ -375,6 +375,16 @@ int __lxstat64 (int ver, const char *path, struct stat64 *buf){
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* On MacOS, time() internally uses gettimeofday. If we don't
|
||||
* break the cycle by just calling it directly, we double-apply
|
||||
* relative changes.
|
||||
*/
|
||||
|
||||
#ifdef __APPLE__
|
||||
static int (*real_gettimeofday)(struct timeval *, void *);
|
||||
static int has_real_gettimeofday = 0;
|
||||
#endif
|
||||
/*
|
||||
* Our version of time() allows us to return fake values, so the calling
|
||||
* program thinks it's retrieving the current date and time, while it is
|
||||
@@ -382,26 +392,54 @@ int __lxstat64 (int ver, const char *path, struct stat64 *buf){
|
||||
* Note that this routine is split into two parts so that the initialization
|
||||
* piece can call the 'real' time function to establish a base time.
|
||||
*/
|
||||
|
||||
static time_t _ftpl_time(time_t *time_tptr) {
|
||||
#ifdef __APPLE__
|
||||
struct timeval tvm, *tv = &tvm;
|
||||
#else
|
||||
static time_t (*real_time)(time_t *);
|
||||
static int has_real_time = 0;
|
||||
#endif
|
||||
|
||||
time_t result;
|
||||
|
||||
time_t null_dummy;
|
||||
|
||||
|
||||
/* Handle null pointers correctly, fix as suggested by Andres Ojamaa */
|
||||
if (time_tptr == NULL) {
|
||||
time_tptr = &null_dummy;
|
||||
/* (void) fprintf(stderr, "NULL pointer caught in time().\n"); */
|
||||
}
|
||||
|
||||
|
||||
#ifdef __APPLE__
|
||||
/* Check whether we've got a pointer to the real ftime() function yet */
|
||||
SINGLE_IF(has_real_gettimeofday==0)
|
||||
real_gettimeofday = NULL;
|
||||
real_gettimeofday = dlsym(RTLD_NEXT, "gettimeofday");
|
||||
|
||||
/* check whether dlsym() worked */
|
||||
if (dlerror() == NULL) {
|
||||
has_real_gettimeofday = 1;
|
||||
}
|
||||
END_SINGLE_IF
|
||||
if (!has_real_gettimeofday) { /* dlsym() failed */
|
||||
#ifdef DEBUG
|
||||
(void) fprintf(stderr, "faketime problem: original gettimeofday() not found.\n");
|
||||
#endif
|
||||
return -1; /* propagate error to caller */
|
||||
}
|
||||
|
||||
/* initialize our result with the real current time */
|
||||
result = (*real_gettimeofday)(tv, NULL);
|
||||
if (result == -1) return result; /* original function failed */
|
||||
if (time_tptr != NULL)
|
||||
*time_tptr = tv->tv_sec;
|
||||
result = tv->tv_sec;
|
||||
#else
|
||||
/* Check whether we've got a pointer to the real time function yet */
|
||||
SINGLE_IF(has_real_time==0)
|
||||
real_time = NULL;
|
||||
real_time = dlsym(RTLD_NEXT, "time");
|
||||
|
||||
|
||||
/* check whether dlsym() worked */
|
||||
if (dlerror() == NULL) {
|
||||
has_real_time = 1;
|
||||
@@ -415,9 +453,11 @@ static time_t _ftpl_time(time_t *time_tptr) {
|
||||
*time_tptr = -1;
|
||||
return -1; /* propagate error to caller */
|
||||
}
|
||||
|
||||
|
||||
/* initialize our result with the real current time */
|
||||
result = (*real_time)(time_tptr);
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -477,10 +517,12 @@ int ftime(struct timeb *tp) {
|
||||
}
|
||||
|
||||
int gettimeofday(struct timeval *tv, void *tz) {
|
||||
#ifndef __APPLE__
|
||||
static int (*real_gettimeofday)(struct timeval *, void *);
|
||||
static int has_real_gettimeofday = 0;
|
||||
#endif
|
||||
int result;
|
||||
|
||||
|
||||
/* sanity check */
|
||||
if (tv == NULL) {
|
||||
return -1;
|
||||
@@ -509,11 +551,12 @@ int gettimeofday(struct timeval *tv, void *tz) {
|
||||
|
||||
/* pass the real current time to our faking version, overwriting it */
|
||||
result = fake_gettimeofday(tv, tz);
|
||||
|
||||
|
||||
/* return the result to the caller */
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifdef POSIX_REALTIME
|
||||
int clock_gettime(clockid_t clk_id, struct timespec *tp) {
|
||||
static int (*real_clock_gettime)(clockid_t clk_id, struct timespec *tp);
|
||||
static int has_real_clock_gettime = 0;
|
||||
@@ -551,6 +594,7 @@ int clock_gettime(clockid_t clk_id, struct timespec *tp) {
|
||||
/* return the result to the caller */
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Static time_t to store our startup time, followed by a load-time library
|
||||
@@ -586,6 +630,33 @@ time_t fake_time(time_t *time_tptr) {
|
||||
static int cache_expired = 1; /* considered expired at first call */
|
||||
static int cache_duration = 10; /* cache fake time input for 10 seconds */
|
||||
|
||||
#ifdef LIMITEDFAKING
|
||||
static long callcounter = 0;
|
||||
static int limited_initialized = 0;
|
||||
char envvarbuf[32];
|
||||
static long FAKETIME_START_AFTER_SECONDS = -1;
|
||||
static long FAKETIME_STOP_AFTER_SECONDS = -1;
|
||||
static long FAKETIME_START_AFTER_NUMCALLS = -1;
|
||||
static long FAKETIME_STOP_AFTER_NUMCALLS = -1;
|
||||
#endif
|
||||
|
||||
#ifdef SPAWNSUPPORT
|
||||
static int spawned = 0;
|
||||
static long spawn_callcounter = 0;
|
||||
static int spawn_initialized = 0;
|
||||
char spawn_envvarbuf[32];
|
||||
static char FAKETIME_SPAWN_TARGET[1024];
|
||||
static long FAKETIME_SPAWN_SECONDS = -1;
|
||||
static long FAKETIME_SPAWN_NUMCALLS = -1;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This no longer appears to be necessary in Mac OS X 10.7 Lion
|
||||
*/
|
||||
//#ifdef __APPLE__
|
||||
// static int malloc_arena = 0;
|
||||
//#endif
|
||||
|
||||
#ifdef PTHREAD_SINGLETHREADED_TIME
|
||||
static pthread_mutex_t time_mutex=PTHREAD_MUTEX_INITIALIZER;
|
||||
pthread_mutex_lock(&time_mutex);
|
||||
@@ -595,13 +666,84 @@ static pthread_mutex_t time_mutex=PTHREAD_MUTEX_INITIALIZER;
|
||||
/* Sanity check by Karl Chan since v0.8 */
|
||||
if (time_tptr == NULL) return -1;
|
||||
|
||||
#ifdef LIMITEDFAKING
|
||||
/* Check whether we actually should be faking the returned timestamp. */
|
||||
|
||||
if (ftpl_starttime > 0) {
|
||||
if (limited_initialized == 0) {
|
||||
if (getenv("FAKETIME_START_AFTER_SECONDS") != NULL) {
|
||||
(void) strncpy(envvarbuf, getenv("FAKETIME_START_AFTER_SECONDS"), 30);
|
||||
FAKETIME_START_AFTER_SECONDS = atol(envvarbuf);
|
||||
}
|
||||
if (getenv("FAKETIME_STOP_AFTER_SECONDS") != NULL) {
|
||||
(void) strncpy(envvarbuf, getenv("FAKETIME_STOP_AFTER_SECONDS"), 30);
|
||||
FAKETIME_STOP_AFTER_SECONDS = atol(envvarbuf);
|
||||
}
|
||||
if (getenv("FAKETIME_START_AFTER_NUMCALLS") != NULL) {
|
||||
(void) strncpy(envvarbuf, getenv("FAKETIME_START_AFTER_NUMCALLS"), 30);
|
||||
FAKETIME_START_AFTER_NUMCALLS = atol(envvarbuf);
|
||||
}
|
||||
if (getenv("FAKETIME_STOP_AFTER_NUMCALLS") != NULL) {
|
||||
(void) strncpy(envvarbuf, getenv("FAKETIME_STOP_AFTER_NUMCALLS"), 30);
|
||||
FAKETIME_STOP_AFTER_NUMCALLS = atol(envvarbuf);
|
||||
}
|
||||
limited_initialized = 1;
|
||||
}
|
||||
if ((callcounter + 1) >= callcounter) callcounter++;
|
||||
|
||||
/* For debugging, output #seconds and #calls */
|
||||
/* fprintf(stderr, "(libfaketime limits -> runtime: %lu, callcounter: %lu\n", (*time_tptr - ftpl_starttime), callcounter); */
|
||||
if ((FAKETIME_START_AFTER_SECONDS != -1) && ((*time_tptr - ftpl_starttime) < FAKETIME_START_AFTER_SECONDS)) return *time_tptr;
|
||||
if ((FAKETIME_STOP_AFTER_SECONDS != -1) && ((*time_tptr - ftpl_starttime) >= FAKETIME_STOP_AFTER_SECONDS)) return *time_tptr;
|
||||
if ((FAKETIME_START_AFTER_NUMCALLS != -1) && (callcounter < FAKETIME_START_AFTER_NUMCALLS)) return *time_tptr;
|
||||
if ((FAKETIME_STOP_AFTER_NUMCALLS != -1) && (callcounter >= FAKETIME_STOP_AFTER_NUMCALLS)) return *time_tptr;
|
||||
/* fprintf(stderr, "(libfaketime limits -> runtime: %lu, callcounter: %lu continues\n", (*time_tptr - ftpl_starttime), callcounter); */
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SPAWNSUPPORT
|
||||
/* check whether we should spawn an external command */
|
||||
|
||||
if (ftpl_starttime > 0) {
|
||||
|
||||
if(spawn_initialized == 0) {
|
||||
if (getenv("FAKETIME_SPAWN_TARGET") != NULL) {
|
||||
(void) strncpy(FAKETIME_SPAWN_TARGET, getenv("FAKETIME_SPAWN_TARGET"), 1024);
|
||||
|
||||
if (getenv("FAKETIME_SPAWN_SECONDS") != NULL) {
|
||||
(void) strncpy(spawn_envvarbuf, getenv("FAKETIME_SPAWN_SECONDS"), 30);
|
||||
FAKETIME_SPAWN_SECONDS = atol(spawn_envvarbuf);
|
||||
}
|
||||
|
||||
if (getenv("FAKETIME_SPAWN_NUMCALLS") != NULL) {
|
||||
(void) strncpy(spawn_envvarbuf, getenv("FAKETIME_SPAWN_NUMCALLS"), 30);
|
||||
FAKETIME_SPAWN_NUMCALLS = atol(spawn_envvarbuf);
|
||||
}
|
||||
}
|
||||
spawn_initialized = 1;
|
||||
}
|
||||
|
||||
if (spawned == 0) { /* exec external command once only */
|
||||
if ((spawn_callcounter + 1) >= spawn_callcounter) spawn_callcounter++;
|
||||
if ((((*time_tptr - ftpl_starttime) == FAKETIME_SPAWN_SECONDS) || (spawn_callcounter == FAKETIME_SPAWN_NUMCALLS)) && (spawned == 0)) {
|
||||
spawned = 1;
|
||||
system(FAKETIME_SPAWN_TARGET);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
if (last_data_fetch > 0) {
|
||||
if ((*time_tptr - last_data_fetch) > cache_duration) {
|
||||
cache_expired = 1;
|
||||
}
|
||||
if ((*time_tptr - last_data_fetch) > cache_duration) {
|
||||
cache_expired = 1;
|
||||
}
|
||||
else {
|
||||
cache_expired = 0;
|
||||
}
|
||||
cache_expired = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef NO_CACHING
|
||||
@@ -654,6 +796,16 @@ static pthread_mutex_t time_mutex=PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
} /* cache had expired */
|
||||
|
||||
/*
|
||||
* This no longer appears to be necessary in Mac OS X 10.7 Lion
|
||||
*/
|
||||
//#ifdef __APPLE__
|
||||
// SINGLE_IF(malloc_arena==0)
|
||||
// malloc_arena = 1;
|
||||
// return *time_tptr;
|
||||
// END_SINGLE_IF
|
||||
//#endif
|
||||
|
||||
/* check whether the user gave us an absolute time to fake */
|
||||
switch (user_faked_time[0]) {
|
||||
|
||||
@@ -724,41 +876,49 @@ static pthread_mutex_t time_mutex=PTHREAD_MUTEX_INITIALIZER;
|
||||
}
|
||||
|
||||
int fake_ftime(struct timeb *tp) {
|
||||
time_t temp_tt;
|
||||
time_t temp_tt = tp->time;
|
||||
|
||||
tp->time = time(&temp_tt);
|
||||
tp->time = fake_time(&temp_tt);
|
||||
|
||||
return 0; /* always returns 0, see manpage */
|
||||
}
|
||||
|
||||
int fake_gettimeofday(struct timeval *tv, void *tz) {
|
||||
time_t temp_tt;
|
||||
|
||||
tv->tv_sec = time(&temp_tt);
|
||||
time_t temp_tt = tv->tv_sec;
|
||||
|
||||
tv->tv_sec = fake_time(&temp_tt);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef POSIX_REALTIME
|
||||
int fake_clock_gettime(clockid_t clk_id, struct timespec *tp) {
|
||||
time_t temp_tt;
|
||||
time_t temp_tt = tp->tv_sec;
|
||||
|
||||
/* Fake only if the call is realtime clock related */
|
||||
if (clk_id == CLOCK_REALTIME) {
|
||||
tp->tv_sec = time(&temp_tt);
|
||||
tp->tv_sec = fake_time(&temp_tt);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This causes serious issues in Mac OS X 10.7 Lion and is disabled there
|
||||
*/
|
||||
#ifndef __APPLE__
|
||||
/* Added in v0.7 as suggested by Jamie Cameron, Google */
|
||||
#ifdef FAKE_INTERNAL_CALLS
|
||||
int __gettimeofday(struct timeval *tv, void *tz) {
|
||||
return gettimeofday(tv, tz);
|
||||
}
|
||||
|
||||
#ifdef POSIX_REALTIME
|
||||
int __clock_gettime(clockid_t clk_id, struct timespec *tp) {
|
||||
return clock_gettime(clk_id, tp);
|
||||
}
|
||||
#endif
|
||||
|
||||
int __ftime(struct timeb *tp) {
|
||||
return ftime(tp);
|
||||
@@ -768,4 +928,7 @@ time_t __time(time_t *time_tptr) {
|
||||
return time(time_tptr);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* eof */
|
||||
|
||||
|
||||
40
src/test.sh
40
src/test.sh
@@ -1,40 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
if [ -f /etc/faketimerc ] ; then
|
||||
echo "Running the test program with your system-wide default in /etc/faketimerc"
|
||||
echo "\$ LD_PRELOAD=./libfaketime.so.1 ./timetest"
|
||||
LD_PRELOAD=./libfaketime.so.1 ./timetest
|
||||
echo
|
||||
else
|
||||
echo "Running the test program with no faked time specified"
|
||||
echo "\$ LD_PRELOAD=./libfaketime.so.1 ./timetest"
|
||||
LD_PRELOAD=./libfaketime.so.1 ./timetest
|
||||
echo
|
||||
fi
|
||||
|
||||
echo "Running the test program with absolute date 2003-01-01 10:00:05 specified"
|
||||
echo "\$ LD_PRELOAD=./libfaketime.so.1 FAKETIME=\"2003-01-01 10:00:05\" ./timetest"
|
||||
LD_PRELOAD=./libfaketime.so.1 FAKETIME="2003-01-01 10:00:05" ./timetest
|
||||
echo
|
||||
|
||||
echo "Running the test program with START date @2005-03-29 14:14:14 specified"
|
||||
echo "\$ LD_PRELOAD=./libfaketime.so.1 FAKETIME=\"@2005-03-29 14:14:14\" ./timetest"
|
||||
LD_PRELOAD=./libfaketime.so.1 FAKETIME="@2005-03-29 14:14:14" ./timetest
|
||||
echo
|
||||
|
||||
echo "Running the test program with 10 days negative offset specified"
|
||||
echo "LD_PRELOAD=./libfaketime.so.1 FAKETIME=\"-10d\" ./timetest"
|
||||
LD_PRELOAD=./libfaketime.so.1 FAKETIME="-10d" ./timetest
|
||||
echo
|
||||
|
||||
echo "Running the test program with 10 days negative offset specified, and FAKE_STAT disabled"
|
||||
echo "\$ LD_PRELOAD=./libfaketime.so.1 FAKETIME=\"-10d\" NO_FAKE_STAT=1 ./timetest"
|
||||
LD_PRELOAD=./libfaketime.so.1 FAKETIME="-10d" NO_FAKE_STAT=1 ./timetest
|
||||
echo
|
||||
|
||||
echo "Running the 'date' command with 15 days negative offset specified"
|
||||
echo "\$ LD_PRELOAD=./libfaketime.so.1 FAKETIME=\"-15d\" date"
|
||||
LD_PRELOAD=./libfaketime.so.1 FAKETIME="-15d" date
|
||||
echo
|
||||
|
||||
exit 0
|
||||
31
test/Makefile
Normal file
31
test/Makefile
Normal file
@@ -0,0 +1,31 @@
|
||||
CC = gcc
|
||||
|
||||
CFLAGS = -std=gnu99 -Wall -DFAKE_STAT
|
||||
LDFLAGS = -lrt
|
||||
|
||||
SRC = timetest.c
|
||||
OBJ = ${SRC:.c=.o}
|
||||
|
||||
all: timetest test
|
||||
|
||||
.c.o:
|
||||
${CC} -c ${CFLAGS} $<
|
||||
|
||||
timetest: ${OBJ}
|
||||
${CC} -o $@ ${OBJ} ${LDFLAGS}
|
||||
|
||||
test: timetest functest
|
||||
@echo
|
||||
@./test.sh
|
||||
|
||||
# run functional tests
|
||||
functest:
|
||||
./testframe.sh functests
|
||||
|
||||
clean:
|
||||
@rm -f ${OBJ} timetest
|
||||
|
||||
distclean: clean
|
||||
@echo
|
||||
|
||||
.PHONY: all test clean distclean
|
||||
31
test/Makefile.MacOS
Normal file
31
test/Makefile.MacOS
Normal file
@@ -0,0 +1,31 @@
|
||||
CC = gcc
|
||||
|
||||
CFLAGS = -std=gnu99 -Wall -DFAKE_STAT
|
||||
LDFLAGS =
|
||||
|
||||
SRC = timetest.c
|
||||
OBJ = ${SRC:.c=.o}
|
||||
|
||||
all: timetest test
|
||||
|
||||
.c.o:
|
||||
${CC} -c ${CFLAGS} $<
|
||||
|
||||
timetest: ${OBJ}
|
||||
${CC} -o $@ ${OBJ} ${LDFLAGS}
|
||||
|
||||
test: timetest functest
|
||||
@echo
|
||||
@./test.sh
|
||||
|
||||
# run functional tests
|
||||
functest:
|
||||
./testframe.sh functests
|
||||
|
||||
clean:
|
||||
@rm -f ${OBJ} timetest
|
||||
|
||||
distclean: clean
|
||||
@echo
|
||||
|
||||
.PHONY: all test clean distclean
|
||||
39
test/README-testframe.txt
Normal file
39
test/README-testframe.txt
Normal file
@@ -0,0 +1,39 @@
|
||||
# here's how the testframe script works.
|
||||
#
|
||||
# Usage for testing:
|
||||
# usage: testframe.sh DIR
|
||||
# testframe.sh runs each testsuite script found within DIR.
|
||||
# (in the context of libfaketime, the DIR is functest.)
|
||||
# exits with status 0 if all tests succeed.
|
||||
#
|
||||
# Interface:
|
||||
# by convention, each testsuite script (within DIR) must be
|
||||
# a bash script named test_*.sh. the script must define a
|
||||
# function named "run". run takes no arguments. run is
|
||||
# expected to call the framework-provided function
|
||||
# run_testcase once for each test function. run_testcase
|
||||
# uses the global vars NFAIL and NSUCC to keep track of how
|
||||
# many testcases failed/succeeded.
|
||||
#
|
||||
# the test function is expected to call something like
|
||||
# asserteq or assertneq (again, framework-provided).
|
||||
#
|
||||
# fine print: for each testsuite, the framework creates a
|
||||
# subshell and dots in the script. also dotted in are
|
||||
# testframe.inc and DIR/common.inc (if it exists). the
|
||||
# testsuite script can make use of any functions defined
|
||||
# in these inc files. the environment variable
|
||||
# TESTSUITE_NAME is set to the filename of the testsuite
|
||||
# script, for possible use in warning or info messages.
|
||||
#
|
||||
# see functests/test_true.sh for a simple example of
|
||||
# a test suite script.
|
||||
#
|
||||
# Simple steps to add a new testsuite:
|
||||
# 1. decide its name - eg, XXX.
|
||||
# 2. choose a DIR of similar testsuites to put it in, or create a new one.
|
||||
# 3. create DIR/test_XXX.sh.
|
||||
# 4. write a run function and testcase functions in DIR/test_XXX.sh.
|
||||
# 5. within the run function, call run_testcase for each testcase function.
|
||||
# 6. within each testcase funtion, call assertneq or asserteq, or do
|
||||
# the equivalent.
|
||||
52
test/functests/common.inc
Normal file
52
test/functests/common.inc
Normal file
@@ -0,0 +1,52 @@
|
||||
# libfaketime-specific common support routines for tests
|
||||
|
||||
# say which *_fakecmd wrapper to use
|
||||
platform()
|
||||
{
|
||||
# may want to expand the pattern for linuxlike
|
||||
typeset out=$(uname)
|
||||
case "$out" in
|
||||
*Darwin*) echo "mac" ;;
|
||||
*Linux*) echo "linuxlike" ;;
|
||||
*) echo 1>&2 unsupported platform, uname=\"$out\" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# run faked command on a mac
|
||||
# UNTESTED
|
||||
mac_fakecmd()
|
||||
{
|
||||
typeset timestring="$1"; shift
|
||||
typeset fakelib=../src/libfaketime.dylib.1
|
||||
export DYLD_INSERT_LIBRARIES=$fakelib
|
||||
export DYLD_FORCE_FLAT_NAMESPACE=1
|
||||
FAKETIME="$timestring" \
|
||||
"$@"
|
||||
}
|
||||
|
||||
# run faked command on linuxlike OS
|
||||
linuxlike_fakecmd()
|
||||
{
|
||||
typeset timestring="$1"; shift
|
||||
typeset fakelib=../src/libfaketime.so.1
|
||||
export LD_PRELOAD=$fakelib
|
||||
FAKETIME="$timestring" \
|
||||
"$@"
|
||||
}
|
||||
|
||||
# run a command with libfaketime using the given timestring
|
||||
fakecmd()
|
||||
{
|
||||
${PLATFORM}_fakecmd "$@"
|
||||
}
|
||||
|
||||
# generate a sequence of numbers from a to b
|
||||
range()
|
||||
{
|
||||
typeset a=$1 b=$2
|
||||
typeset i=$a
|
||||
while ((i <= b)); do
|
||||
echo $i
|
||||
((i = i+1))
|
||||
done
|
||||
}
|
||||
7
test/functests/dont_test_false.sh
Normal file
7
test/functests/dont_test_false.sh
Normal file
@@ -0,0 +1,7 @@
|
||||
# a testsuite that will force failure - for testing purposes
|
||||
|
||||
run()
|
||||
{
|
||||
run_testcase false
|
||||
}
|
||||
|
||||
13
test/functests/test_null.sh
Normal file
13
test/functests/test_null.sh
Normal file
@@ -0,0 +1,13 @@
|
||||
# check that the date doesn't happen to be 0.
|
||||
|
||||
run()
|
||||
{
|
||||
run_testcase nulltest
|
||||
}
|
||||
|
||||
nulltest()
|
||||
{
|
||||
typeset tdate=${I2DATES[0]}
|
||||
|
||||
assertneq 0 "$(date +%s)" "($tdate)"
|
||||
}
|
||||
8
test/functests/test_true.sh
Normal file
8
test/functests/test_true.sh
Normal file
@@ -0,0 +1,8 @@
|
||||
# test suite that always succeds - for testing framework
|
||||
|
||||
run()
|
||||
{
|
||||
run_testcase true
|
||||
return 0
|
||||
}
|
||||
|
||||
67
test/functests/test_walkone.sh
Executable file
67
test/functests/test_walkone.sh
Executable file
@@ -0,0 +1,67 @@
|
||||
# walking-1 test.
|
||||
# sourced in from testframe.sh.
|
||||
#
|
||||
# this script defines a suite of functional tests
|
||||
# that verifies the correct operation of libfaketime
|
||||
# with the date command.
|
||||
|
||||
run()
|
||||
{
|
||||
init
|
||||
|
||||
for i in $(range 0 30); do
|
||||
run_testcase test_with_i $i
|
||||
done
|
||||
}
|
||||
|
||||
# ----- support routines
|
||||
init()
|
||||
{
|
||||
typeset testsuite="$1"
|
||||
PLATFORM=$(platform)
|
||||
if [ -z "$PLATFORM" ]; then
|
||||
echo "$testsuite: unknown platform! quitting"
|
||||
return 1
|
||||
fi
|
||||
echo "# PLATFORM=$PLATFORM"
|
||||
return 0
|
||||
}
|
||||
|
||||
|
||||
# run date cmd under faketime, print time in secs
|
||||
fakedate()
|
||||
{
|
||||
#
|
||||
# let the time format be raw seconds since Epoch
|
||||
# for both input to libfaketime, and output of the date cmd.
|
||||
#
|
||||
typeset fmt='%s'
|
||||
export FAKETIME_FMT=$fmt
|
||||
fakecmd "$1" date +$fmt
|
||||
}
|
||||
|
||||
#
|
||||
# compute x**n.
|
||||
# use only the shell, in case we need to run on machines
|
||||
# without bc, dc, perl, etc.
|
||||
#
|
||||
pow()
|
||||
{
|
||||
typeset x="$1" n="$2"
|
||||
typeset r=1
|
||||
typeset i=0
|
||||
while ((i < n)); do
|
||||
((r = r*x))
|
||||
((i++))
|
||||
done
|
||||
echo $r
|
||||
}
|
||||
|
||||
# run a fakedate test with a given time t
|
||||
test_with_i()
|
||||
{
|
||||
typeset i="$1"
|
||||
typeset t=$(pow 2 $i)
|
||||
|
||||
asserteq $(fakedate $t) $t "(secs since Epoch)"
|
||||
}
|
||||
40
test/test.sh
Executable file
40
test/test.sh
Executable file
@@ -0,0 +1,40 @@
|
||||
#!/bin/sh
|
||||
|
||||
if [ -f /etc/faketimerc ] ; then
|
||||
echo "Running the test program with your system-wide default in /etc/faketimerc"
|
||||
echo "\$ LD_PRELOAD=../src/libfaketime.so.1 ./timetest"
|
||||
LD_PRELOAD=../src/libfaketime.so.1 ./timetest
|
||||
echo
|
||||
else
|
||||
echo "Running the test program with no faked time specified"
|
||||
echo "\$ LD_PRELOAD=../src/libfaketime.so.1 ./timetest"
|
||||
LD_PRELOAD=../src/libfaketime.so.1 ./timetest
|
||||
echo
|
||||
fi
|
||||
|
||||
echo "Running the test program with absolute date 2003-01-01 10:00:05 specified"
|
||||
echo "\$ LD_PRELOAD=../src/libfaketime.so.1 FAKETIME=\"2003-01-01 10:00:05\" ./timetest"
|
||||
LD_PRELOAD=../src/libfaketime.so.1 FAKETIME="2003-01-01 10:00:05" ./timetest
|
||||
echo
|
||||
|
||||
echo "Running the test program with START date @2005-03-29 14:14:14 specified"
|
||||
echo "\$ LD_PRELOAD=../src/libfaketime.so.1 FAKETIME=\"@2005-03-29 14:14:14\" ./timetest"
|
||||
LD_PRELOAD=../src/libfaketime.so.1 FAKETIME="@2005-03-29 14:14:14" ./timetest
|
||||
echo
|
||||
|
||||
echo "Running the test program with 10 days negative offset specified"
|
||||
echo "LD_PRELOAD=../src/libfaketime.so.1 FAKETIME=\"-10d\" ./timetest"
|
||||
LD_PRELOAD=../src/libfaketime.so.1 FAKETIME="-10d" ./timetest
|
||||
echo
|
||||
|
||||
echo "Running the test program with 10 days negative offset specified, and FAKE_STAT disabled"
|
||||
echo "\$ LD_PRELOAD=../src/libfaketime.so.1 FAKETIME=\"-10d\" NO_FAKE_STAT=1 ./timetest"
|
||||
LD_PRELOAD=../src/libfaketime.so.1 FAKETIME="-10d" NO_FAKE_STAT=1 ./timetest
|
||||
echo
|
||||
|
||||
echo "Running the 'date' command with 15 days negative offset specified"
|
||||
echo "\$ LD_PRELOAD=../src/libfaketime.so.1 FAKETIME=\"-15d\" date"
|
||||
LD_PRELOAD=../src/libfaketime.so.1 FAKETIME="-15d" date
|
||||
echo
|
||||
|
||||
exit 0
|
||||
55
test/testframe.inc
Normal file
55
test/testframe.inc
Normal file
@@ -0,0 +1,55 @@
|
||||
# framework common functions for use in test suites and test cases
|
||||
|
||||
#
|
||||
# run a test and keep stats on success/failure.
|
||||
# arguments: a command, possibly a shell function.
|
||||
# return value: 0 on success, 1 on failure.
|
||||
# side effects: increments global var NSUCC on success, NFAIL on failure.
|
||||
#
|
||||
run_testcase()
|
||||
{
|
||||
if "$@"; then
|
||||
((NSUCC++))
|
||||
return 0
|
||||
else
|
||||
((NFAIL++))
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
#
|
||||
# verbosely check that the test output matches the expected value.
|
||||
# arguments: the test output, the expected value, and a description.
|
||||
# return value: 0 on if test output equals expected value; 1 otherwise.
|
||||
# side effects: prints a descriptive message.
|
||||
#
|
||||
asserteq()
|
||||
{
|
||||
typeset out="$1" expected="$2" desc="$3"
|
||||
echo -n "out=$out $desc"
|
||||
if [ "$out" = "$expected" ]; then
|
||||
echo " - ok"
|
||||
return 0
|
||||
else
|
||||
echo " expected=$expected - bad"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
#
|
||||
# verbosely check that the test output doesn't match the reference value.
|
||||
# return value: 1 on if test output equals expected value; 0 if not equal.
|
||||
# side effects: prints descriptive message.
|
||||
#
|
||||
assertneq()
|
||||
{
|
||||
typeset out="$1" ref="$2" desc="$3"
|
||||
echo -n "out=$out $desc"
|
||||
if [ "$out" = "$ref" ]; then
|
||||
echo " ref=$ref - bad"
|
||||
return 1
|
||||
else
|
||||
echo " ref=$ref - ok"
|
||||
return 0
|
||||
fi
|
||||
}
|
||||
99
test/testframe.sh
Executable file
99
test/testframe.sh
Executable file
@@ -0,0 +1,99 @@
|
||||
#! /bin/bash
|
||||
# testframe.sh DIR
|
||||
# bare-bones testing framework.
|
||||
# run the test suites in the given DIR;
|
||||
# exit with nonzero status if any of them failed.
|
||||
# see README.testframe.txt for details.
|
||||
#
|
||||
|
||||
# echo labelled error/warning message to stderr
|
||||
report()
|
||||
{
|
||||
echo $PROG: $* 1>&2
|
||||
}
|
||||
|
||||
# echo OK or BAD depending on argument (0 or not)
|
||||
status_word()
|
||||
{
|
||||
if [ "$1" -eq 0 ]; then
|
||||
echo OK
|
||||
else
|
||||
echo BAD
|
||||
fi
|
||||
}
|
||||
|
||||
# run the given testsuite, return nonzero if any testcase failed.
|
||||
run_testsuite()
|
||||
{
|
||||
typeset testsuite="$1"
|
||||
|
||||
NFAIL=0
|
||||
NSUCC=0
|
||||
|
||||
# add testsuite dir to PATH for convenience
|
||||
typeset dir=$(dirname $testsuite)
|
||||
PATH=$dir:$PATH
|
||||
. testframe.inc
|
||||
if [ -f $dir/common.inc ]; then
|
||||
. $dir/common.inc
|
||||
fi
|
||||
. $testsuite
|
||||
export TESTSUITE_NAME=$testsuite
|
||||
|
||||
echo ""
|
||||
echo "# Begin $testsuite"
|
||||
|
||||
run
|
||||
typeset runstat=$?
|
||||
|
||||
echo "# $testsuite summary: $NSUCC succeeded, $NFAIL failed"
|
||||
if [ $runstat -ne 0 ]; then
|
||||
((NFAIL++))
|
||||
report "error: $testsuite run exit_status=$runstat!"
|
||||
fi
|
||||
echo "# End $testsuite -" $(status_word $NFAIL)
|
||||
[ $NFAIL -eq 0 ]
|
||||
}
|
||||
|
||||
#
|
||||
# list all testsuite scripts in the given directories.
|
||||
# a testsuite file must be a bash script whose name is of the form test_*.sh .
|
||||
#
|
||||
list_testsuites()
|
||||
{
|
||||
for dir in "$@"; do
|
||||
ls $dir/test_*.sh 2>/dev/null
|
||||
done
|
||||
}
|
||||
|
||||
main()
|
||||
{
|
||||
TS_NFAIL=0
|
||||
TS_NSUCC=0
|
||||
|
||||
echo "# Begin Test Suites in $*"
|
||||
typeset testsuites=$(list_testsuites "$@")
|
||||
|
||||
if [ -z "$testsuites" ]; then
|
||||
report "error: no testsuites found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
for testsuite in $testsuites; do
|
||||
if run_testsuite $testsuite; then
|
||||
((TS_NSUCC++))
|
||||
else
|
||||
((TS_NFAIL++))
|
||||
fi
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "# Test Suites summary: $TS_NSUCC succeeded, $TS_NFAIL failed"
|
||||
echo "# End Test Suites -" $(status_word $TS_NFAIL)
|
||||
[ $TS_NFAIL -eq 0 ]
|
||||
}
|
||||
|
||||
# ----- start of mainline code
|
||||
PROG=${0##*/}
|
||||
|
||||
main "${@:-.}"
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/timeb.h>
|
||||
|
||||
#ifdef FAKE_STAT
|
||||
@@ -35,14 +36,16 @@ int main (int argc, char **argv) {
|
||||
time_t now;
|
||||
struct timeb tb;
|
||||
struct timeval tv;
|
||||
#ifndef __APPLE__
|
||||
struct timespec ts;
|
||||
#endif
|
||||
#ifdef FAKE_STAT
|
||||
struct stat buf;
|
||||
#endif
|
||||
|
||||
time(&now);
|
||||
printf("time() : Current date and time: %s", ctime(&now));
|
||||
printf("time(NULL) : Seconds since Epoch : %u\n", time(NULL));
|
||||
printf("time(NULL) : Seconds since Epoch : %u\n", (unsigned int)time(NULL));
|
||||
|
||||
ftime(&tb);
|
||||
printf("ftime() : Current date and time: %s", ctime(&tb.time));
|
||||
@@ -54,8 +57,10 @@ int main (int argc, char **argv) {
|
||||
gettimeofday(&tv, NULL);
|
||||
printf("gettimeofday() : Current date and time: %s", ctime(&tv.tv_sec));
|
||||
|
||||
#ifndef __APPLE__
|
||||
clock_gettime(CLOCK_REALTIME, &ts);
|
||||
printf("clock_gettime(): Current date and time: %s", ctime(&ts.tv_sec));
|
||||
#endif
|
||||
|
||||
#ifdef FAKE_STAT
|
||||
lstat(argv[0], &buf);
|
||||
Reference in New Issue
Block a user