Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Failing manual test for ScheduledFireTimeUtc #376

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions Quartz.build
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,7 @@
<include name="System.dll" />
<include name="System.Data.dll" />
<include name="System.Transactions.dll" />
<include name="System.Windows.Forms.dll" />
<include name="${common-logging-dll}" />
<include name="${common-logging-core-dll}" />
<include name="${nunit-dll}" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Data" />
<Reference Include="System.Windows.Forms" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\AssemblyInfo.cs">
Expand All @@ -126,6 +127,8 @@
<Compile Include="IntegrationTest.cs" />
<Compile Include="RAMJobStoreTest.cs" />
<Compile Include="RAMSchedulerTest.cs" />
<Compile Include="ScheduledFireTimeTest.cs" />
<Compile Include="ScheduledFireTimeTestJob.cs" />
<Compile Include="TestJob.cs" />
</ItemGroup>
<ItemGroup>
Expand Down
79 changes: 79 additions & 0 deletions src/Quartz.Tests.Integration/ScheduledFireTimeTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using Common.Logging;

using NUnit.Framework;

using Quartz.Impl;
using Quartz.Simpl;

namespace Quartz.Tests.Integration
{
/// <summary>
/// This is a manual test requiring the tester to manually change the system clock at the right time or put the device to sleep for the right time
/// Not inheriting from <see cref="IntegrationTest" /> so that this manual test would not be run when integration category tests are run
/// </summary>
[TestFixture, Explicit]
public class ScheduledFireTimeTest
{
private IScheduler sched;
private ScheduledFireTimeTestJob scheduledFireTimeTestJob;

[SetUp]
public void SetUp()
{
ISchedulerFactory sf = new StdSchedulerFactory();
sched = sf.GetScheduler();
scheduledFireTimeTestJob = new ScheduledFireTimeTestJob();
var jobFactory = new FixedJobFactory(scheduledFireTimeTestJob);
sched.JobFactory = jobFactory;
}

[Test]
public void TestScheduledFireTimeUtc()
{
var now = DateTimeOffset.Now;
var startTime = now.AddSeconds(120);
var trigger = TriggerBuilder.Create().WithIdentity("DailyTrigger")
.WithSchedule(
DailyTimeIntervalScheduleBuilder.Create()
.WithMisfireHandlingInstructionFireAndProceed()
.StartingDailyAt(TimeOfDay.HourMinuteAndSecondOfDay(startTime.Hour, startTime.Minute, startTime.Second))
.OnEveryDay()
.WithIntervalInHours(1)
.WithRepeatCount(9999)
.InTimeZone(TimeZoneInfo.Local)
).Build();
var jobDetail = JobBuilder.Create().WithIdentity("DailyJob", "DailyGroup").Build();
sched.ScheduleJob(jobDetail, trigger);
sched.Start();
MessageBox.Show("You have about a minute to cause a misfire now. Please either: " + Environment.NewLine
+ "A. Push the computer clock 1 hour forward into the future" + Environment.NewLine
+ "or B. Put the computer to sleep for about three minutes and then resume" + Environment.NewLine
+ "When you have carried out A or B, press OK", "Manual Test", MessageBoxButtons.OK);
if (scheduledFireTimeTestJob.ScheduledFireTimeUtc.HasValue)
{
var scheduledTimeUtc = scheduledFireTimeTestJob.ScheduledFireTimeUtc.Value;
var fireTimeUtc = scheduledFireTimeTestJob.FireTimeUtc;
var howLongAgo = fireTimeUtc - scheduledTimeUtc;
Console.WriteLine("Event Scheduled for {0} Ticked at {1} with Difference of {2}", scheduledTimeUtc, fireTimeUtc, howLongAgo);
Assert.Greater(howLongAgo, TimeSpan.FromSeconds(30), "Scheduled Fire Time Wrong - It Should Have Been Earlier Because of the Misfire");
}
else
{
Assert.Fail("Failed To Get ScheduledFireTimeUtc at {0}", DateTimeOffset.UtcNow);
}
}

[TearDown]
public void TearDown()
{
sched.Shutdown();
}

}
}
23 changes: 23 additions & 0 deletions src/Quartz.Tests.Integration/ScheduledFireTimeTestJob.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Quartz.Tests.Integration
{
public class ScheduledFireTimeTestJob:IJob
{

public void Execute(IJobExecutionContext context)
{
// Cannot Assert anything here because we are on a background thread, so any exceptions here will not cause the test to fail
ScheduledFireTimeUtc = context.ScheduledFireTimeUtc;
// Could set as context.FireTimeUtc, but using the time now just in case there is something wrong with context.FireTimeUtc as well
FireTimeUtc = DateTimeOffset.UtcNow;
}

public DateTimeOffset FireTimeUtc { get; set; }

public DateTimeOffset? ScheduledFireTimeUtc { get; set; }
}
}
1 change: 1 addition & 0 deletions src/Quartz/Quartz.2010.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,7 @@
<Compile Include="Simpl\DefaultObjectSerializer.cs" />
<Compile Include="Simpl\HostNameBasedIdGenerator.cs" />
<Compile Include="Simpl\RemotingSchedulerProxyFactory.cs" />
<Compile Include="Simpl\FixedJobFactory.cs" />
<Compile Include="Simpl\SystemPropertyInstanceIdGenerator.cs" />
<Compile Include="Simpl\HostnameInstanceIdGenerator.cs">
<SubType>Code</SubType>
Expand Down
78 changes: 78 additions & 0 deletions src/Quartz/Simpl/FixedJobFactory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;

using Quartz.Spi;

namespace Quartz.Simpl
{
/// <summary>
/// A <see cref="IJobFactory" /> that returns a fixed job regardless of the job details provided.
/// The single job that is returned may be passed in the constructor or changed through the <see cref="Job" /> property
/// </summary>
public class FixedJobFactory : IJobFactory
{
/// <summary>
/// If using this empty constructor make sure to set the <see cref="Job" /> property before asking for jobs
/// </summary>
public FixedJobFactory()
{

}

/// <summary>
///
/// </summary>
/// <param name="job">The fixed job that will be returned by the job factory</param>
public FixedJobFactory(IJob job)
{
Job = job;
}

/// <summary>
/// The single fixed job to be returned
/// </summary>
public IJob Job { get; set; }

/// <summary>
/// Called by the scheduler at the time of the trigger firing, in order to
/// produce a <see cref="IJob" /> instance on which to call Execute.
/// </summary>
/// <remarks>
/// It should be extremely rare for this method to throw an exception -
/// basically only the case where there is no way at all to instantiate
/// and prepare the Job for execution. When the exception is thrown, the
/// Scheduler will move all triggers associated with the Job into the
/// <see cref="TriggerState.Error" /> state, which will require human
/// intervention (e.g. an application restart after fixing whatever
/// configuration problem led to the issue with instantiating the Job).
/// </remarks>
/// <param name="bundle">Not used at all by this job factory</param>
/// <param name="scheduler"></param>
/// <returns>The job of the <see cref="Job" /> property</returns>
/// <throws> <see cref="SchedulerException" /> if the the <see cref="Job" /> property is null</throws>
public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
{
if (Job == null)
{
SchedulerException se = new SchedulerException("Job property null");
throw se;
}
return Job;
}

/// <summary>
/// Allows the job factory to destroy/cleanup the job if needed.
/// </summary>
public void ReturnJob(IJob job)
{
var disposable = job as IDisposable;
if (disposable != null)
{
disposable.Dispose();
}
}
}
}