Can I change the current date and time for a specific process? - unit-testing

Is there a way to change the date and time seen by a specific process as opposed to the entire computer (i.e. the time returned by time() in C, by DateTime.Now in C#, by datetime.now() in Python, by new Date() in JavaScript, by System.currentTimeMillis() in Java, etc.)?
For instance, is there a way to fool a program into thinking it's midnight while it's 7 AM on the rest of the computer, or to make it think it's Christmas or Leap Day while the system clock shows July 18th?
An applicable situation would be when you're writing unit tests and you want to quickly test any special behavior the program has on Christmas or on Leap Day or on the demo's expiration date, and you want to test this behavior without having to use the date changing function in the OS and interfere with programs that rely on the date being correct (much less forcing me to have superuser privileges over the computer).

Previously mentioned Typemock also has an API for C++, which also allows you to fake time, in C++:
TEST_METHOD(FakeCurrentTime)
{
SYSTEMTIME fakeTime;
fakeTime.wYear = 2000;
fakeTime.wMonth = 1;
fakeTime.wDay = 1;
FAKE_GLOBAL(GetSystemTime);
WHEN_CALLED(GetSystemTime(RET(&fakeTime))).Ignore();
SYSTEMTIME now;
GetSystemTime(&now);
Assert::IsTrue(now.wMilliseconds - fakeTime.wMilliseconds == 0);
}

I don't think you can do what you want to do in C#. There aren't any hooks that I know of to make DateTime.Now return arbitrary values out of the box. The standard way to implement unit testing that is time sensitive is to create a time provider interface. This is the approach taken by third party libraries such as Noda Time that values testing time related functions. One such implementation is below (not Noda Time compatible):
public ITimeProvider
{
DateTime CurrentTime { get; }
DateTime CurrentUtcTime { get; }
}
public DefaultTimeProvider : ITimeProvider
{
public DateTime CurrentTime { get { return DateTime.Now; } }
public DateTime CurrentUtcTime { get { return DateTime.UtcNow; } }
}
Then when you want to unit test the code you replace the DefaultTimeProvider implementation with a mock implementation. You can use your favorite mocking framework or just write something like this:
public MockTimeProvider : ITimeProvider
{
private readonly DateTime _currentTime;
private readonly DateTime _currentUtcTime;
public MockTimeProvider(DateTime currentTime, DateTime currentUtcTime)
{
_currentTime = currentTime;
_currentUtcTime = currentUtcTime;
}
public DateTime CurrentTime { get { return _currentTime; } }
public DateTime CurrentUtcTime { get { return _currentUtcTime; } }
}

Disclaimer, I work at Typemock.
You can use Typemock Isolator for this:
[TestMethod]
public void isLicenseExpiredTest()
{
Isolate.WhenCalled(() => DateTime.Now).WillReturn(new DateTime(2017, 5, 4));
bool result = Licenses.IsLicenseExpired();
Assert.IsFalse(result);
}
public static class Licenses
{
public static bool IsLicenseExpired()
{
if (DateTime.Now > new DateTime(2016, 5, 4))
{
return false;
}
else
{
return true;
}
}
}

java.time
Java 8 and later has the java.time framework built in. Supplants the old date-time classes.
Clock
Includes the Clock class. You can override this class to make your own faked current time.
A few alternate implementations are included via static methods. You can ask for a Clock that stays fixed on a single moment you specify. You can shift the current time by some specified amount. And you have the Clock report the current moment rounded to the whole second or minute and so on.

Related

Can someone please explain the proper usage of Timers and Triggers in Apache Beam?

I'm looking for some examples of usage of Triggers and Timers in Apache beam, I wanted to use Processing-time timers for listening my data from pub sub in every 5 minutes and using Processing time triggers processing the above data collected in an hour altogether in python.
Please take a look at the following resources: Stateful processing with Apache Beam and Timely (and Stateful) Processing with Apache Beam
The first blog post is more general in how to handle states for context, and the second has some examples on buffering and triggering after a certain period of time, which seems similar to what you are trying to do.
A full example was requested. Here is what I was able to come up with:
PCollection<String> records =
pipeline.apply(
"ReadPubsub",
PubsubIO.readStrings()
.fromSubscription(
"projects/{project}/subscriptions/{subscription}"));
TupleTag<Iterable<String>> every5MinTag = new TupleTag<>();
TupleTag<Iterable<String>> everyHourTag = new TupleTag<>();
PCollectionTuple timersTuple =
records
.apply("WithKeys", WithKeys.of(1)) // A KV<> is required to use state. Keying by data is more appropriate than hardcode.
.apply(
"Batch",
ParDo.of(
new DoFn<KV<Integer, String>, Iterable<String>>() {
#StateId("buffer5Min")
private final StateSpec<BagState<String>> bufferedEvents5Min =
StateSpecs.bag();
#StateId("count5Min")
private final StateSpec<ValueState<Integer>> countState5Min =
StateSpecs.value();
#TimerId("every5Min")
private final TimerSpec every5MinSpec =
TimerSpecs.timer(TimeDomain.PROCESSING_TIME);
#StateId("bufferHour")
private final StateSpec<BagState<String>> bufferedEventsHour =
StateSpecs.bag();
#StateId("countHour")
private final StateSpec<ValueState<Integer>> countStateHour =
StateSpecs.value();
#TimerId("everyHour")
private final TimerSpec everyHourSpec =
TimerSpecs.timer(TimeDomain.PROCESSING_TIME);
#ProcessElement
public void process(
#Element KV<Integer, String> record,
#StateId("count5Min") ValueState<Integer> count5MinState,
#StateId("countHour") ValueState<Integer> countHourState,
#StateId("buffer5Min") BagState<String> buffer5Min,
#StateId("bufferHour") BagState<String> bufferHour,
#TimerId("every5Min") Timer every5MinTimer,
#TimerId("everyHour") Timer everyHourTimer) {
if (Objects.firstNonNull(count5MinState.read(), 0) == 0) {
every5MinTimer
.offset(Duration.standardMinutes(1))
.align(Duration.standardMinutes(1))
.setRelative();
}
buffer5Min.add(record.getValue());
if (Objects.firstNonNull(countHourState.read(), 0) == 0) {
everyHourTimer
.offset(Duration.standardMinutes(60))
.align(Duration.standardMinutes(60))
.setRelative();
}
bufferHour.add(record.getValue());
}
#OnTimer("every5Min")
public void onTimerEvery5Min(
OnTimerContext context,
#StateId("buffer5Min") BagState<String> bufferState,
#StateId("count5Min") ValueState<Integer> countState) {
if (!bufferState.isEmpty().read()) {
context.output(every5MinTag, bufferState.read());
bufferState.clear();
countState.clear();
}
}
#OnTimer("everyHour")
public void onTimerEveryHour(
OnTimerContext context,
#StateId("bufferHour") BagState<String> bufferState,
#StateId("countHour") ValueState<Integer> countState) {
if (!bufferState.isEmpty().read()) {
context.output(everyHourTag, bufferState.read());
bufferState.clear();
countState.clear();
}
}
})
.withOutputTags(every5MinTag, TupleTagList.of(everyHourTag)));
timersTuple
.get(every5MinTag)
.setCoder(IterableCoder.of(StringUtf8Coder.of()))
.apply(<<do something every 5 min>>);
timersTuple
.get(everyHourTag)
.setCoder(IterableCoder.of(StringUtf8Coder.of()))
.apply(<< do something every hour>>);
pipeline.run().waitUntilFinish();

Acumatica - Action "Reverse and Apply Memo" Default Post Period to active financial period

Can a customization be created to set the post period to the current active financial period after pressing the "Reverse and Apply to Memo" action in "Invoices and Memos" screen?
We've noticed the newly created credit memo defaults to the post period of the invoice which could be incorrect if it's credited in the following financial period.
The solution defined below was developed within Acumatica 20.102.0015 and changes the date and post period for the created credit memo on "Reverse and Apply Memo" action to the default of a new document instead of the date from the reversed invoice.
namespace AARAMPostPeriod
{
public class AAARInvoiceEntryExtension : PXGraphExtension<ARInvoiceEntry>
{
public delegate IEnumerable ReverseDocumentAndApplyToReversalIfNeededDel(PXAdapter adapter, ReverseInvoiceArgs reverseArgs);
[PXOverride]
public virtual IEnumerable ReverseDocumentAndApplyToReversalIfNeeded(PXAdapter adapter, ReverseInvoiceArgs reverseArgs, ReverseDocumentAndApplyToReversalIfNeededDel del)
{
if(reverseArgs.ApplyToOriginalDocument) reverseArgs.DateOption = ReverseInvoiceArgs.CopyOption.SetDefault;
return del(adapter, reverseArgs);
}
}
}
Default value for reverseArgs.DateOption is typically
ReverseInvoiceArgs.CopyOption.SetOriginal
You are talking about the receivables side of things, but I did something similar on the payables side. It isn't exactly what you are asking for, but it is too big for a comment.
You may be able to get the general idea from this and apply to your scenario. The approach I took was to check the period when releasing.
protected virtual void _(Events.FieldUpdated<APInvoice.finPeriodID> e)
{
APInvoice row = (APInvoice)e.Row;
CheckPeriod(e.Cache, row);
}
#region Release override
public delegate IEnumerable ReleaseDelegate(PXAdapter adapter);
[PXOverride]
public virtual IEnumerable Release(PXAdapter adapter, ReleaseDelegate baseMethod)
{
CheckPeriod(Base.Caches[typeof(APInvoice)], Base.Document.Current);
return baseMethod(adapter);
}
#endregion
protected virtual void CheckPeriod(PXCache cache, APInvoice invoice)
{
if (invoice?.FinPeriodID == null) return;
string currentPeriod = GetCurrentPeriod(invoice.BranchID);
if (currentPeriod != invoice.FinPeriodID)
{
PXUIFieldAttribute.SetError<APInvoice.finPeriodID>(cache, invoice, "Invalid period");
}
}
public virtual string GetCurrentPeriod(int? branchID)
{
PXResultset<Branch> Results = PXSelectJoin<GL.Branch,
InnerJoin<FinPeriod, On<FinPeriod.organizationID, Equal<Branch.organizationID>>>,
Where<Branch.branchID, Equal<Required<Branch.branchID>>,
And<FinPeriod.startDate, LessEqual<Required<FinPeriod.startDate>>,
And<FinPeriod.endDate, Greater<Required<FinPeriod.endDate>>>>>> // End Date is the date AFTER the period ends
.SelectSingleBound(Base, null, branchID, Base.Accessinfo.BusinessDate, Base.Accessinfo.BusinessDate);
if (Results != null)
{
foreach (PXResult<GL.Branch, FinPeriod> result in Results)
{
FinPeriod period = result;
return period.FinPeriodID;
}
}
return null;
}
As you can see, I put an override on the Release to perform my validation which sets an error condition if the period is not current. The validation is performed by retrieving the current period of the current business date and comparing to the period on the APInvoice.
You could explore leveraging GetCurrentPeriod from the example and put into an override on FieldDefaulting if it helps with your goal.

Delaying actions using Decentraland's ECS

How do I make an action occur with a delay, but after a timeout?
The setTimeout() function doesn’t work in Decentraland scenes, so is there an alternative?
For example, I want an entity to wait 300 milliseconds after it’s clicked before I remove it from the engine.
To implement this you’ll have to create:
A custom component to keep track of time
A component group to keep track of all the entities with a delay in the scene
A system that updates the timers con all these
components on each frame.
It sounds rather complicated, but once you created one delay, implementing another delay only takes one line.
The component:
#Component("timerDelay")
export class Delay implements ITimerComponent{
elapsedTime: number;
targetTime: number;
onTargetTimeReached: (ownerEntity: IEntity) => void;
private onTimeReachedCallback?: ()=> void
/**
* #param millisecs amount of time in milliseconds
* #param onTimeReachedCallback callback for when time is reached
*/
constructor(millisecs: number, onTimeReachedCallback?: ()=> void){
this.elapsedTime = 0
this.targetTime = millisecs / 1000
this.onTimeReachedCallback = onTimeReachedCallback
this.onTargetTimeReached = (entity)=>{
if (this.onTimeReachedCallback) this.onTimeReachedCallback()
entity.removeComponent(this)
}
}
}
The component group:
export const delayedEntities = engine.getComponentGroup(Delay)
The system:
// define system
class TimerSystem implements ISystem {
update(dt: number){
for (let entity of delayedEntities.entities) {
let timerComponent = entity.getComponent(component)
timerComponent.elapsedTime += dt
if (timerComponent.elapsedTime >= timerComponent.targetTime){
timerComponent.onTargetTimeReached(entity)
}
})
}
}
// instance system
engine.addSystem(new TimerSystem())
Once all these parts are in place, you can simply do the following to delay an execution in your scene:
const myEntity = new Entity()
myEntity.addComponent(new Delay(1000, () => {
log("time ran out")
}))
engine.addEntity(myEntity)
A few years late, but the OP's selected answer is kind of deprecated because you can accomplish a delay doing:
import { Delay } from "node_modules/decentraland-ecs-utils/timer/component/delay"
const ent = new Entity
ent.addComponent(new Delay(3 * 1000, () => {
// this code will run when time is up
}))
Read the docs.
Use the utils.Delay() function in the utils library.
This function just takes the delay time in milliseconds, and the function you want to execute.
Here's the full documentation, explaining how to add the library + how to use this function, including example code:
https://www.npmjs.com/package/decentraland-ecs-utils

What are the best practices for unit testing properties with code in the setter?

I'm fairly new to unit testing and we are actually attempting to use it on a project. There is a property like this.
public TimeSpan CountDown
{
get
{
return _countDown;
}
set
{
long fraction = value.Ticks % 10000000;
value -= TimeSpan.FromTicks(fraction);
if(fraction > 5000000)
value += TimeSpan.FromSeconds(1);
if(_countDown != value)
{
_countDown = value;
NotifyChanged("CountDown");
}
}
}
My test looks like this.
[TestMethod]
public void CountDownTest_GetSet_PropChangedShouldFire()
{
ManualRafflePresenter target = new ManualRafflePresenter();
bool fired = false;
string name = null;
target.PropertyChanged += new PropertyChangedEventHandler((o, a) =>
{
fired = true;
name = a.PropertyName;
});
TimeSpan expected = new TimeSpan(0, 1, 25);
TimeSpan actual;
target.CountDown = expected;
actual = target.CountDown;
Assert.AreEqual(expected, actual);
Assert.IsTrue(fired);
Assert.AreEqual("CountDown", name);
}
The question is how do I test the code in the setter? Do I break it out into a method? If I do it would probably be private since no one else needs to use this. But they say not to test private methods. Do make a class if this is the only case? would two uses of this code make a class worthwhile? What is wrong with this code from a design standpoint. What is correct?
The way you've got is fine (call the setter and then check the get returns the expected value).
Make sure you choose a selection of test values that exercise all the paths in that setter. A single set/get test isn't sufficient coverage.

Why does this unit test fail when testing DateTime equality?

Using NUnit 2.2 on .NET 3.5, the following test fails when using DateTime.Equals. Why?
[TestFixture]
public class AttributeValueModelTest
{
public class HasDate
{
public DateTime? DateValue
{
get
{
DateTime value;
return DateTime.TryParse(ObjectValue.ToString(), out value) ? value : new DateTime?();
}
}
public object ObjectValue { get; set; }
}
[Test]
public void TwoDates()
{
DateTime actual = DateTime.Now;
var date = new HasDate {ObjectValue = actual};
Assert.IsTrue(date.DateValue.Value.Equals(actual));
}
}
The dates aren't equal. TryParse drops some ticks. Compare the Tick values.
For one test run:
Console.WriteLine(date.DateValue.Value.Ticks);
Console.WriteLine(actual.Ticks);
Yields:
633646934930000000
633646934936763185
The problem isn't really TryParse, but actually ToString().
A DateTime object starts with precision (if not accuracy) down to millionth of seconds. ToString() convertsit into a string, with precision only to a second.
TryParse is doing the best it can with what it is given.
If you add a format specifier (along the lines of "yyyy-MM-dd HH:mm:ss.ffffff"), it should work.
To specify a format that includes all the precision, you can use the String.Format() method. The example that James gives would look like this:
String.Format("{0:yyyy-MM-dd HH:mm:ss.ffffff}", ObjectValue);
I don't know what that will do when you pass it something that's not a date.
Perhaps a simpler approach is to add a special case when you've already got a date object:
public DateTime? DateValue
{
get
{
DateTime value = ObjectValue as DateTime;
if (value != null) return value;
return DateTime.TryParse(ObjectValue.ToString(), out value) ? value : new DateTime?();
}
}
public DateTime? DateValue
{
get
{
DateTime value;
bool isDate = DateTime.TryParse(ObjectValue.ToString(), out value);
return isDate ? new DateTime?(value) : new DateTime?();
}
}
I don't know if this is the same in .NET, but in Java the equals often will only compare if the instances are the same, not if the values are the same. You'd instead want to use compareTo.