From d8d1134538ad4ea4d889977632e473dfb0020e9d Mon Sep 17 00:00:00 2001 From: Atif Aziz Date: Tue, 24 Jun 2008 15:47:19 +0000 Subject: [PATCH] Initial import. --- COPYING.txt | 12 + lib/nunit.framework.dll | Bin 0 -> 77824 bytes lib/nunit.framework.xml | 5614 +++++++++++++++++ lic/OpenSymphony.txt | 1 + src/CrontabConsole/NCrontabConsole.csproj | 60 + src/CrontabConsole/Program.cs | 85 + src/CrontabConsole/Properties/AssemblyInfo.cs | 36 + src/CrontabViewer/MainForm.Designer.cs | 199 + src/CrontabViewer/MainForm.cs | 182 + src/CrontabViewer/MainForm.resx | 126 + src/CrontabViewer/NCrontabViewer.csproj | 69 + src/CrontabViewer/Program.cs | 47 + src/CrontabViewer/Properties/AssemblyInfo.cs | 35 + src/NCrontab.Tests/CrontabScheduleTests.cs | 313 + src/NCrontab.Tests/NCrontab.Tests.csproj | 61 + src/NCrontab.Tests/Properties/AssemblyInfo.cs | 34 + src/NCrontab.sln | 43 + src/NCrontab/AssemblyInfo.cs | 41 + src/NCrontab/CrontabException.cs | 52 + src/NCrontab/CrontabField.cs | 325 + src/NCrontab/CrontabFieldImpl.cs | 344 + src/NCrontab/CrontabFieldKind.cs | 41 + src/NCrontab/CrontabSchedule.cs | 272 + src/NCrontab/ICrontabField.cs | 36 + src/NCrontab/NCrontab.csproj | 147 + src/SolutionInfo.cs | 49 + 26 files changed, 8224 insertions(+) create mode 100644 COPYING.txt create mode 100644 lib/nunit.framework.dll create mode 100644 lib/nunit.framework.xml create mode 100644 lic/OpenSymphony.txt create mode 100644 src/CrontabConsole/NCrontabConsole.csproj create mode 100644 src/CrontabConsole/Program.cs create mode 100644 src/CrontabConsole/Properties/AssemblyInfo.cs create mode 100644 src/CrontabViewer/MainForm.Designer.cs create mode 100644 src/CrontabViewer/MainForm.cs create mode 100644 src/CrontabViewer/MainForm.resx create mode 100644 src/CrontabViewer/NCrontabViewer.csproj create mode 100644 src/CrontabViewer/Program.cs create mode 100644 src/CrontabViewer/Properties/AssemblyInfo.cs create mode 100644 src/NCrontab.Tests/CrontabScheduleTests.cs create mode 100644 src/NCrontab.Tests/NCrontab.Tests.csproj create mode 100644 src/NCrontab.Tests/Properties/AssemblyInfo.cs create mode 100644 src/NCrontab.sln create mode 100644 src/NCrontab/AssemblyInfo.cs create mode 100644 src/NCrontab/CrontabException.cs create mode 100644 src/NCrontab/CrontabField.cs create mode 100644 src/NCrontab/CrontabFieldImpl.cs create mode 100644 src/NCrontab/CrontabFieldKind.cs create mode 100644 src/NCrontab/CrontabSchedule.cs create mode 100644 src/NCrontab/ICrontabField.cs create mode 100644 src/NCrontab/NCrontab.csproj create mode 100644 src/SolutionInfo.cs diff --git a/COPYING.txt b/COPYING.txt new file mode 100644 index 0000000..3193fbd --- /dev/null +++ b/COPYING.txt @@ -0,0 +1,12 @@ +Copyright (c) 2008, Atif Aziz. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +- Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +- Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + +- Neither the name of the original author (Atif Aziz) nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/lib/nunit.framework.dll b/lib/nunit.framework.dll new file mode 100644 index 0000000000000000000000000000000000000000..d68d9f20c5ab7154fa4cf17b0f720c5c5b48eade GIT binary patch literal 77824 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 YFyg?710xQMI56VChyx=IyxSc3AOBQO>Hq)$ literal 0 HcmV?d00001 diff --git a/lib/nunit.framework.xml b/lib/nunit.framework.xml new file mode 100644 index 0000000..2a739ea --- /dev/null +++ b/lib/nunit.framework.xml @@ -0,0 +1,5614 @@ + + + + nunit.framework + + + + + EmptyStringConstraint tests whether a string is empty. + + + + + EmptyConstraint tests a whether a string or collection is empty, + postponing the decision about which test is applied until the + type of the actual argument is known. + + + + + The Constraint class is the base of all built-in or + user-defined constraints in NUnit. It provides the operator + overloads used to combine constraints. + + + + + Static UnsetObject used to detect derived constraints + failing to set the actual value. + + + + + If true, all string comparisons will ignore case + + + + + If true, strings in error messages will be clipped + + + + + If true, arrays will be treated as collections, allowing + those of different dimensions to be compared + + + + + If non-zero, equality comparisons within the specified + tolerance will succeed. + + + + + IComparer object used in comparisons for some constraints. + + + + + The actual value being tested against a constraint + + + + + Flag the constraint to use a tolerance when determining equality. + Currently only used for doubles and floats. + + Tolerance to be used + Self. + + + + Flag the constraint to use the supplied IComparer object. + + The IComparer object to use. + Self. + + + + Write the failure message to the MessageWriter provided + as an argument. The default implementation simply passes + the constraint and the actual value to the writer, which + then displays the constraint description and the value. + + Constraints that need to provide additional details, + such as where the error occured can override this. + + The MessageWriter on which to display the message + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Write the actual value for a failing constraint test to a + MessageWriter. The default implementation simply writes + the raw value of actual, leaving it to the writer to + perform any formatting. + + The writer on which the actual value is displayed + + + + This operator creates a constraint that is satisfied only if both + argument constraints are satisfied. + + + + + This operator creates a constraint that is satisfied if either + of the argument constraints is satisfied. + + + + + This operator creates a constraint that is satisfied if the + argument constraint is not satisfied. + + + + + Flag the constraint to ignore case and return self. + + + + + Flag the constraint to suppress string clipping + and return self. + + + + + Flag the constraint to compare arrays as collections + and return self. + + + + + Class used to detect any derived constraints + that fail to set the actual value in their + Matches override. + + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + SubstringConstraint can test whether a string contains + the expected substring. + + + + + Initializes a new instance of the class. + + The expected. + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + StartsWithConstraint can test whether a string starts + with an expected substring. + + + + + Initializes a new instance of the class. + + The expected string + + + + Test whether the constraint is matched by the actual value. + This is a template method, which calls the IsMatch method + of the derived class. + + + + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + EndsWithConstraint can test whether a string ends + with an expected substring. + + + + + Initializes a new instance of the class. + + The expected string + + + + Test whether the constraint is matched by the actual value. + This is a template method, which calls the IsMatch method + of the derived class. + + + + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + RegexConstraint can test whether a string matches + the pattern provided. + + + + + Initializes a new instance of the class. + + The pattern. + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + ConstraintBuilder is used to resolve the Not and All properties, + which serve as prefix operators for constraints. With the addition + of an operand stack, And and Or could be supported, but we have + left them out in favor of a simpler, more type-safe implementation. + Use the & and | operator overloads to combine constraints. + + + + + Implicitly convert ConstraintBuilder to an actual Constraint + at the point where the syntax demands it. + + + + + + + Resolves the chain of constraints using an + EqualConstraint as base. + + + + + Resolves the chain of constraints using a + SameAsConstraint as base. + + + + + Resolves the chain of constraints using a + LessThanConstraint as base. + + + + + Resolves the chain of constraints using a + GreaterThanConstraint as base. + + + + + Resolves the chain of constraints using a + LessThanOrEqualConstraint as base. + + + + + Resolves the chain of constraints using a + LessThanOrEqualConstraint as base. + + + + + Resolves the chain of constraints using a + GreaterThanOrEqualConstraint as base. + + + + + Resolves the chain of constraints using a + GreaterThanOrEqualConstraint as base. + + + + + Resolves the chain of constraints using an + ExactTypeConstraint as base. + + + + + Resolves the chain of constraints using an + InstanceOfTypeConstraint as base. + + + + + Resolves the chain of constraints using an + AssignableFromConstraint as base. + + + + + Resolves the chain of constraints using a + ContainsConstraint as base. This constraint + will, in turn, make use of the appropriate + second-level constraint, depending on the + type of the actual argument. + + + + + Resolves the chain of constraints using a + CollectionContainsConstraint as base. + + The expected object + + + + Resolves the chain of constraints using a + StartsWithConstraint as base. + + + + + Resolves the chain of constraints using a + StringEndingConstraint as base. + + + + + Resolves the chain of constraints using a + StringMatchingConstraint as base. + + + + + Resolves the chain of constraints using a + CollectionEquivalentConstraint as base. + + + + + Resolves the chain of constraints using a + CollectionContainingConstraint as base. + + + + + Resolves the chain of constraints using a + CollectionSubsetConstraint as base. + + + + + Resolves the chain of constraints using a + PropertyConstraint as base + + + + + Resolves the chain of constraints using a + PropertyCOnstraint on Length as base + + + + + + + Resolves the chain of constraints using a + PropertyCOnstraint on Length as base + + + + + + + Modifies the ConstraintBuilder by pushing a Prop operator on the + ops stack and the name of the property on the opnds stack. + + + + + + + Resolve a constraint that has been recognized by applying + any pending operators and returning the resulting Constraint. + + A constraint that incorporates all pending operators + + + + Resolves the chain of constraints using + EqualConstraint(null) as base. + + + + + Resolves the chain of constraints using + EqualConstraint(true) as base. + + + + + Resolves the chain of constraints using + EqualConstraint(false) as base. + + + + + Resolves the chain of constraints using + Is.NaN as base. + + + + + Resolves the chain of constraints using + Is.Empty as base. + + + + + Resolves the chain of constraints using + Is.Unique as base. + + + + + Modifies the ConstraintBuilder by pushing a Not operator on the stack. + + + + + Modifies the ConstraintBuilder by pushing a Not operator on the stack. + + + + + Modifies the ConstraintBuilder by pushing an All operator on the stack. + + + + + Modifies the ConstraintBuilder by pushing a Some operator on the stack. + + + + + Modifies the constraint builder by pushing All and Not operators on the stack + + + + + CollectionConstraint is the abstract base class for + constraints that operate on collections. + + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Protected method to be implemented by derived classes + + + + + + + CollectionTally counts (tallies) the number of + occurences of each object in one or more enuerations. + + + + + Construct a CollectionTally object from a collection + + + + + + Remove the counts for a collection from the tally, + so long as their are sufficient items to remove. + The tallies are not permitted to become negative. + + The collection to remove + True if there were enough items to remove, otherwise false + + + + Test whether all the counts are equal to a given value + + The value to be looked for + True if all counts are equal to the value, otherwise false + + + + Get the count of the number of times an object is present in the tally + + + + + EmptyCollectionConstraint tests whether a colletion is empty. + + + + + Check that the collection is empty + + + + + + + Write the constraint description to a MessageWriter + + + + + + UniqueItemsConstraint tests whether all the items in a + collection are unique. + + + + + Check that all items are unique. + + + + + + + Write a description of this constraint to a MessageWriter + + + + + + CollectionContainsConstraint is used to test whether a collection + contains an expected object as a member. + + + + + Construct a CollectionContainsConstraint + + + + + + Test whether the expected item is contained in the collection + + + + + + + Write a descripton of the constraint to a MessageWriter + + + + + + CollectionEquivalentCOnstraint is used to determine whether two + collections are equivalent. + + + + + Construct a CollectionEquivalentConstraint + + + + + + Test whether two collections are equivalent + + + + + + + Write a description of this constraint to a MessageWriter + + + + + + CollectionSubsetConstraint is used to determine whether + one collection is a subset of another + + + + + Construct a CollectionSubsetConstraint + + The collection that the actual value is expected to be a subset of + + + + Test whether the actual collection is a subset of + the expected collection provided. + + + + + + + Write a description of this constraint to a MessageWriter + + + + + + EqualConstraint is able to compare an actual value with the + expected value provided in its constructor. + + + + + Initializes a new instance of the class. + + The expected value. + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Write a failure message. Overridden to provide custom + failure messages for EqualConstraint. + + The MessageWriter to write to + + + + Write description of this constraint + + The MessageWriter to write to + + + + Helper method to compare two arrays + + + + + Display the failure information for two collections that did not match. + + The MessageWriter on which to display + The expected collection. + The actual collection + The depth of this failure in a set of nested collections + + + + Displays a single line showing the types and sizes of the expected + and actual collections or arrays. If both are identical, the value is + only shown once. + + The MessageWriter on which to display + The expected collection or array + The actual collection or array + The indentation level for the message line + + + + Displays a single line showing the point in the expected and actual + arrays at which the comparison failed. If the arrays have different + structures or dimensions, both values are shown. + + The MessageWriter on which to display + The expected array + The actual array + Index of the failure point in the underlying collections + The indentation level for the message line + + + + Abstract base class used for prefixes + + + + + The base constraint + + + + + Construct given a base constraint + + + + + + Set all modifiers applied to the prefix into + the base constraint before matching + + + + + NotConstraint negates the effect of some other constraint + + + + + Initializes a new instance of the class. + + The base constraint to be negated. + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for if the base constraint fails, false if it succeeds + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Write the actual value for a failing constraint test to a MessageWriter. + + The writer on which the actual value is displayed + + + + AllItemsConstraint applies another constraint to each + item in a collection, succeeding if they all succeed. + + + + + Construct an AllItemsConstraint on top of an existing constraint + + + + + + Apply the item constraint to each item in the collection, + failing if any item fails. + + + + + + + Write a description of this constraint to a MessageWriter + + + + + + SomeItemsConstraint applies another constraint to each + item in a collection, succeeding if any of them succeeds. + + + + + Construct a SomeItemsConstraint on top of an existing constraint + + + + + + Apply the item constraint to each item in the collection, + failing if any item fails. + + + + + + + Write a description of this constraint to a MessageWriter + + + + + + SomeItemsConstraint applies another constraint to each + item in a collection, succeeding if any of them succeeds. + + + + + Construct a SomeItemsConstraint on top of an existing constraint + + + + + + Apply the item constraint to each item in the collection, + failing if any item fails. + + + + + + + Write a description of this constraint to a MessageWriter + + + + + + SameAsConstraint tests whether an object is identical to + the object passed to its constructor + + + + + Initializes a new instance of the class. + + The expected object. + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + TypeConstraint is the abstract base for constraints + that take a Type as their expected value. + + + + + The expected Type used by the constraint + + + + + Construct a TypeConstraint for a given Type + + + + + + Write the actual value for a failing constraint test to a + MessageWriter. TypeCOnstraints override this method to write + the name of the type. + + The writer on which the actual value is displayed + + + + ExactTypeConstraint is used to test that an object + is of the exact type provided in the constructor + + + + + Construct an ExactTypeConstraint for a given Type + + + + + + Test that an object is of the exact type specified + + + + + + + Write the description of this constraint to a MessageWriter + + + + + + InstanceOfTypeConstraint is used to test that an object + is of the same type provided or derived from it. + + + + + Construct an InstanceOfTypeConstraint for the type provided + + + + + + Test whether an object is of the specified type or a derived type + + + + + + + Write a description of this constraint to a MessageWriter + + + + + + AssignableFromConstraint is used to test that an object + can be assigned from a given Type. + + + + + Construct an AssignableFromConstraint for the type provided + + + + + + Test whether an object can be assigned from the specified type + + + + + + + Write a description of this constraint to a MessageWriter + + + + + + Abstract base class for constraints that compare values to + determine if one is greater than, equal to or less than + the other. + + + + + The value against which a comparison is to be made + + + + + If true, less than returns success + + + + + if true, equal returns success + + + + + if true, greater than returns success + + + + + The predicate used as a part of the description + + + + + Initializes a new instance of the class. + + The value against which to make a comparison. + if set to true less succeeds. + if set to true equal succeeds. + if set to true greater succeeds. + String used in describing the constraint. + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Tests whether a value is greater than the value supplied to its constructor + + + + + Initializes a new instance of the class. + + The expected value. + + + + Tests whether a value is greater than or equal to the value supplied to its constructor + + + + + Initializes a new instance of the class. + + The expected value. + + + + Tests whether a value is less than the value supplied to its constructor + + + + + Initializes a new instance of the class. + + The expected value. + + + + Tests whether a value is less than or equal to the value supplied to its constructor + + + + + Initializes a new instance of the class. + + The expected value. + + + + The Numerics class contains common operations on numeric values. + + + + + Checks the type of the object, returning true if + the object is a numeric type. + + The object to check + true if the object is a numeric type + + + + Checks the type of the object, returning true if + the object is a floating point numeric type. + + The object to check + true if the object is a floating point numeric type + + + + Checks the type of the object, returning true if + the object is a fixed point numeric type. + + The object to check + true if the object is a fixed point numeric type + + + + Test two numeric values for equality, performing the usual numeric + conversions and using a provided or default tolerance. If the value + referred to by tolerance is null, this method may set it to a default. + + The expected value + The actual value + A reference to the numeric tolerance in effect + True if the values are equal + + + + Compare two numeric values, performing the usual numeric conversions. + + The expected value + The actual value + + + + + ContainsConstraint tests a whether a string contains a substring + or a collection contains an object. It postpones the decision of + which test to use until the type of the actual argument is known. + This allows testing whether a string is contained in a collection + or as a substring of another string using the same syntax. + + + + + Initializes a new instance of the class. + + The expected. + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Summary description for PropertyConstraint. + + + + + Initializes a new instance of the class. + + The name. + The constraint to apply to the property. + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Write the actual value for a failing constraint test to a + MessageWriter. The default implementation simply writes + the raw value of actual, leaving it to the writer to + perform any formatting. + + The writer on which the actual value is displayed + + + + BinaryOperation is the abstract base of all constraints + that combine two other constraints in some fashion. + + + + + The first constraint being combined + + + + + The second constraint being combined + + + + + Construct a BinaryOperation from two other constraints + + The first constraint + The second constraint + + + + AndConstraint succeeds only if both members succeed. + + + + + Create an AndConstraint from two other constraints + + The first constraint + The second constraint + + + + Apply both member constraints to an actual value, succeeding + succeeding only if both of them succeed. + + The actual value + True if the constraints both succeeded + + + + Write a description for this contraint to a MessageWriter + + The MessageWriter to receive the description + + + + OrConstraint succeeds if either member succeeds + + + + + Create an OrConstraint from two other constraints + + The first constraint + The second constraint + + + + Apply the member constraints to an actual value, succeeding + succeeding as soon as one of them succeeds. + + The actual value + True if either constraint succeeded + + + + Write a description for this contraint to a MessageWriter + + The MessageWriter to receive the description + + + + The Is class is a helper class with properties and methods + that supply a number of constraints used in Asserts. + + + + + Is.Null returns a static constraint that tests for null + + + + + Is.True returns a static constraint that tests whether a value is true + + + + + Is.False returns a static constraint that tests whether a value is false + + + + + Is.NaN returns a static constraint that tests whether a value is an NaN + + + + + Is.Empty returns a static constraint that tests whether a string or collection is empty + + + + + Is.Unique returns a static constraint that tests whether a collection contains all unque items. + + + + + Is.EqualTo returns a constraint that tests whether the + actual value equals the supplied argument + + + + + + + Is.SameAs returns a constraint that tests whether the + actual value is the same object as the supplied argument. + + + + + + + Is.GreaterThan returns a constraint that tests whether the + actual value is greater than the suppled argument + + + + + Is.GreaterThanOrEqualTo returns a constraint that tests whether the + actual value is greater than or equal to the suppled argument + + + + + Is.AtLeast is a synonym for Is.GreaterThanOrEqualTo + + + + + Is.LessThan returns a constraint that tests whether the + actual value is less than the suppled argument + + + + + Is.LessThanOrEqualTo returns a constraint that tests whether the + actual value is less than or equal to the suppled argument + + + + + Is.AtMost is a synonym for Is.LessThanOrEqualTo + + + + + Is.TypeOf returns a constraint that tests whether the actual + value is of the exact type supplied as an argument. + + + + + Is.InstanceOfType returns a constraint that tests whether + the actual value is of the type supplied as an argument + or a derived type. + + + + + Is.AssignableFrom returns a constraint that tests whether + the actual value is assignable from the type supplied as + an argument. + + + + + + + Is.EquivalentTo returns a constraint that tests whether + the actual value is a collection containing the same + elements as the collection supplied as an arument + + + + + Is.SubsetOf returns a constraint that tests whether + the actual value is a subset of the collection + supplied as an arument + + + + + Is.Not returns a ConstraintBuilder that negates + the constraint that follows it. + + + + + Is.All returns a ConstraintBuilder, which will apply + the following constraint to all members of a collection, + succeeding if all of them succeed. This property is + a synonym for Has.AllItems. + + + + + The Iz class is a synonym for Is intended for use in VB, + which regards Is as a keyword. + + + + + The Text class is a helper class with properties and methods + that supply a number of constraints used with strings. + + + + + Contains returns a constraint that succeeds if the actual + value contains the substring supplied as an argument. + + + + + DoesNotContain returns a constraint that fails if the actual + value contains the substring supplied as an argument. + + + + + StartsWith returns a constraint that succeeds if the actual + value starts with the substring supplied as an argument. + + + + + DoesNotStartWith returns a constraint that fails if the actual + value starts with the substring supplied as an argument. + + + + + EndsWith returns a constraint that succeeds if the actual + value ends with the substring supplied as an argument. + + + + + DoesNotEndWith returns a constraint that fails if the actual + value ends with the substring supplied as an argument. + + + + + Matches returns a constraint that succeeds if the actual + value matches the pattern supplied as an argument. + + + + + + + DoesNotMatch returns a constraint that failss if the actual + value matches the pattern supplied as an argument. + + + + + + + Text.All returns a ConstraintBuilder, which will apply + the following constraint to all members of a collection, + succeeding if all of them succeed. + + + + + The List class is a helper class with properties and methods + that supply a number of constraints used with lists and collections. + + + + + List.Map returns a ListMapper, which can be used to map + the original collection to another collection. + + + + + + + ListMapper is used to transform a collection used as an actual argument + producing another collection to be used in the assertion. + + + + + Construct a ListMapper based on a collection + + The collection to be transformed + + + + Produces a collection containing all the values of a property + + The collection of property values + + + + + Summary description for HasNoPrefixB. + + + + + Returns a new ConstraintBuilder, which will apply the + following constraint to a named property of the object + being tested. + + The name of the property + + + + Returns a new PropertyConstraint checking for the + existence of a particular property value. + + The name of the property to look for + The expected value of the property + + + + Returns a new PropertyConstraint for the Length property + + + + + + + Returns a new PropertyConstraint or the Count property + + + + + + + Returns a new CollectionContainsConstraint checking for the + presence of a particular object in the collection. + + The expected object + + + + Has.No returns a ConstraintBuilder that negates + the constraint that follows it. + + + + + Has.AllItems returns a ConstraintBuilder, which will apply + the following constraint to all members of a collection, + succeeding if all of them succeed. + + + + + Has.Some returns a ConstraintBuilder, which will apply + the following constraint to all members of a collection, + succeeding if any of them succeed. It is a synonym + for Has.Item. + + + + + Has.None returns a ConstraintBuilder, which will apply + the following constraint to all members of a collection, + succeeding only if none of them succeed. + + + + + Nested class that allows us to restrict the number + of key words that may appear after Has.No. + + + + + Return a ConstraintBuilder conditioned to apply + the following constraint to a property. + + The property name + A ConstraintBuilder + + + + Return a Constraint that succeeds if the expected object is + not contained in a collection. + + The expected object + A Constraint + + + + The Assert class contains a collection of static methods that + implement the most common assertions used in NUnit. + + + + + We don't actually want any instances of this object, but some people + like to inherit from it to add other static methods. Hence, the + protected constructor disallows any instances of this object. + + + + + The Equals method throws an AssertionException. This is done + to make sure there is no mistake by calling this function. + + + + + + + override the default ReferenceEquals to throw an AssertionException. This + implementation makes sure there is no mistake in calling this function + as part of Assert. + + + + + + + Asserts that a condition is true. If the condition is false the method throws + an . + + The evaluated condition + The message to display if the condition is false + Arguments to be used in formatting the message + + + + Asserts that a condition is true. If the condition is false the method throws + an . + + The evaluated condition + The message to display if the condition is false + + + + Asserts that a condition is true. If the condition is false the method throws + an . + + The evaluated condition + + + + Asserts that a condition is false. If the condition is true the method throws + an . + + The evaluated condition + The message to display if the condition is true + Arguments to be used in formatting the message + + + + Asserts that a condition is false. If the condition is true the method throws + an . + + The evaluated condition + The message to display if the condition is true + + + + Asserts that a condition is false. If the condition is true the method throws + an . + + The evaluated condition + + + + Verifies that the object that is passed in is not equal to null + If the object is null then an + is thrown. + + The object that is to be tested + The message to be displayed when the object is null + Arguments to be used in formatting the message + + + + Verifies that the object that is passed in is not equal to null + If the object is null then an + is thrown. + + The object that is to be tested + The message to be displayed when the object is null + + + + Verifies that the object that is passed in is not equal to null + If the object is null then an + is thrown. + + The object that is to be tested + + + + Verifies that the object that is passed in is equal to null + If the object is not null then an + is thrown. + + The object that is to be tested + The message to be displayed when the object is not null + Arguments to be used in formatting the message + + + + Verifies that the object that is passed in is equal to null + If the object is not null then an + is thrown. + + The object that is to be tested + The message to be displayed when the object is not null + + + + Verifies that the object that is passed in is equal to null + If the object is not null null then an + is thrown. + + The object that is to be tested + + + + Verifies that the double is passed is an NaN value. + If the object is not NaN then an + is thrown. + + The value that is to be tested + The message to be displayed when the object is not null + Arguments to be used in formatting the message + + + + Verifies that the double is passed is an NaN value. + If the object is not NaN then an + is thrown. + + The object that is to be tested + The message to be displayed when the object is not null + + + + Verifies that the double is passed is an NaN value. + If the object is not NaN then an + is thrown. + + The object that is to be tested + + + + Assert that a string is empty - that is equal to string.Empty + + The string to be tested + The message to be displayed on failure + Arguments to be used in formatting the message + + + + Assert that a string is empty - that is equal to string.Emtpy + + The string to be tested + The message to be displayed on failure + + + + Assert that a string is empty - that is equal to string.Emtpy + + The string to be tested + + + + Assert that an array, list or other collection is empty + + An array, list or other collection implementing ICollection + The message to be displayed on failure + Arguments to be used in formatting the message + + + + Assert that an array, list or other collection is empty + + An array, list or other collection implementing ICollection + The message to be displayed on failure + + + + Assert that an array,list or other collection is empty + + An array, list or other collection implementing ICollection + + + + Assert that a string is not empty - that is not equal to string.Empty + + The string to be tested + The message to be displayed on failure + Arguments to be used in formatting the message + + + + Assert that a string is empty - that is equal to string.Emtpy + + The string to be tested + The message to be displayed on failure + + + + Assert that a string is empty - that is equal to string.Emtpy + + The string to be tested + + + + Assert that an array, list or other collection is empty + + An array, list or other collection implementing ICollection + The message to be displayed on failure + Arguments to be used in formatting the message + + + + Assert that an array, list or other collection is empty + + An array, list or other collection implementing ICollection + The message to be displayed on failure + + + + Assert that an array,list or other collection is empty + + An array, list or other collection implementing ICollection + + + + Asserts that an object may be assigned a value of a given Type. + + The expected Type. + The object under examination + + + + Asserts that an object may be assigned a value of a given Type. + + The expected Type. + The object under examination + The messge to display in case of failure + + + + Asserts that an object may be assigned a value of a given Type. + + The expected Type. + The object under examination + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that an object may not be assigned a value of a given Type. + + The expected Type. + The object under examination + + + + Asserts that an object may not be assigned a value of a given Type. + + The expected Type. + The object under examination + The messge to display in case of failure + + + + Asserts that an object may not be assigned a value of a given Type. + + The expected Type. + The object under examination + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that an object is an instance of a given type. + + The expected Type + The object being examined + + + + Asserts that an object is an instance of a given type. + + The expected Type + The object being examined + A message to display in case of failure + + + + Asserts that an object is an instance of a given type. + + The expected Type + The object being examined + A message to display in case of failure + An array of objects to be used in formatting the message + + + + Asserts that an object is not an instance of a given type. + + The expected Type + The object being examined + + + + Asserts that an object is not an instance of a given type. + + The expected Type + The object being examined + A message to display in case of failure + + + + Asserts that an object is not an instance of a given type. + + The expected Type + The object being examined + A message to display in case of failure + An array of objects to be used in formatting the message + + + + Verifies that two ints are equal. If they are not, then an + is thrown. + + The expected value + The actual value + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Verifies that two ints are equal. If they are not, then an + is thrown. + + The expected value + The actual value + The message that will be displayed on failure + + + + Verifies that two ints are equal. If they are not, then an + is thrown. + + The expected value + The actual value + + + + Verifies that two longs are equal. If they are not, then an + is thrown. + + The expected value + The actual value + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Verifies that two longs are equal. If they are not, then an + is thrown. + + The expected value + The actual value + The message that will be displayed on failure + + + + Verifies that two longs are equal. If they are not, then an + is thrown. + + The expected value + The actual value + + + + Verifies that two uints are equal. If they are not, then an + is thrown. + + The expected value + The actual value + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Verifies that two uints are equal. If they are not, then an + is thrown. + + The expected value + The actual value + The message that will be displayed on failure + + + + Verifies that two uints are equal. If they are not, then an + is thrown. + + The expected value + The actual value + + + + Verifies that two ulongs are equal. If they are not, then an + is thrown. + + The expected value + The actual value + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Verifies that two ulongs are equal. If they are not, then an + is thrown. + + The expected value + The actual value + The message that will be displayed on failure + + + + Verifies that two ulongs are equal. If they are not, then an + is thrown. + + The expected value + The actual value + + + + Verifies that two decimals are equal. If they are not, then an + is thrown. + + The expected value + The actual value + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Verifies that two decimal are equal. If they are not, then an + is thrown. + + The expected value + The actual value + The message that will be displayed on failure + + + + Verifies that two decimals are equal. If they are not, then an + is thrown. + + The expected value + The actual value + + + + Verifies that two doubles are equal considering a delta. If the + expected value is infinity then the delta value is ignored. If + they are not equals then an is + thrown. + + The expected value + The actual value + The maximum acceptable difference between the + the expected and the actual + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Verifies that two doubles are equal considering a delta. If the + expected value is infinity then the delta value is ignored. If + they are not equals then an is + thrown. + + The expected value + The actual value + The maximum acceptable difference between the + the expected and the actual + The message that will be displayed on failure + + + + Verifies that two doubles are equal considering a delta. If the + expected value is infinity then the delta value is ignored. If + they are not equals then an is + thrown. + + The expected value + The actual value + The maximum acceptable difference between the + the expected and the actual + + + + Verifies that two floats are equal considering a delta. If the + expected value is infinity then the delta value is ignored. If + they are not equals then an is + thrown. + + The expected value + The actual value + The maximum acceptable difference between the + the expected and the actual + The message displayed upon failure + Arguments to be used in formatting the message + + + + Verifies that two floats are equal considering a delta. If the + expected value is infinity then the delta value is ignored. If + they are not equals then an is + thrown. + + The expected value + The actual value + The maximum acceptable difference between the + the expected and the actual + The message displayed upon failure + + + + Verifies that two floats are equal considering a delta. If the + expected value is infinity then the delta value is ignored. If + they are not equals then an is + thrown. + + The expected value + The actual value + The maximum acceptable difference between the + the expected and the actual + + + + Verifies that two objects are equal. Two objects are considered + equal if both are null, or if both have the same value. All + non-numeric types are compared by using the Equals method. + Arrays are compared by comparing each element using the same rules. + If they are not equal an is thrown. + + The value that is expected + The actual value + The message to display if objects are not equal + Arguments to be used in formatting the message + + + + Verifies that two objects are equal. Two objects are considered + equal if both are null, or if both have the same value. All + non-numeric types are compared by using the Equals method. + If they are not equal an is thrown. + + The value that is expected + The actual value + The message to display if objects are not equal + + + + Verifies that two objects are equal. Two objects are considered + equal if both are null, or if both have the same value. All + non-numeric types are compared by using the Equals method. + If they are not equal an is thrown. + + The value that is expected + The actual value + + + + Asserts that two objects are not equal. If they are equal + an is thrown. + + The expected object + The actual object + The message to be displayed when the two objects are the same object. + Arguments to be used in formatting the message + + + + Asserts that two objects are not equal. If they are equal + an is thrown. + + The expected object + The actual object + The message to be displayed when the objects are the same + + + + Asserts that two objects are not equal. If they are equal + an is thrown. + + The expected object + The actual object + + + + Asserts that two ints are not equal. If they are equal + an is thrown. + + The expected object + The actual object + The message to be displayed when the two objects are the same object. + Arguments to be used in formatting the message + + + + Asserts that two ints are not equal. If they are equal + an is thrown. + + The expected object + The actual object + The message to be displayed when the objects are the same + + + + Asserts that two ints are not equal. If they are equal + an is thrown. + + The expected object + The actual object + + + + Asserts that two longss are not equal. If they are equal + an is thrown. + + The expected object + The actual object + The message to be displayed when the two objects are the same object. + Arguments to be used in formatting the message + + + + Asserts that two longs are not equal. If they are equal + an is thrown. + + The expected object + The actual object + The message to be displayed when the objects are the same + + + + Asserts that two longs are not equal. If they are equal + an is thrown. + + The expected object + The actual object + + + + Asserts that two uints are not equal. If they are equal + an is thrown. + + The expected object + The actual object + The message to be displayed when the two objects are the same object. + Arguments to be used in formatting the message + + + + Asserts that two uints are not equal. If they are equal + an is thrown. + + The expected object + The actual object + The message to be displayed when the objects are the same + + + + Asserts that two uints are not equal. If they are equal + an is thrown. + + The expected object + The actual object + + + + Asserts that two ulongs are not equal. If they are equal + an is thrown. + + The expected object + The actual object + The message to be displayed when the two objects are the same object. + Arguments to be used in formatting the message + + + + Asserts that two ulongs are not equal. If they are equal + an is thrown. + + The expected object + The actual object + The message to be displayed when the objects are the same + + + + Asserts that two ulong are not equal. If they are equal + an is thrown. + + The expected object + The actual object + + + + Asserts that two decimals are not equal. If they are equal + an is thrown. + + The expected object + The actual object + The message to be displayed when the two objects are the same object. + Arguments to be used in formatting the message + + + + Asserts that two decimals are not equal. If they are equal + an is thrown. + + The expected object + The actual object + The message to be displayed when the objects are the same + + + + Asserts that two decimals are not equal. If they are equal + an is thrown. + + The expected object + The actual object + + + + Asserts that two floats are not equal. If they are equal + an is thrown. + + The expected object + The actual object + The message to be displayed when the two objects are the same object. + Arguments to be used in formatting the message + + + + Asserts that two floats are not equal. If they are equal + an is thrown. + + The expected object + The actual object + The message to be displayed when the objects are the same + + + + Asserts that two floats are not equal. If they are equal + an is thrown. + + The expected object + The actual object + + + + Asserts that two doubles are not equal. If they are equal + an is thrown. + + The expected object + The actual object + The message to be displayed when the two objects are the same object. + Arguments to be used in formatting the message + + + + Asserts that two doubles are not equal. If they are equal + an is thrown. + + The expected object + The actual object + The message to be displayed when the objects are the same + + + + Asserts that two doubles are not equal. If they are equal + an is thrown. + + The expected object + The actual object + + + + Asserts that two objects refer to the same object. If they + are not the same an is thrown. + + The expected object + The actual object + The message to be displayed when the two objects are not the same object. + Arguments to be used in formatting the message + + + + Asserts that two objects refer to the same object. If they + are not the same an is thrown. + + The expected object + The actual object + The message to be displayed when the object is null + + + + Asserts that two objects refer to the same object. If they + are not the same an is thrown. + + The expected object + The actual object + + + + Asserts that two objects do not refer to the same object. If they + are the same an is thrown. + + The expected object + The actual object + The message to be displayed when the two objects are the same object. + Arguments to be used in formatting the message + + + + Asserts that two objects do not refer to the same object. If they + are the same an is thrown. + + The expected object + The actual object + The message to be displayed when the objects are the same + + + + Asserts that two objects do not refer to the same object. If they + are the same an is thrown. + + The expected object + The actual object + + + + Verifies that the first value is greater than the second + value. If they are not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Verifies that the first value is greater than the second + value. If they are not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message that will be displayed on failure + + + + Verifies that the first value is greater than the second + value. If they are not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than the second + value. If they are not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Verifies that the first value is greater than the second + value. If they are not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message that will be displayed on failure + + + + Verifies that the first value is greater than the second + value. If they are not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than the second + value. If they are not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Verifies that the first value is greater than the second + value. If they are not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message that will be displayed on failure + + + + Verifies that the first value is greater than the second + value. If they are not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than the second + value. If they are not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Verifies that the first value is greater than the second + value. If they are not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message that will be displayed on failure + + + + Verifies that the first value is greater than the second + value. If they are not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than the second + value. If they are not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Verifies that the first value is greater than the second + value. If they are not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message that will be displayed on failure + + + + Verifies that the first value is greater than the second + value. If they are not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than the second + value. If they are not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Verifies that the first value is greater than the second + value. If they are not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message that will be displayed on failure + + + + Verifies that the first value is greater than the second + value. If they are not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than the second + value. If they are not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Verifies that the first value is greater than the second + value. If they are not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message that will be displayed on failure + + + + Verifies that the first value is greater than the second + value. If they are not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than the second + value. If they are not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Verifies that the first value is greater than the second + value. If they are not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message that will be displayed on failure + + + + Verifies that the first value is greater than the second + value. If they are not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message that will be displayed on failure + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message that will be displayed on failure + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message that will be displayed on failure + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message that will be displayed on failure + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message that will be displayed on failure + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message that will be displayed on failure + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message that will be displayed on failure + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message that will be displayed on failure + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Asserts that an object is contained in a list. + + The expected object + The list to be examined + The message to display in case of failure + Arguments used in formatting the message + + + + Asserts that an object is contained in a list. + + The expected object + The list to be examined + The message to display in case of failure + + + + Asserts that an object is contained in a list. + + The expected object + The list to be examined + + + + Throws an with the message and arguments + that are passed in. This is used by the other Assert functions. + + The message to initialize the with. + Arguments to be used in formatting the message + + + + Throws an with the message that is + passed in. This is used by the other Assert functions. + + The message to initialize the with. + + + + Throws an . + This is used by the other Assert functions. + + + + + Throws an with the message and arguments + that are passed in. This causes the test to be reported as ignored. + + The message to initialize the with. + Arguments to be used in formatting the message + + + + Throws an with the message that is + passed in. This causes the test to be reported as ignored. + + The message to initialize the with. + + + + Throws an . + This causes the test to be reported as ignored. + + + + + NOTE: The use of asserters for extending NUnit has + now been replaced by the use of constraints. This + method is marked obsolete. + + Test the condition asserted by an asserter and throw + an assertion exception using provided message on failure. + + An object that implements IAsserter + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + + A Constraint to be applied + The actual value to test + + + + Apply a constraint to an actual value, succeedingt if the constraint + is satisfied and throwing an assertion exception on failure. + + A Constraint to be applied + The actual value to test + The message that will be displayed on failure + + + + Apply a constraint to an actual value, succeedingt if the constraint + is satisfied and throwing an assertion exception on failure. + + A Constraint to be applied + The actual value to test + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that a condition is true. If the condition is false the method throws + an . + + The evaluated condition + The message to display if the condition is false + Arguments to be used in formatting the message + + + + Asserts that a condition is true. If the condition is false the method throws + an . + + The evaluated condition + The message to display if the condition is false + + + + Asserts that a condition is true. If the condition is false the method throws + an . + + The evaluated condition + + + + Verifies that the first value is greater than or equal to the second + value. If they are not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Verifies that the first value is greater than or equal to the second + value. If they are not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message that will be displayed on failure + + + + Verifies that the first value is greater than or equal to the second + value. If they are not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than or equal to the second + value. If they are not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Verifies that the first value is greater than or equal to the second + value. If they are not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message that will be displayed on failure + + + + Verifies that the first value is greater or equal to than the second + value. If they are not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than or equal to the second + value. If they are not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Verifies that the first value is greater than or equal to the second + value. If they are not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message that will be displayed on failure + + + + Verifies that the first value is greater or equal to than the second + value. If they are not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than or equal to the second + value. If they are not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Verifies that the first value is greater than or equal to the second + value. If they are not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message that will be displayed on failure + + + + Verifies that the first value is greater or equal to than the second + value. If they are not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than or equal to the second + value. If they are not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Verifies that the first value is greater than or equal to the second + value. If they are not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message that will be displayed on failure + + + + Verifies that the first value is greater than or equal to the second + value. If they are not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than or equal to the second + value. If they are not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Verifies that the first value is greater than or equal to the second + value. If they are not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message that will be displayed on failure + + + + Verifies that the first value is greater than or equal to the second + value. If they are not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than or equal to the second + value. If they are not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Verifies that the first value is greater than or equal to the second + value. If they are not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message that will be displayed on failure + + + + Verifies that the first value is greater than or equal to the second + value. If they are not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than the second + value. If they are not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Verifies that the first value is greater than the second + value. If they are not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message that will be displayed on failure + + + + Verifies that the first value is greater than the second + value. If they are not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message that will be displayed on failure + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message that will be displayed on failure + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message that will be displayed on failure + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message that will be displayed on failure + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message that will be displayed on failure + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message that will be displayed on failure + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message that will be displayed on failure + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message that will be displayed on failure + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Gets the number of assertions executed so far and + resets the counter to zero. + + + + + Enumeration indicating how the expected message parameter is to be used + + + + Expect an exact match + + + Expect a message containing the parameter string + + + Match the regular expression provided as a parameter + + + + ExpectedExceptionAttribute + + + + + + Constructor for a non-specific exception + + + + + Constructor for a given type of exception + + The type of the expected exception + + + + Constructor for a given exception name + + The full name of the expected exception + + + + Constructor for a given type of exception and expected message text + + The type of the expected exception + The expected message text + + + + Constructor for a given exception name and expected message text + + The full name of the expected exception + The expected messge text + + + + Gets or sets the expected exception type + + + + + Gets or sets the full Type name of the expected exception + + + + + Gets or sets the expected message text + + + + + Gets or sets the user message displayed in case of failure + + + + + Gets or sets the type of match to be performed on the expected message + + + + + Gets the name of a method to be used as an exception handler + + + + + A set of Assert methods operationg on one or more collections + + + + + The Equals method throws an AssertionException. This is done + to make sure there is no mistake by calling this function. + + + + + + + override the default ReferenceEquals to throw an AssertionException. This + implementation makes sure there is no mistake in calling this function + as part of Assert. + + + + + + + Asserts that all items contained in collection are of the type specified by expectedType. + + IEnumerable containing objects to be considered + System.Type that all objects in collection must be instances of + + + + Asserts that all items contained in collection are of the type specified by expectedType. + + IEnumerable containing objects to be considered + System.Type that all objects in collection must be instances of + The message that will be displayed on failure + + + + Asserts that all items contained in collection are of the type specified by expectedType. + + IEnumerable containing objects to be considered + System.Type that all objects in collection must be instances of + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that all items contained in collection are not equal to null. + + IEnumerable containing objects to be considered + + + + Asserts that all items contained in collection are not equal to null. + + IEnumerable containing objects to be considered + The message that will be displayed on failure + + + + Asserts that all items contained in collection are not equal to null. + + IEnumerable of objects to be considered + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Ensures that every object contained in collection exists within the collection + once and only once. + + IEnumerable of objects to be considered + + + + Ensures that every object contained in collection exists within the collection + once and only once. + + IEnumerable of objects to be considered + The message that will be displayed on failure + + + + Ensures that every object contained in collection exists within the collection + once and only once. + + IEnumerable of objects to be considered + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that expected and actual are exactly equal. The collections must have the same count, + and contain the exact same objects in the same order. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + + + + Asserts that expected and actual are exactly equal. The collections must have the same count, + and contain the exact same objects in the same order. + If comparer is not null then it will be used to compare the objects. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The IComparer to use in comparing objects from each IEnumerable + + + + Asserts that expected and actual are exactly equal. The collections must have the same count, + and contain the exact same objects in the same order. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The message that will be displayed on failure + + + + Asserts that expected and actual are exactly equal. The collections must have the same count, + and contain the exact same objects in the same order. + If comparer is not null then it will be used to compare the objects. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The IComparer to use in comparing objects from each IEnumerable + The message that will be displayed on failure + + + + Asserts that expected and actual are exactly equal. The collections must have the same count, + and contain the exact same objects in the same order. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that expected and actual are exactly equal. The collections must have the same count, + and contain the exact same objects in the same order. + If comparer is not null then it will be used to compare the objects. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The IComparer to use in comparing objects from each IEnumerable + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that expected and actual are equivalent, containing the same objects but the match may be in any order. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + + + + Asserts that expected and actual are equivalent, containing the same objects but the match may be in any order. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The message that will be displayed on failure + + + + Asserts that expected and actual are equivalent, containing the same objects but the match may be in any order. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that expected and actual are not exactly equal. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + + + + Asserts that expected and actual are not exactly equal. + If comparer is not null then it will be used to compare the objects. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The IComparer to use in comparing objects from each IEnumerable + + + + Asserts that expected and actual are not exactly equal. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The message that will be displayed on failure + + + + Asserts that expected and actual are not exactly equal. + If comparer is not null then it will be used to compare the objects. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The IComparer to use in comparing objects from each IEnumerable + The message that will be displayed on failure + + + + Asserts that expected and actual are not exactly equal. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that expected and actual are not exactly equal. + If comparer is not null then it will be used to compare the objects. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The IComparer to use in comparing objects from each IEnumerable + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that expected and actual are not equivalent. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + + + + Asserts that expected and actual are not equivalent. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The message that will be displayed on failure + + + + Asserts that expected and actual are not equivalent. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that collection contains actual as an item. + + IEnumerable of objects to be considered + Object to be found within collection + + + + Asserts that collection contains actual as an item. + + IEnumerable of objects to be considered + Object to be found within collection + The message that will be displayed on failure + + + + Asserts that collection contains actual as an item. + + IEnumerable of objects to be considered + Object to be found within collection + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that collection does not contain actual as an item. + + IEnumerable of objects to be considered + Object that cannot exist within collection + + + + Asserts that collection does not contain actual as an item. + + IEnumerable of objects to be considered + Object that cannot exist within collection + The message that will be displayed on failure + + + + Asserts that collection does not contain actual as an item. + + IEnumerable of objects to be considered + Object that cannot exist within collection + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that superset is not a subject of subset. + + The IEnumerable superset to be considered + The IEnumerable subset to be considered + + + + Asserts that superset is not a subject of subset. + + The IEnumerable superset to be considered + The IEnumerable subset to be considered + The message that will be displayed on failure + + + + Asserts that superset is not a subject of subset. + + The IEnumerable superset to be considered + The IEnumerable subset to be considered + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that superset is a subset of subset. + + The IEnumerable superset to be considered + The IEnumerable subset to be considered + + + + Asserts that superset is a subset of subset. + + The IEnumerable superset to be considered + The IEnumerable subset to be considered + The message that will be displayed on failure + + + + Asserts that superset is a subset of subset. + + The IEnumerable superset to be considered + The IEnumerable subset to be considered + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Assert that an array, list or other collection is empty + + An array, list or other collection implementing IEnumerable + The message to be displayed on failure + Arguments to be used in formatting the message + + + + Assert that an array, list or other collection is empty + + An array, list or other collection implementing IEnumerable + The message to be displayed on failure + + + + Assert that an array,list or other collection is empty + + An array, list or other collection implementing IEnumerable + + + + Assert that an array, list or other collection is empty + + An array, list or other collection implementing IEnumerable + The message to be displayed on failure + Arguments to be used in formatting the message + + + + Assert that an array, list or other collection is empty + + An array, list or other collection implementing IEnumerable + The message to be displayed on failure + + + + Assert that an array,list or other collection is empty + + An array, list or other collection implementing IEnumerable + + + + NOTE: The use of asserters for extending NUnit has + now been replaced by the use of constraints. This + class is marked obsolete. + + AbstractAsserter is the base class for all asserters. + Asserters encapsulate a condition test and generation + of an AssertionException with a tailored message. They + are used by the Assert class as helper objects. + + User-defined asserters may be passed to the + Assert.DoAssert method in order to implement + extended asserts. + + + + + NOTE: The use of asserters for extending NUnit has + now been replaced by the use of constraints. This + interface is marked obsolete. + + The interface implemented by an asserter. Asserters + encapsulate a condition test and generation of an + AssertionException with a tailored message. They + are used by the Assert class as helper objects. + + User-defined asserters may be passed to the + Assert.DoAssert method in order to implement + extended asserts. + + + + + Test the condition for the assertion. + + True if the test succeeds + + + + Return the message giving the failure reason. + The return value is unspecified if no failure + has occured. + + + + + The user-defined message for this asserter. + + + + + Arguments to use in formatting the user-defined message. + + + + + Our failure message object, initialized as needed + + + + + Constructs an AbstractAsserter + + The message issued upon failure + Arguments to be used in formatting the message + + + + Test method to be implemented by derived types. + Default always succeeds. + + True if the test succeeds + + + + AssertionFailureMessage object used internally + + + + + Message related to a failure. If no failure has + occured, the result is unspecified. + + + + + The Assertion class is obsolete and has been + replaced by the Assert class. + + + + + Asserts that a condition is true. If it isn't it throws + an . + + The message to display is the condition + is false + The evaluated condition + + + + Asserts that a condition is true. If it isn't it throws + an . + + The evaluated condition + + + + /// Asserts that two doubles are equal concerning a delta. If the + expected value is infinity then the delta value is ignored. + + The expected value + The actual value + The maximum acceptable difference between the + the expected and the actual + + + + /// Asserts that two singles are equal concerning a delta. If the + expected value is infinity then the delta value is ignored. + + The expected value + The actual value + The maximum acceptable difference between the + the expected and the actual + + + Asserts that two objects are equal. If they are not + an is thrown. + + + Asserts that two ints are equal. If they are not + an is thrown. + + + Asserts that two ints are equal. If they are not + an is thrown. + + + Asserts that two doubles are equal concerning a delta. + If the expected value is infinity then the delta value is ignored. + + + + Asserts that two floats are equal concerning a delta. + If the expected value is infinity then the delta value is ignored. + + + + + Asserts that two objects are equal. Two objects are considered + equal if both are null, or if both have the same value. Numeric + types are compared via string comparision on their contents to + avoid problems comparing values between different types. All + non-numeric types are compared by using the Equals method. + If they are not equal an is thrown. + + + + Asserts that an object isn't null. + + + Asserts that an object isn't null. + + + Asserts that an object is null. + + + Asserts that an object is null. + + + Asserts that two objects refer to the same object. If they + are not the same an is thrown. + + + + Asserts that two objects refer to the same object. + If they are not an is thrown. + + + + Fails a test with no message. + + + Fails a test with the given message. + + + + Thrown when an assertion failed. + + + + + The error message that explains + the reason for the exception + + + The error message that explains + the reason for the exception + The exception that caused the + current exception + + + + Serialization Constructor + + + + + AssertionFailureMessage encapsulates a failure message + issued as a result of an Assert failure. + + + + + Number of characters before a highlighted position before + clipping will occur. Clipped text is replaced with an + elipsis "..." + + + + + Number of characters after a highlighted position before + clipping will occur. Clipped text is replaced with an + elipsis "..." + + + + + Prefix used to start an expected value line. + Must be same length as actualPrefix. + + + + + Prefix used to start an actual value line. + Must be same length as expectedPrefix. + + + + + Construct an AssertionFailureMessage with a message + and optional arguments. + + + + + + + Construct an empty AssertionFailureMessage + + + + + Add an expected value line to the message containing + the text provided as an argument. + + Text describing what was expected. + + + + Add an actual value line to the message containing + the text provided as an argument. + + Text describing the actual value. + + + + Add an expected value line to the message containing + a string representation of the object provided. + + An object representing the expected value + + + + Add an expected value line to the message containing a double + and the tolerance used in making the comparison. + + The expected value + The tolerance specified in the Assert + + + + Add an actual value line to the message containing + a string representation of the object provided. + + An object representing what was actually found + + + + Display two lines that communicate the expected value, and the actual value + + The expected value + The actual value found + + + + Display two lines that communicate the expected value, the actual value and + the tolerance used in comparing two doubles. + + The expected value + The actual value found + The tolerance specified in the Assert + + + + Draws a marker under the expected/actual strings that highlights + where in the string a mismatch occurred. + + The position of the mismatch + + + + Reports whether the string lengths are the same or different, and + what the string lengths are. + + The expected string + The actual string value + + + + Called to create additional message lines when two objects have been + found to be unequal. If the inputs are strings, a special message is + rendered that can help track down where the strings are different, + based on differences in length, or differences in content. + + If the inputs are not strings, the ToString method of the objects + is used to show what is different about them. + + The expected value + The actual value + True if a case-insensitive comparison is being performed + + + + Called to create additional message lines when two doubles have been + found to be unequal, within the specified tolerance. + + + + + Constructs a message that can be displayed when the content of two + strings are different, but the string lengths are the same. The + message will clip the strings to a reasonable length, centered + around the first position where they are mismatched, and draw + a line marking the position of the difference to make comparison + quicker. + + The expected string value + The actual string value + True if a case-insensitive comparison is being performed + + + + Display a standard message showing the differences found between + two arrays that were expected to be equal. + + The expected array value + The actual array value + The index at which a difference was found + + + + Display a standard message showing the differences found between + two collections that were expected to be equal. + + The expected collection value + The actual collection value + The index at which a difference was found + + + + Get an array of indices representing the point in a collection or + array corresponding to a single int index into the collection. + + The collection to which the indices apply + Index in the collection + Array of indices + + + + Displays elements from a list on a line + + Text to prefix the line with + The list of items to display + The index in the list of the first element to display + The maximum number of elements to display + + + + Formats an object for display in a message line + + The object to be displayed + + + + + Tests two objects to determine if they are strings. + + + + + + + + Renders up to M characters before, and up to N characters after + the specified index position. If leading or trailing text is + clipped, and elipses "..." is added where the missing text would + be. + + Clips strings to limit previous or post newline characters, + since these mess up the comparison + + + + + + + + Shows the position two strings start to differ. Comparison + starts at the start index. + + + + + -1 if no mismatch found, or the index where mismatch found + + + + Turns CR, LF, or TAB into visual indicator to preserve visual marker + position. This is done by replacing the '\r' into '\\' and 'r' + characters, and the '\n' into '\\' and 'n' characters, and '\t' into + '\\' and 't' characters. + + Thus the single character becomes two characters for display. + + + + + + + Attribute used to apply a category to a test + + + + + The name of the category + + + + + Construct attribute for a given category + + The name of the category + + + + Protected constructor uses the Type name as the name + of the category. + + + + + The name of the category + + + + + Abstract base for Attributes that are used to include tests + in the test run based on environmental settings. + + + + + Constructor with no included items specified, for use + with named property syntax. + + + + + Constructor taking one or more included items + + Comma-delimited list of included items + + + + Name of the item that is needed in order for + a test to run. Multiple itemss may be given, + separated by a comma. + + + + + Name of the item to be excluded. Multiple items + may be given, separated by a comma. + + + + + The reason for including or excluding the test + + + + + PlatformAttribute is used to mark a test fixture or an + individual method as applying to a particular platform only. + + + + + Constructor with no platforms specified, for use + with named property syntax. + + + + + Constructor taking one or more platforms + + Comma-deliminted list of platforms + + + + CultureAttribute is used to mark a test fixture or an + individual method as applying to a particular Culture only. + + + + + Constructor with no cultures specified, for use + with named property syntax. + + + + + Constructor taking one or more cultures + + Comma-deliminted list of cultures + + + + MessageWriter is the abstract base for classes that write + constraint descriptions and messages in some form. The + class has separate methods for writing various components + of a message, allowing implementations to tailor the + presentation as needed. + + + + + Construct a MessageWriter given a culture + + + + + Method to write single line message with optional args, usually + written to precede the general failure message. + + The message to be written + Any arguments used in formatting the message + + + + Method to write single line message with optional args, usually + written to precede the general failure message, at a givel + indentation level. + + The indentation level of the message + The message to be written + Any arguments used in formatting the message + + + + Display Expected and Actual lines for a constraint. This + is called by MessageWriter's default implementation of + WriteMessageTo and provides the generic two-line display. + + The constraint that failed + + + + Display Expected and Actual lines for given values. This + method may be called by constraints that need more control over + the display of actual and expected values than is provided + by the default implementation. + + The expected value + The actual value causing the failure + + + + Display Expected and Actual lines for given values, including + a tolerance value on the Expected line. + + The expected value + The actual value causing the failure + The tolerance within which the test was made + + + + Display the expected and actual string values on separate lines. + If the mismatch parameter is >=0, an additional line is displayed + line containing a caret that points to the mismatch point. + + The expected string value + The actual string value + The point at which the strings don't match or -1 + If true, case is ignored in locating the point where the strings differ + If true, the strings should be clipped to fit the line + + + + Writes the text for a connector. + + The connector. + + + + Writes the text for a predicate. + + The predicate. + + + + Writes the text for an expected value. + + The expected value. + + + + Writes the text for a modifier + + The modifier. + + + + Writes the text for an actual value. + + The actual value. + + + + Writes the text for a generalized value. + + The value. + + + + Writes the text for a collection value, + starting at a particular point, to a max length + + The collection containing elements to write. + The starting point of the elements to write + The maximum number of elements to write + + + + Abstract method to get the max line length + + + + + Static methods used in creating messages + + + + + Static string used when strings are clipped + + + + + Returns the representation of a type as used in NUnitLite. + This is the same as Type.ToString() except for arrays, + which are displayed with their declared sizes. + + + + + + + Converts any control characters in a string + to their escaped representation. + + The string to be converted + The converted string + + + + Return the a string representation for a set of indices into an array + + Array of indices for which a string is needed + + + + Get an array of indices representing the point in a collection or + array corresponding to a single int index into the collection. + + The collection to which the indices apply + Index in the collection + Array of indices + + + + Clip a string to a given length, starting at a particular offset, returning the clipped + string with ellipses representing the removed parts + + The string to be clipped + The maximum permitted length of the result string + The point at which to start clipping + The clipped string + + + + Clip the expected and actual strings in a coordinated fashion, + so that they may be displayed together. + + + + + + + + + Shows the position two strings start to differ. Comparison + starts at the start index. + + The expected string + The actual string + The index in the strings at which comparison should start + Boolean indicating whether case should be ignored + -1 if no mismatch found, or the index where mismatch found + + + + Summary description for SetCultureAttribute. + + + + + PropertyAttribute is used to attach information to a test as a name/value pair.. + + + + + The property name + + + + + The property value + + + + + Construct a PropertyAttribute with a name and value + + The name of the property + The property value + + + + Constructor for use by inherited classes that use the + name of the type as the property name. + + + + + Gets the property name + + + + + Gets the property value + + + + + Construct given the name of a culture + + + + + + TextMessageWriter writes constraint descriptions and messages + in displayable form as a text stream. It tailors the display + of individual message components to form the standard message + format of NUnit assertion failure messages. + + + + + Prefix used for the expected value line of a message + + + + + Prefix used for the actual value line of a message + + + + + Length of a message prefix + + + + + Construct a TextMessageWriter + + + + + Construct a TextMessageWriter, specifying a user message + and optional formatting arguments. + + + + + + + Method to write single line message with optional args, usually + written to precede the general failure message, at a givel + indentation level. + + The indentation level of the message + The message to be written + Any arguments used in formatting the message + + + + Display Expected and Actual lines for a constraint. This + is called by MessageWriter's default implementation of + WriteMessageTo and provides the generic two-line display. + + The constraint that failed + + + + Display Expected and Actual lines for given values. This + method may be called by constraints that need more control over + the display of actual and expected values than is provided + by the default implementation. + + The expected value + The actual value causing the failure + + + + Display Expected and Actual lines for given values, including + a tolerance value on the expected line. + + The expected value + The actual value causing the failure + The tolerance within which the test was made + + + + Display the expected and actual string values on separate lines. + If the mismatch parameter is >=0, an additional line is displayed + line containing a caret that points to the mismatch point. + + The expected string value + The actual string value + The point at which the strings don't match or -1 + If true, case is ignored in string comparisons + If true, clip the strings to fit the max line length + + + + Writes the text for a connector. + + The connector. + + + + Writes the text for a predicate. + + The predicate. + + + + Write the text for a modifier. + + The modifier. + + + + Writes the text for an expected value. + + The expected value. + + + + Writes the text for an actual value. + + The actual value. + + + + Writes the text for a generalized value. + + The value. + + + + Writes the text for a collection value, + starting at a particular point, to a max length + + The collection containing elements to write. + The starting point of the elements to write + The maximum number of elements to write + + + + Write the generic 'Expected' line for a constraint + + The constraint that failed + + + + Write the generic 'Expected' line for a given value + + The expected value + + + + Write the generic 'Expected' line for a given value + and tolerance. + + The expected value + The tolerance within which the test was made + + + + Write the generic 'Actual' line for a constraint + + The constraint for which the actual value is to be written + + + + Write the generic 'Actual' line for a given value + + The actual value causing a failure + + + + Gets or sets the maximum line length for this writer + + + + + Basic Asserts on strings. + + + + + The Equals method throws an AssertionException. This is done + to make sure there is no mistake by calling this function. + + + + + + + override the default ReferenceEquals to throw an AssertionException. This + implementation makes sure there is no mistake in calling this function + as part of Assert. + + + + + + + Asserts that a string is found within another string. + + The expected string + The string to be examined + The message to display in case of failure + Arguments used in formatting the message + + + + Asserts that a string is found within another string. + + The expected string + The string to be examined + The message to display in case of failure + + + + Asserts that a string is found within another string. + + The expected string + The string to be examined + + + + Asserts that a string starts with another string. + + The expected string + The string to be examined + The message to display in case of failure + Arguments used in formatting the message + + + + Asserts that a string starts with another string. + + The expected string + The string to be examined + The message to display in case of failure + + + + Asserts that a string starts with another string. + + The expected string + The string to be examined + + + + Asserts that a string ends with another string. + + The expected string + The string to be examined + The message to display in case of failure + Arguments used in formatting the message + + + + Asserts that a string ends with another string. + + The expected string + The string to be examined + The message to display in case of failure + + + + Asserts that a string ends with another string. + + The expected string + The string to be examined + + + + Asserts that two strings are equal, without regard to case. + + The expected string + The actual string + The message to display in case of failure + Arguments used in formatting the message + + + + Asserts that two strings are equal, without regard to case. + + The expected string + The actual string + The message to display in case of failure + + + + Asserts that two strings are equal, without regard to case. + + The expected string + The actual string + + + + Asserts that a string matches an expected regular expression pattern. + + The expected expression + The actual string + The message to display in case of failure + Arguments used in formatting the message + + + + Asserts that a string matches an expected regular expression pattern. + + The expected expression + The actual string + The message to display in case of failure + + + + Asserts that a string matches an expected regular expression pattern. + + The expected expression + The actual string + + + + AssertionHelper is an optional base class for user tests, + allowing the use of shorter names for constraints and + asserts and avoiding conflict with the definition of + , from which it inherits much of its + behavior, in certain mock object frameworks. + + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. Works + identically to + + A Constraint to be applied + The actual value to test + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. Works + identically to + + A Constraint to be applied + The actual value to test + The message that will be displayed on failure + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. Works + identically to + + A Constraint to be applied + The actual value to test + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that a condition is true. If the condition is false the method throws + an . Works Identically to + . + + The evaluated condition + The message to display if the condition is false + Arguments to be used in formatting the message + + + + Asserts that a condition is true. If the condition is false the method throws + an . Works Identically to + . + + The evaluated condition + The message to display if the condition is false + + + + Asserts that a condition is true. If the condition is false the method throws + an . Works Identically to . + + The evaluated condition + + + + Returns a ListMapper based on a collection. + + The original collection + + + + + Summary description for FileAssert. + + + + + The Equals method throws an AssertionException. This is done + to make sure there is no mistake by calling this function. + + + + + + + override the default ReferenceEquals to throw an AssertionException. This + implementation makes sure there is no mistake in calling this function + as part of Assert. + + + + + + + We don't actually want any instances of this object, but some people + like to inherit from it to add other static methods. Hence, the + protected constructor disallows any instances of this object. + + + + + Verifies that two Streams are equal. Two Streams are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + The expected Stream + The actual Stream + The message to display if Streams are not equal + Arguments to be used in formatting the message + + + + Verifies that two Streams are equal. Two Streams are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + The expected Stream + The actual Stream + The message to display if objects are not equal + + + + Verifies that two Streams are equal. Two Streams are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + The expected Stream + The actual Stream + + + + Verifies that two files are equal. Two files are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + A file containing the value that is expected + A file containing the actual value + The message to display if Streams are not equal + Arguments to be used in formatting the message + + + + Verifies that two files are equal. Two files are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + A file containing the value that is expected + A file containing the actual value + The message to display if objects are not equal + + + + Verifies that two files are equal. Two files are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + A file containing the value that is expected + A file containing the actual value + + + + Verifies that two files are equal. Two files are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + The path to a file containing the value that is expected + The path to a file containing the actual value + The message to display if Streams are not equal + Arguments to be used in formatting the message + + + + Verifies that two files are equal. Two files are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + The path to a file containing the value that is expected + The path to a file containing the actual value + The message to display if objects are not equal + + + + Verifies that two files are equal. Two files are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + The path to a file containing the value that is expected + The path to a file containing the actual value + + + + Asserts that two Streams are not equal. If they are equal + an is thrown. + + The expected Stream + The actual Stream + The message to be displayed when the two Stream are the same. + Arguments to be used in formatting the message + + + + Asserts that two Streams are not equal. If they are equal + an is thrown. + + The expected Stream + The actual Stream + The message to be displayed when the Streams are the same. + + + + Asserts that two Streams are not equal. If they are equal + an is thrown. + + The expected Stream + The actual Stream + + + + Asserts that two files are not equal. If they are equal + an is thrown. + + A file containing the value that is expected + A file containing the actual value + The message to display if Streams are not equal + Arguments to be used in formatting the message + + + + Asserts that two files are not equal. If they are equal + an is thrown. + + A file containing the value that is expected + A file containing the actual value + The message to display if objects are not equal + + + + Asserts that two files are not equal. If they are equal + an is thrown. + + A file containing the value that is expected + A file containing the actual value + + + + Asserts that two files are not equal. If they are equal + an is thrown. + + The path to a file containing the value that is expected + The path to a file containing the actual value + The message to display if Streams are not equal + Arguments to be used in formatting the message + + + + Asserts that two files are not equal. If they are equal + an is thrown. + + The path to a file containing the value that is expected + The path to a file containing the actual value + The message to display if objects are not equal + + + + Asserts that two files are not equal. If they are equal + an is thrown. + + The path to a file containing the value that is expected + The path to a file containing the actual value + + + + Thrown when an assertion failed. + + + + + + + The error message that explains + the reason for the exception + The exception that caused the + current exception + + + + Serialization Constructor + + + + + GlobalSettings is a place for setting default values used + by the framework in performing asserts. + + + + + Default tolerance for floating point equality + + + + + Obsolete class, formerly used to identify tests through + inheritance. Avoid using this class for new tests. + + + + + Method called immediately before running the test. + + + + + Method Called immediately after running the test. It is + guaranteed to be called, even if an exception is thrown. + + + + + Attribute used to mark a class that contains one-time SetUp + and/or TearDown methods that apply to all the tests in a + namespace or an assembly. + + + + + SetUpFixtureAttribute is used to identify a SetUpFixture + + + + + Attribute used to mark a static (shared in VB) property + that returns a list of tests. + + + + + Attribute used to identify a method that is called + immediately after each test is run. The method is + guaranteed to be called, even if an exception is thrown. + + + + + Adding this attribute to a method within a + class makes the method callable from the NUnit test runner. There is a property + called Description which is optional which you can provide a more detailed test + description. This class cannot be inherited. + + + + [TestFixture] + public class Fixture + { + [Test] + public void MethodToTest() + {} + + [Test(Description = "more detailed description")] + publc void TestDescriptionMethod() + {} + } + + + + + + Descriptive text for this test + + + + + [TestFixture] + public class ExampleClass + {} + + + + + Descriptive text for this fixture + + + + + Attribute used to identify a method that is + called before any tests in a fixture are run. + + + + + Attribute used to identify a method that is called after + all the tests in a fixture have run. The method is + guaranteed to be called, even if an exception is thrown. + + + + + Attribute used to mark a test that is to be ignored. + Ignored tests result in a warning message when the + tests are run. + + + + + Constructs the attribute without giving a reason + for ignoring the test. + + + + + Constructs the attribute giving a reason for ignoring the test + + The reason for ignoring the test + + + + The reason for ignoring a test + + + + + ExplicitAttribute marks a test or test fixture so that it will + only be run if explicitly executed from the gui or command line + or if it is included by use of a filter. The test will not be + run simply because an enclosing suite is run. + + + + + Default constructor + + + + + Constructor with a reason + + The reason test is marked explicit + + + + The reason test is marked explicit + + + + + Attribute used to provide descriptive text about a + test case or fixture. + + + + + Construct the attribute + + Text describing the test + + + + Gets the test description + + + + + Interface implemented by a user fixture in order to + validate any expected exceptions. It is only called + for test methods marked with the ExpectedException + attribute. + + + + + Method to handle an expected exception + + The exception to be handled + + + diff --git a/lic/OpenSymphony.txt b/lic/OpenSymphony.txt new file mode 100644 index 0000000..851b9f3 --- /dev/null +++ b/lic/OpenSymphony.txt @@ -0,0 +1 @@ +The OpenSymphony Software License \ No newline at end of file diff --git a/src/CrontabConsole/NCrontabConsole.csproj b/src/CrontabConsole/NCrontabConsole.csproj new file mode 100644 index 0000000..55cf54a --- /dev/null +++ b/src/CrontabConsole/NCrontabConsole.csproj @@ -0,0 +1,60 @@ + + + Debug + AnyCPU + 9.0.21022 + 2.0 + {89D84924-0952-40FC-8994-758C4215ABEB} + Exe + Properties + NCrontabConsole + NCrontabConsole + NCrontabConsole.Program + + + 2.0 + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + SolutionInfo.cs + + + + + + + {1948D266-8DCB-4AC5-98E6-A609713011CB} + NCrontab + + + + + \ No newline at end of file diff --git a/src/CrontabConsole/Program.cs b/src/CrontabConsole/Program.cs new file mode 100644 index 0000000..9990f24 --- /dev/null +++ b/src/CrontabConsole/Program.cs @@ -0,0 +1,85 @@ +#region License, Terms and Author(s) +// +// NCrontab - Crontab for .NET +// Copyright (c) 2008 Atif Aziz. All rights reserved. +// +// Author(s): +// +// Atif Aziz, http://www.raboof.com +// +// This library is free software; you can redistribute it and/or modify it +// under the terms of the New BSD License, a copy of which should have +// been delivered along with this distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +#endregion + +namespace NCrontabConsole +{ + #region Imports + + using System; + using System.Diagnostics; + using System.Globalization; + using System.IO; + using NCrontab; + + #endregion + + internal static class Program + { + private static int Main(string[] args) + { + try + { + if (args.Length != 3) + throw new ApplicationException("Missing required arguments. You must at least supply CRONTAB-EXPRESSION START-DATE END-DATE."); + + var expression = args[0]; + var start = ParseDateArgument(args[1], "start"); + var end = ParseDateArgument(args[2], "end"); + var format = args.Length == 4 ? args[3] : "f"; + + WriteOccurrences(CrontabSchedule.Parse(expression), start, end, format, Console.Out); + + return 0; + } + catch (Exception e) + { + Console.Error.WriteLine(e.Message); + Trace.WriteLine(e.ToString()); + return 1; + } + } + + private static DateTime ParseDateArgument(string arg, string hint) + { + try + { + return DateTime.Parse(arg, null, DateTimeStyles.AssumeLocal); + } + catch (FormatException e) + { + throw new ApplicationException("Invalid " + hint + " date or date format argument.", e); + } + } + + private static void WriteOccurrences(CrontabSchedule schedule, DateTime start, DateTime end, string format, TextWriter output) + { + var occurrence = schedule.GetNextOccurrences(start, end).GetEnumerator(); + while (occurrence.MoveNext()) + output.WriteLine(occurrence.Current.ToString(format)); + } + } +} diff --git a/src/CrontabConsole/Properties/AssemblyInfo.cs b/src/CrontabConsole/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..71dfcf5 --- /dev/null +++ b/src/CrontabConsole/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +#region License, Terms and Author(s) +// +// NCrontab - Crontab for .NET +// Copyright (c) 2008 Atif Aziz. All rights reserved. +// +// Author(s): +// +// Atif Aziz, http://www.raboof.com +// +// This library is free software; you can redistribute it and/or modify it +// under the terms of the New BSD License, a copy of which should have +// been delivered along with this distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +#endregion + +using System.Reflection; + +[assembly: AssemblyTitle("NCrontabConsole")] +[assembly: AssemblyDescription("NCrontab console sample")] + +[assembly: AssemblyVersion("0.2.0.0")] +[assembly: AssemblyFileVersion("0.2.0.0")] + + diff --git a/src/CrontabViewer/MainForm.Designer.cs b/src/CrontabViewer/MainForm.Designer.cs new file mode 100644 index 0000000..657e6d8 --- /dev/null +++ b/src/CrontabViewer/MainForm.Designer.cs @@ -0,0 +1,199 @@ +namespace NCrontabViewer +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + this._startTimePicker = new System.Windows.Forms.DateTimePicker(); + this._endTimePicker = new System.Windows.Forms.DateTimePicker(); + this._timer = new System.Windows.Forms.Timer(this.components); + this._resultBox = new System.Windows.Forms.RichTextBox(); + this._cronBox = new System.Windows.Forms.TextBox(); + this.label1 = new System.Windows.Forms.Label(); + this.label2 = new System.Windows.Forms.Label(); + this.label3 = new System.Windows.Forms.Label(); + this._moreButton = new System.Windows.Forms.Button(); + this._statusBar = new System.Windows.Forms.StatusBar(); + this._statusBarPanel = new System.Windows.Forms.StatusBarPanel(); + this._errorProvider = new System.Windows.Forms.ErrorProvider(this.components); + ((System.ComponentModel.ISupportInitialize)(this._statusBarPanel)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this._errorProvider)).BeginInit(); + this.SuspendLayout(); + // + // _startTimePicker + // + this._startTimePicker.CustomFormat = "dd/MM/yyyy HH:mm"; + this._startTimePicker.Format = System.Windows.Forms.DateTimePickerFormat.Custom; + this._startTimePicker.Location = new System.Drawing.Point(65, 16); + this._startTimePicker.Name = "_startTimePicker"; + this._startTimePicker.Size = new System.Drawing.Size(166, 23); + this._startTimePicker.TabIndex = 0; + this._startTimePicker.ValueChanged += new System.EventHandler(this.CronBox_Changed); + // + // _endTimePicker + // + this._endTimePicker.CustomFormat = "dd/MM/yyyy HH:mm"; + this._endTimePicker.Format = System.Windows.Forms.DateTimePickerFormat.Custom; + this._endTimePicker.Location = new System.Drawing.Point(298, 16); + this._endTimePicker.Name = "_endTimePicker"; + this._endTimePicker.Size = new System.Drawing.Size(166, 23); + this._endTimePicker.TabIndex = 1; + this._endTimePicker.ValueChanged += new System.EventHandler(this.CronBox_Changed); + // + // _timer + // + this._timer.Enabled = true; + this._timer.Interval = 500; + this._timer.Tick += new System.EventHandler(this.Timer_Tick); + // + // _resultBox + // + this._resultBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this._resultBox.BackColor = System.Drawing.SystemColors.Control; + this._resultBox.Font = new System.Drawing.Font("Courier New", 7.8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this._resultBox.Location = new System.Drawing.Point(16, 88); + this._resultBox.Name = "_resultBox"; + this._resultBox.ReadOnly = true; + this._resultBox.ScrollBars = System.Windows.Forms.RichTextBoxScrollBars.Vertical; + this._resultBox.Size = new System.Drawing.Size(531, 344); + this._resultBox.TabIndex = 3; + this._resultBox.Text = ""; + // + // _cronBox + // + this._cronBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this._cronBox.Location = new System.Drawing.Point(143, 48); + this._cronBox.Name = "_cronBox"; + this._cronBox.Size = new System.Drawing.Size(323, 23); + this._cronBox.TabIndex = 2; + this._cronBox.Text = "* * * * *"; + this._cronBox.TextChanged += new System.EventHandler(this.CronBox_Changed); + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(16, 16); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(43, 17); + this.label1.TabIndex = 4; + this.label1.Text = "&Start:"; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(255, 16); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(37, 17); + this.label2.TabIndex = 5; + this.label2.Text = "&End:"; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(16, 48); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(121, 17); + this.label3.TabIndex = 6; + this.label3.Text = "&Recurring Pattern:"; + // + // _moreButton + // + this._moreButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this._moreButton.Enabled = false; + this._moreButton.Location = new System.Drawing.Point(491, 48); + this._moreButton.Name = "_moreButton"; + this._moreButton.Size = new System.Drawing.Size(56, 24); + this._moreButton.TabIndex = 7; + this._moreButton.Text = "&More"; + this._moreButton.Click += new System.EventHandler(this.More_Click); + // + // _statusBar + // + this._statusBar.Location = new System.Drawing.Point(0, 448); + this._statusBar.Name = "_statusBar"; + this._statusBar.Panels.AddRange(new System.Windows.Forms.StatusBarPanel[] { + this._statusBarPanel}); + this._statusBar.ShowPanels = true; + this._statusBar.Size = new System.Drawing.Size(563, 24); + this._statusBar.TabIndex = 8; + this._statusBar.Text = "Ready"; + // + // _statusBarPanel + // + this._statusBarPanel.AutoSize = System.Windows.Forms.StatusBarPanelAutoSize.Spring; + this._statusBarPanel.Name = "_statusBarPanel"; + this._statusBarPanel.Text = "Ready"; + this._statusBarPanel.Width = 487; + // + // _errorProvider + // + this._errorProvider.BlinkStyle = System.Windows.Forms.ErrorBlinkStyle.AlwaysBlink; + this._errorProvider.ContainerControl = this; + // + // MainForm + // + this.AutoScaleBaseSize = new System.Drawing.Size(6, 16); + this.ClientSize = new System.Drawing.Size(563, 472); + this.Controls.Add(this._statusBar); + this.Controls.Add(this._moreButton); + this.Controls.Add(this.label3); + this.Controls.Add(this.label2); + this.Controls.Add(this.label1); + this.Controls.Add(this._cronBox); + this.Controls.Add(this._resultBox); + this.Controls.Add(this._startTimePicker); + this.Controls.Add(this._endTimePicker); + this.Font = new System.Drawing.Font("Tahoma", 7.8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.Name = "MainForm"; + this.Text = "Crontab Viewer"; + ((System.ComponentModel.ISupportInitialize)(this._statusBarPanel)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this._errorProvider)).EndInit(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.DateTimePicker _startTimePicker; + private System.Windows.Forms.DateTimePicker _endTimePicker; + private System.Windows.Forms.Timer _timer; + private System.Windows.Forms.RichTextBox _resultBox; + private System.Windows.Forms.TextBox _cronBox; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.Button _moreButton; + private System.Windows.Forms.StatusBar _statusBar; + private System.Windows.Forms.StatusBarPanel _statusBarPanel; + private System.Windows.Forms.ErrorProvider _errorProvider; + } +} \ No newline at end of file diff --git a/src/CrontabViewer/MainForm.cs b/src/CrontabViewer/MainForm.cs new file mode 100644 index 0000000..0f1658c --- /dev/null +++ b/src/CrontabViewer/MainForm.cs @@ -0,0 +1,182 @@ +#region License, Terms and Author(s) +// +// NCrontab - Crontab for .NET +// Copyright (c) 2008 Atif Aziz. All rights reserved. +// +// Author(s): +// +// Atif Aziz, http://www.raboof.com +// +// This library is free software; you can redistribute it and/or modify it +// under the terms of the New BSD License, a copy of which should have +// been delivered along with this distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +#endregion + +namespace NCrontabViewer +{ + #region Imports + + using System; + using System.Globalization; + using System.Text; + using System.Windows.Forms; + using NCrontab; + + #endregion + + public partial class MainForm : Form + { + private DateTime _lastChangeTime; + private bool _dirty; + private CrontabSchedule _crontab; + private DateTime _startTime; + private int _totalOccurrenceCount; + + public MainForm() + { + InitializeComponent(); + } + + private void CronBox_Changed(object sender, EventArgs args) + { + _lastChangeTime = DateTime.Now; + _dirty = true; + _crontab = null; + } + + private void Timer_Tick(object sender, EventArgs args) + { + var changeLapse = DateTime.Now - _lastChangeTime; + + if (!_dirty || changeLapse <= TimeSpan.FromMilliseconds(500)) + return; + + _dirty = false; + DoCrontabbing(); + } + + private void DoCrontabbing() + { + _resultBox.Clear(); + _errorProvider.SetError(_cronBox, null); + _statusBarPanel.Text = "Ready"; + _moreButton.Enabled = false; + + if (_crontab == null) + { + try + { + var expression = _cronBox.Text.Trim(); + + if (expression.Length == 0) + return; + + _crontab = CrontabSchedule.Parse(expression); + + _totalOccurrenceCount = 0; + + _startTime = DateTime.ParseExact(_startTimePicker.Text, + _startTimePicker.CustomFormat, CultureInfo.InvariantCulture, + DateTimeStyles.AssumeLocal).AddMinutes(-1); + } + catch (CrontabException e) + { + _errorProvider.SetError(_cronBox, e.Message); + + var traceBuilder = new StringBuilder(); + + Exception traceException = e; + Exception lastException; + + do + { + traceBuilder.Append(traceException.Message); + traceBuilder.Append("\r\n"); + lastException = traceException; + traceException = traceException.GetBaseException(); + } + while (lastException != traceException); + + _resultBox.Text = traceBuilder.ToString(); + return; + } + + } + + var endTime = DateTime.ParseExact(_endTimePicker.Text, + _endTimePicker.CustomFormat, CultureInfo.InvariantCulture, + DateTimeStyles.AssumeLocal); + + var sb = new StringBuilder(); + var lastTimeString = "??? ??, ??? ???? ??:??"; + + var count = 0; + const int maxCount = 500; + + foreach (var occurance in _crontab.GetNextOccurrences(_startTime, endTime)) + { + if (count + 1 > maxCount) + break; + + _startTime = occurance; + _totalOccurrenceCount++; + count++; + + var timeString = occurance.ToString("ddd dd, MMM yyyy HH:mm"); + sb.Append(timeString); + sb.Append(" | "); + + Diff(lastTimeString, timeString, 0, 3, sb); + sb.Append(' '); + Diff(lastTimeString, timeString, 4, 2, sb); + sb.Append(", "); + Diff(lastTimeString, timeString, 8, 3, sb); + sb.Append(' '); + Diff(lastTimeString, timeString, 12, 4, sb); + sb.Append(' '); + Diff(lastTimeString, timeString, 17, 2, sb); + sb.Append(':'); + Diff(lastTimeString, timeString, 20, 2, sb); + + lastTimeString = timeString; + + sb.Append("\r\n"); + } + + _moreButton.Enabled = count == maxCount; + + _statusBarPanel.Text = string.Format("Last count = {0}, Total = {1}", + count.ToString("N0"), _totalOccurrenceCount.ToString("N0")); + + _resultBox.Text = sb.ToString(); + _resultBox.Select(0, 0); + _resultBox.ScrollToCaret(); + } + + private static void Diff(string oldString, string newString, int index, int length, StringBuilder builder) + { + if (string.CompareOrdinal(oldString, index, newString, index, length) == 0) + builder.Append('-', length); + else + builder.Append(newString, index, length); + } + + private void More_Click(object sender, EventArgs e) + { + DoCrontabbing(); + } + } +} diff --git a/src/CrontabViewer/MainForm.resx b/src/CrontabViewer/MainForm.resx new file mode 100644 index 0000000..a32fc35 --- /dev/null +++ b/src/CrontabViewer/MainForm.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 166, 17 + + + 17, 17 + + \ No newline at end of file diff --git a/src/CrontabViewer/NCrontabViewer.csproj b/src/CrontabViewer/NCrontabViewer.csproj new file mode 100644 index 0000000..c84db89 --- /dev/null +++ b/src/CrontabViewer/NCrontabViewer.csproj @@ -0,0 +1,69 @@ + + + + Debug + AnyCPU + 9.0.21022 + 2.0 + {02F42DAC-8A9F-45BB-B734-BB08F0D194C4} + WinExe + Properties + NCrontabViewer + NCrontabViewer + v2.0 + 512 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + SolutionInfo.cs + + + Form + + + MainForm.cs + + + + + MainForm.cs + Designer + + + + + {1948D266-8DCB-4AC5-98E6-A609713011CB} + NCrontab + + + + + \ No newline at end of file diff --git a/src/CrontabViewer/Program.cs b/src/CrontabViewer/Program.cs new file mode 100644 index 0000000..ec43630 --- /dev/null +++ b/src/CrontabViewer/Program.cs @@ -0,0 +1,47 @@ +#region License, Terms and Author(s) +// +// NCrontab - Crontab for .NET +// Copyright (c) 2008 Atif Aziz. All rights reserved. +// +// Author(s): +// +// Atif Aziz, http://www.raboof.com +// +// This library is free software; you can redistribute it and/or modify it +// under the terms of the New BSD License, a copy of which should have +// been delivered along with this distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +#endregion + +namespace NCrontabViewer +{ + #region Imports + + using System; + using System.Windows.Forms; + + #endregion + + internal static class Program + { + [STAThread] + private static void Main() + { + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new MainForm()); + } + } +} diff --git a/src/CrontabViewer/Properties/AssemblyInfo.cs b/src/CrontabViewer/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..73e4f72 --- /dev/null +++ b/src/CrontabViewer/Properties/AssemblyInfo.cs @@ -0,0 +1,35 @@ +#region License, Terms and Author(s) +// +// NCrontab - Crontab for .NET +// Copyright (c) 2008 Atif Aziz. All rights reserved. +// +// Author(s): +// +// Atif Aziz, http://www.raboof.com +// +// This library is free software; you can redistribute it and/or modify it +// under the terms of the New BSD License, a copy of which should have +// been delivered along with this distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +#endregion + +using System.Reflection; + +[assembly: AssemblyTitle("NCrontabViewer")] +[assembly: AssemblyDescription("NCrontab GUI sample")] + +[assembly: AssemblyVersion("0.2.0.0")] +[assembly: AssemblyFileVersion("0.2.0.0")] + diff --git a/src/NCrontab.Tests/CrontabScheduleTests.cs b/src/NCrontab.Tests/CrontabScheduleTests.cs new file mode 100644 index 0000000..7adfa9c --- /dev/null +++ b/src/NCrontab.Tests/CrontabScheduleTests.cs @@ -0,0 +1,313 @@ +#region License, Terms and Author(s) +// +// NCrontab - Crontab for .NET +// Copyright (c) 2008 Atif Aziz. All rights reserved. +// +// Author(s): +// +// Atif Aziz, http://www.raboof.com +// +// This library is free software; you can redistribute it and/or modify it +// under the terms of the New BSD License, a copy of which should have +// been delivered along with this distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +#endregion + +namespace NCrontab.Tests +{ + #region Imports + + using System; + using System.Diagnostics; + using System.Globalization; + using System.Threading; + using NUnit.Framework; + + #endregion + + [ TestFixture ] + public sealed class CrontabScheduleTests + { + private const string _timeFormat = "dd/MM/yyyy HH:mm"; + + [ Test, ExpectedException(typeof(ArgumentNullException)) ] + public void CannotParseNullString() + { + CrontabSchedule.Parse(null); + } + + [ Test, ExpectedException(typeof(CrontabException)) ] + public void CannotParseEmptyString() + { + CrontabSchedule.Parse(string.Empty); + } + + [ Test ] + public void AllTimeString() + { + Assert.AreEqual("* * * * *", CrontabSchedule.Parse("* * * * *").ToString()); + } + + [ Test ] + public void Formatting() + { + Assert.AreEqual("* 1-3 * * *", CrontabSchedule.Parse("* 1-2,3 * * *").ToString()); + Assert.AreEqual("* * * 1,3,5,7,9,11 *", CrontabSchedule.Parse("* * * */2 *").ToString()); + Assert.AreEqual("10,25,40 * * * *", CrontabSchedule.Parse("10-40/15 * * * *").ToString()); + Assert.AreEqual("* * * 1,3,8 1-2,5", CrontabSchedule.Parse("* * * Mar,Jan,Aug Fri,Mon-Tue").ToString()); + } + + /// + /// Tests to see if the cron class can calculate the previous matching + /// time correctly in various circumstances. + /// + + [ Test ] + public void Evaluations() + { + CronCall("01/01/2003 00:00", "* * * * *", "01/01/2003 00:01", false); + CronCall("01/01/2003 00:01", "* * * * *", "01/01/2003 00:02", false); + CronCall("01/01/2003 00:02", "* * * * *", "01/01/2003 00:03", false); + CronCall("01/01/2003 00:59", "* * * * *", "01/01/2003 01:00", false); + CronCall("01/01/2003 01:59", "* * * * *", "01/01/2003 02:00", false); + CronCall("01/01/2003 23:59", "* * * * *", "02/01/2003 00:00", false); + CronCall("31/12/2003 23:59", "* * * * *", "01/01/2004 00:00", false); + + CronCall("28/02/2003 23:59", "* * * * *", "01/03/2003 00:00", false); + CronCall("28/02/2004 23:59", "* * * * *", "29/02/2004 00:00", false); + + // Minute tests + + CronCall("01/01/2003 00:00", "45 * * * *", "01/01/2003 00:45", false); + + CronCall("01/01/2003 00:00", "45-47,48,49 * * * *", "01/01/2003 00:45", false); + CronCall("01/01/2003 00:45", "45-47,48,49 * * * *", "01/01/2003 00:46", false); + CronCall("01/01/2003 00:46", "45-47,48,49 * * * *", "01/01/2003 00:47", false); + CronCall("01/01/2003 00:47", "45-47,48,49 * * * *", "01/01/2003 00:48", false); + CronCall("01/01/2003 00:48", "45-47,48,49 * * * *", "01/01/2003 00:49", false); + CronCall("01/01/2003 00:49", "45-47,48,49 * * * *", "01/01/2003 01:45", false); + + CronCall("01/01/2003 00:00", "2/5 * * * *", "01/01/2003 00:02", false); + CronCall("01/01/2003 00:02", "2/5 * * * *", "01/01/2003 00:07", false); + CronCall("01/01/2003 00:50", "2/5 * * * *", "01/01/2003 00:52", false); + CronCall("01/01/2003 00:52", "2/5 * * * *", "01/01/2003 00:57", false); + CronCall("01/01/2003 00:57", "2/5 * * * *", "01/01/2003 01:02", false); + + // Hour tests + + CronCall("20/12/2003 10:00", " * 3/4 * * *", "20/12/2003 11:00", false); + CronCall("20/12/2003 00:30", " * 3 * * *", "20/12/2003 03:00", false); + CronCall("20/12/2003 01:45", "30 3 * * *", "20/12/2003 03:30", false); + + // Day of month tests + + CronCall("07/01/2003 00:00", "30 * 1 * *", "01/02/2003 00:30", false); + CronCall("01/02/2003 00:30", "30 * 1 * *", "01/02/2003 01:30", false); + + CronCall("01/01/2003 00:00", "10 * 22 * *", "22/01/2003 00:10", false); + CronCall("01/01/2003 00:00", "30 23 19 * *", "19/01/2003 23:30", false); + CronCall("01/01/2003 00:00", "30 23 21 * *", "21/01/2003 23:30", false); + CronCall("01/01/2003 00:01", " * * 21 * *", "21/01/2003 00:00", false); + CronCall("10/07/2003 00:00", " * * 30,31 * *", "30/07/2003 00:00", false); + + // Test month rollovers for months with 28,29,30 and 31 days + + CronCall("28/02/2002 23:59", "* * * 3 *", "01/03/2002 00:00", false); + CronCall("29/02/2004 23:59", "* * * 3 *", "01/03/2004 00:00", false); + CronCall("31/03/2002 23:59", "* * * 4 *", "01/04/2002 00:00", false); + CronCall("30/04/2002 23:59", "* * * 5 *", "01/05/2002 00:00", false); + + // Test month 30,31 days + + CronCall("01/01/2000 00:00", "0 0 15,30,31 * *", "15/01/2000 00:00", false); + CronCall("15/01/2000 00:00", "0 0 15,30,31 * *", "30/01/2000 00:00", false); + CronCall("30/01/2000 00:00", "0 0 15,30,31 * *", "31/01/2000 00:00", false); + CronCall("31/01/2000 00:00", "0 0 15,30,31 * *", "15/02/2000 00:00", false); + + CronCall("15/02/2000 00:00", "0 0 15,30,31 * *", "15/03/2000 00:00", false); + + CronCall("15/03/2000 00:00", "0 0 15,30,31 * *", "30/03/2000 00:00", false); + CronCall("30/03/2000 00:00", "0 0 15,30,31 * *", "31/03/2000 00:00", false); + CronCall("31/03/2000 00:00", "0 0 15,30,31 * *", "15/04/2000 00:00", false); + + CronCall("15/04/2000 00:00", "0 0 15,30,31 * *", "30/04/2000 00:00", false); + CronCall("30/04/2000 00:00", "0 0 15,30,31 * *", "15/05/2000 00:00", false); + + CronCall("15/05/2000 00:00", "0 0 15,30,31 * *", "30/05/2000 00:00", false); + CronCall("30/05/2000 00:00", "0 0 15,30,31 * *", "31/05/2000 00:00", false); + CronCall("31/05/2000 00:00", "0 0 15,30,31 * *", "15/06/2000 00:00", false); + + CronCall("15/06/2000 00:00", "0 0 15,30,31 * *", "30/06/2000 00:00", false); + CronCall("30/06/2000 00:00", "0 0 15,30,31 * *", "15/07/2000 00:00", false); + + CronCall("15/07/2000 00:00", "0 0 15,30,31 * *", "30/07/2000 00:00", false); + CronCall("30/07/2000 00:00", "0 0 15,30,31 * *", "31/07/2000 00:00", false); + CronCall("31/07/2000 00:00", "0 0 15,30,31 * *", "15/08/2000 00:00", false); + + CronCall("15/08/2000 00:00", "0 0 15,30,31 * *", "30/08/2000 00:00", false); + CronCall("30/08/2000 00:00", "0 0 15,30,31 * *", "31/08/2000 00:00", false); + CronCall("31/08/2000 00:00", "0 0 15,30,31 * *", "15/09/2000 00:00", false); + + CronCall("15/09/2000 00:00", "0 0 15,30,31 * *", "30/09/2000 00:00", false); + CronCall("30/09/2000 00:00", "0 0 15,30,31 * *", "15/10/2000 00:00", false); + + CronCall("15/10/2000 00:00", "0 0 15,30,31 * *", "30/10/2000 00:00", false); + CronCall("30/10/2000 00:00", "0 0 15,30,31 * *", "31/10/2000 00:00", false); + CronCall("31/10/2000 00:00", "0 0 15,30,31 * *", "15/11/2000 00:00", false); + + CronCall("15/11/2000 00:00", "0 0 15,30,31 * *", "30/11/2000 00:00", false); + CronCall("30/11/2000 00:00", "0 0 15,30,31 * *", "15/12/2000 00:00", false); + + CronCall("15/12/2000 00:00", "0 0 15,30,31 * *", "30/12/2000 00:00", false); + CronCall("30/12/2000 00:00", "0 0 15,30,31 * *", "31/12/2000 00:00", false); + CronCall("31/12/2000 00:00", "0 0 15,30,31 * *", "15/01/2001 00:00", false); + + // Other month tests (including year rollover) + + CronCall("01/12/2003 05:00", "10 * * 6 *", "01/06/2004 00:10", false); + CronCall("04/01/2003 00:00", " 1 2 3 * *", "03/02/2003 02:01", false); + CronCall("01/07/2002 05:00", "10 * * February,April-Jun *", "01/02/2003 00:10", false); + CronCall("01/01/2003 00:00", "0 12 1 6 *", "01/06/2003 12:00", false); + CronCall("11/09/1988 14:23", "* 12 1 6 *", "01/06/1989 12:00", false); + CronCall("11/03/1988 14:23", "* 12 1 6 *", "01/06/1988 12:00", false); + CronCall("11/03/1988 14:23", "* 2,4-8,15 * 6 *", "01/06/1988 02:00", false); + CronCall("11/03/1988 14:23", "20 * * january,FeB,Mar,april,May,JuNE,July,Augu,SEPT-October,Nov,DECEM *", "11/03/1988 15:20", false); + + // Day of week tests + + CronCall("26/06/2003 10:00", "30 6 * * 0", "29/06/2003 06:30", false); + CronCall("26/06/2003 10:00", "30 6 * * sunday", "29/06/2003 06:30", false); + CronCall("26/06/2003 10:00", "30 6 * * SUNDAY", "29/06/2003 06:30", false); + CronCall("19/06/2003 00:00", "1 12 * * 2", "24/06/2003 12:01", false); + CronCall("24/06/2003 12:01", "1 12 * * 2", "01/07/2003 12:01", false); + + CronCall("01/06/2003 14:55", "15 18 * * Mon", "02/06/2003 18:15", false); + CronCall("02/06/2003 18:15", "15 18 * * Mon", "09/06/2003 18:15", false); + CronCall("09/06/2003 18:15", "15 18 * * Mon", "16/06/2003 18:15", false); + CronCall("16/06/2003 18:15", "15 18 * * Mon", "23/06/2003 18:15", false); + CronCall("23/06/2003 18:15", "15 18 * * Mon", "30/06/2003 18:15", false); + CronCall("30/06/2003 18:15", "15 18 * * Mon", "07/07/2003 18:15", false); + + CronCall("01/01/2003 00:00", "* * * * Mon", "06/01/2003 00:00", false); + CronCall("01/01/2003 12:00", "45 16 1 * Mon", "01/09/2003 16:45", false); + CronCall("01/09/2003 23:45", "45 16 1 * Mon", "01/12/2003 16:45", false); + + // Leap year tests + + CronCall("01/01/2000 12:00", "1 12 29 2 *", "29/02/2000 12:01", false); + CronCall("29/02/2000 12:01", "1 12 29 2 *", "29/02/2004 12:01", false); + CronCall("29/02/2004 12:01", "1 12 29 2 *", "29/02/2008 12:01", false); + + // Non-leap year tests + + CronCall("01/01/2000 12:00", "1 12 28 2 *", "28/02/2000 12:01", false); + CronCall("28/02/2000 12:01", "1 12 28 2 *", "28/02/2001 12:01", false); + CronCall("28/02/2001 12:01", "1 12 28 2 *", "28/02/2002 12:01", false); + CronCall("28/02/2002 12:01", "1 12 28 2 *", "28/02/2003 12:01", false); + CronCall("28/02/2003 12:01", "1 12 28 2 *", "28/02/2004 12:01", false); + CronCall("29/02/2004 12:01", "1 12 28 2 *", "28/02/2005 12:01", false); + } + + [ Test ] + public void FiniteOccurrences() + { + CronFinite(" * * * * * ", "01/01/2003 00:00", "01/01/2003 00:00"); + CronFinite(" * * * * * ", "31/12/2002 23:59", "01/01/2003 00:00"); + CronFinite(" * * * * Mon", "31/12/2002 23:59", "01/01/2003 00:00"); + CronFinite(" * * * * Mon", "01/01/2003 00:00", "02/01/2003 00:00"); + CronFinite(" * * * * Mon", "01/01/2003 00:00", "02/01/2003 12:00"); + CronFinite("30 12 * * Mon", "01/01/2003 00:00", "06/01/2003 12:00"); + } + + [ Test, Category("Performance") ] + public void DontLoopIndefinitely() + { + // + // Test to check we don't loop indefinitely looking for a February + // 31st because no such date would ever exist! + // + + TimeCron(TimeSpan.FromSeconds(1), () => + CronFinite("* * 31 Feb *", "01/01/2001 00:00", "01/01/2010 00:00")); + } + + private static void TimeCron(TimeSpan limit, ThreadStart test) + { + Debug.Assert(test != null); + + Exception e = null; + + var worker = new Thread(() => { try { test(); } catch (Exception ee) { e = ee; } }); + + worker.Start(); + + if (worker.Join(!Debugger.IsAttached ? limit.Milliseconds : Timeout.Infinite)) + { + if (e != null) + throw new Exception(e.Message, e); + + return; + } + + worker.Abort(); + + Assert.Fail("The test did not complete in the allocated time ({0}). " + + "Check there is not an infinite loop somewhere.", limit); + } + + private static void CronCall(string startTimeString, string cronExpression, string nextTimeString, bool expectException) + { + var start = Time(startTimeString); + + try + { + var schedule = CrontabSchedule.Parse(cronExpression); + + if (expectException) + Assert.Fail("The expression <{0}> cannot be valid.", cronExpression); + + var next = schedule.GetNextOccurrence(start); + + Assert.AreEqual(nextTimeString, TimeString(next), + "Occurrence of <{0}> after <{1}>.", cronExpression, startTimeString); + } + catch (CrontabException e) + { + if (!expectException) + Assert.Fail("Unexpected ParseException while parsing <{0}>: {1}", cronExpression, e.ToString()); + } + } + + private static void CronFinite(string cronExpression, string startTimeString, string endTimeString) + { + var schedule = CrontabSchedule.Parse(cronExpression); + var occurrence = schedule.GetNextOccurrence(Time(startTimeString), Time(endTimeString)); + + Assert.AreEqual(endTimeString, TimeString(occurrence), + "Occurrence of <{0}> after <{1}> did not terminate with <{2}>.", + cronExpression, startTimeString, endTimeString); + } + + private static string TimeString(DateTime time) + { + return time.ToString(_timeFormat, CultureInfo.InvariantCulture); + } + + private static DateTime Time(string str) + { + return DateTime.ParseExact(str, _timeFormat, CultureInfo.InvariantCulture); + } + } +} \ No newline at end of file diff --git a/src/NCrontab.Tests/NCrontab.Tests.csproj b/src/NCrontab.Tests/NCrontab.Tests.csproj new file mode 100644 index 0000000..1c17ccc --- /dev/null +++ b/src/NCrontab.Tests/NCrontab.Tests.csproj @@ -0,0 +1,61 @@ + + + + Debug + AnyCPU + 9.0.21022 + 2.0 + {7F587D68-75DD-4779-8744-85E9B07EC565} + Library + Properties + NCrontab.Tests + NCrontab.Tests + v2.0 + 512 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + False + ..\lib\nunit.framework.dll + + + + + + SolutionInfo.cs + + + + + + + {1948D266-8DCB-4AC5-98E6-A609713011CB} + NCrontab + + + + + \ No newline at end of file diff --git a/src/NCrontab.Tests/Properties/AssemblyInfo.cs b/src/NCrontab.Tests/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..beca47b --- /dev/null +++ b/src/NCrontab.Tests/Properties/AssemblyInfo.cs @@ -0,0 +1,34 @@ +#region License, Terms and Author(s) +// +// NCrontab - Crontab for .NET +// Copyright (c) 2008 Atif Aziz. All rights reserved. +// +// Author(s): +// +// Atif Aziz, http://www.raboof.com +// +// This library is free software; you can redistribute it and/or modify it +// under the terms of the New BSD License, a copy of which should have +// been delivered along with this distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +#endregion + +using System.Reflection; + +[assembly: AssemblyTitle("NCrontab.Tests")] +[assembly: AssemblyDescription("NUnit tests for NCrontab")] + +[assembly: AssemblyVersion("0.2.0.*")] +[assembly: AssemblyFileVersion("0.2.0.*")] diff --git a/src/NCrontab.sln b/src/NCrontab.sln new file mode 100644 index 0000000..aa34351 --- /dev/null +++ b/src/NCrontab.sln @@ -0,0 +1,43 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NCrontab", "NCrontab\NCrontab.csproj", "{1948D266-8DCB-4AC5-98E6-A609713011CB}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NCrontabConsole", "CrontabConsole\NCrontabConsole.csproj", "{89D84924-0952-40FC-8994-758C4215ABEB}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NCrontab.Tests", "NCrontab.Tests\NCrontab.Tests.csproj", "{7F587D68-75DD-4779-8744-85E9B07EC565}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NCrontabViewer", "CrontabViewer\NCrontabViewer.csproj", "{02F42DAC-8A9F-45BB-B734-BB08F0D194C4}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{A4109292-0FE5-4761-868A-31A5BEB1810A}" + ProjectSection(SolutionItems) = preProject + SolutionInfo.cs = SolutionInfo.cs + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {1948D266-8DCB-4AC5-98E6-A609713011CB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1948D266-8DCB-4AC5-98E6-A609713011CB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1948D266-8DCB-4AC5-98E6-A609713011CB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1948D266-8DCB-4AC5-98E6-A609713011CB}.Release|Any CPU.Build.0 = Release|Any CPU + {89D84924-0952-40FC-8994-758C4215ABEB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {89D84924-0952-40FC-8994-758C4215ABEB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {89D84924-0952-40FC-8994-758C4215ABEB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {89D84924-0952-40FC-8994-758C4215ABEB}.Release|Any CPU.Build.0 = Release|Any CPU + {7F587D68-75DD-4779-8744-85E9B07EC565}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7F587D68-75DD-4779-8744-85E9B07EC565}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7F587D68-75DD-4779-8744-85E9B07EC565}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7F587D68-75DD-4779-8744-85E9B07EC565}.Release|Any CPU.Build.0 = Release|Any CPU + {02F42DAC-8A9F-45BB-B734-BB08F0D194C4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {02F42DAC-8A9F-45BB-B734-BB08F0D194C4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {02F42DAC-8A9F-45BB-B734-BB08F0D194C4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {02F42DAC-8A9F-45BB-B734-BB08F0D194C4}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/src/NCrontab/AssemblyInfo.cs b/src/NCrontab/AssemblyInfo.cs new file mode 100644 index 0000000..26a9caf --- /dev/null +++ b/src/NCrontab/AssemblyInfo.cs @@ -0,0 +1,41 @@ +#region License, Terms and Author(s) +// +// NCrontab - Crontab for .NET +// Copyright (c) 2008 Atif Aziz. All rights reserved. +// +// Author(s): +// +// Atif Aziz, http://www.raboof.com +// +// This library is free software; you can redistribute it and/or modify it +// under the terms of the New BSD License, a copy of which should have +// been delivered along with this distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +#endregion + +#region Imports + +using System.Reflection; +using CLSCompliantAttribute = System.CLSCompliantAttribute; + +#endregion + +[assembly: AssemblyTitle("NCrontab")] +[assembly: AssemblyDescription("Crontab for .NET")] + +[assembly: AssemblyVersion("0.2.10124.0")] +[assembly: AssemblyFileVersion("0.2.10124.1211")] + +[assembly: CLSCompliant(true)] diff --git a/src/NCrontab/CrontabException.cs b/src/NCrontab/CrontabException.cs new file mode 100644 index 0000000..45330f1 --- /dev/null +++ b/src/NCrontab/CrontabException.cs @@ -0,0 +1,52 @@ +#region License, Terms and Author(s) +// +// NCrontab - Crontab for .NET +// Copyright (c) 2008 Atif Aziz. All rights reserved. +// +// Author(s): +// +// Atif Aziz, http://www.raboof.com +// +// This library is free software; you can redistribute it and/or modify it +// under the terms of the New BSD License, a copy of which should have +// been delivered along with this distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +#endregion + +namespace NCrontab +{ + #region Imports + + using System; + using System.Runtime.Serialization; + + #endregion + + [ Serializable ] + public class CrontabException : Exception + { + public CrontabException() : + base("Crontab error.") {} // TODO: Fix message and add it to resource. + + public CrontabException(string message) : + base(message) {} + + public CrontabException(string message, Exception innerException) : + base(message, innerException) {} + + protected CrontabException(SerializationInfo info, StreamingContext context) : + base(info, context) {} + } +} \ No newline at end of file diff --git a/src/NCrontab/CrontabField.cs b/src/NCrontab/CrontabField.cs new file mode 100644 index 0000000..02717e8 --- /dev/null +++ b/src/NCrontab/CrontabField.cs @@ -0,0 +1,325 @@ +#region License, Terms and Author(s) +// +// NCrontab - Crontab for .NET +// Copyright (c) 2008 Atif Aziz. All rights reserved. +// +// Author(s): +// +// Atif Aziz, http://www.raboof.com +// +// This library is free software; you can redistribute it and/or modify it +// under the terms of the New BSD License, a copy of which should have +// been delivered along with this distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +#endregion + +namespace NCrontab +{ + #region Imports + + using System; + using System.Collections; + using System.Globalization; + using System.IO; + + #endregion + + /// + /// Represents a single crontab field. + /// + + [ Serializable ] + public sealed class CrontabField : ICrontabField + { + private readonly BitArray _bits; + private /* readonly */ int _minValueSet; + private /* readonly */ int _maxValueSet; + private readonly CrontabFieldImpl _impl; + + /// + /// Parses a crontab field expression given its kind. + /// + + public static CrontabField Parse(CrontabFieldKind kind, string expression) + { + return new CrontabField(CrontabFieldImpl.FromKind(kind), expression); + } + + /// + /// Parses a crontab field expression representing minutes. + /// + + public static CrontabField Minutes(string expression) + { + return new CrontabField(CrontabFieldImpl.Minute, expression); + } + + /// + /// Parses a crontab field expression representing hours. + /// + + public static CrontabField Hours(string expression) + { + return new CrontabField(CrontabFieldImpl.Hour, expression); + } + + /// + /// Parses a crontab field expression representing days in any given month. + /// + + public static CrontabField Days(string expression) + { + return new CrontabField(CrontabFieldImpl.Day, expression); + } + + /// + /// Parses a crontab field expression representing months. + /// + + public static CrontabField Months(string expression) + { + return new CrontabField(CrontabFieldImpl.Month, expression); + } + + /// + /// Parses a crontab field expression representing days of a week. + /// + + public static CrontabField DaysOfWeek(string expression) + { + return new CrontabField(CrontabFieldImpl.DayOfWeek, expression); + } + + private CrontabField(CrontabFieldImpl impl, string expression) + { + if (impl == null) + throw new ArgumentNullException("impl"); + + _impl = impl; + _bits = new BitArray(impl.ValueCount); + + _bits.SetAll(false); + _minValueSet = int.MaxValue; + _maxValueSet = -1; + + _impl.Parse(expression, Accumulate); + } + + /// + /// Gets the first value of the field or -1. + /// + + public int GetFirst() + { + return _minValueSet < int.MaxValue ? _minValueSet : -1; + } + + /// + /// Gets the next value of the field that occurs after the given + /// start value or -1 if there is no next value available. + /// + + public int Next(int start) + { + if (start < _minValueSet) + return _minValueSet; + + var startIndex = ValueToIndex(start); + var lastIndex = ValueToIndex(_maxValueSet); + + for (var i = startIndex; i <= lastIndex; i++) + { + if (_bits[i]) + return IndexToValue(i); + } + + return -1; + } + + private int IndexToValue(int index) + { + return index + _impl.MinValue; + } + + private int ValueToIndex(int value) + { + return value - _impl.MinValue; + } + + /// + /// Determines if the given value occurs in the field. + /// + + public bool Contains(int value) + { + return _bits[ValueToIndex(value)]; + } + + /// + /// Accumulates the given range (start to end) and interval of values + /// into the current set of the field. + /// + /// + /// To set the entire range of values representable by the field, + /// set and to -1 and + /// to 1. + /// + + private void Accumulate(int start, int end, int interval) + { + var minValue = _impl.MinValue; + var maxValue = _impl.MaxValue; + + if (start == end) + { + if (start < 0) + { + // + // We're setting the entire range of values. + // + + if (interval <= 1) + { + _minValueSet = minValue; + _maxValueSet = maxValue; + _bits.SetAll(true); + return; + } + + start = minValue; + end = maxValue; + } + else + { + // + // We're only setting a single value - check that it is in range. + // + + if (start < minValue) + { + throw new CrontabException(string.Format( + "'{0} is lower than the minimum allowable value for this field. Value must be between {1} and {2} (all inclusive).", + start, _impl.MinValue, _impl.MaxValue)); + } + + if (start > maxValue) + { + throw new CrontabException(string.Format( + "'{0} is higher than the maximum allowable value for this field. Value must be between {1} and {2} (all inclusive).", + end, _impl.MinValue, _impl.MaxValue)); + } + } + } + else + { + // + // For ranges, if the start is bigger than the end value then + // swap them over. + // + + if (start > end) + { + end ^= start; + start ^= end; + end ^= start; + } + + if (start < 0) + { + start = minValue; + } + else if (start < minValue) + { + throw new CrontabException(string.Format( + "'{0} is lower than the minimum allowable value for this field. Value must be between {1} and {2} (all inclusive).", + start, _impl.MinValue, _impl.MaxValue)); + } + + if (end < 0) + { + end = maxValue; + } + else if (end > maxValue) + { + throw new CrontabException(string.Format( + "'{0} is higher than the maximum allowable value for this field. Value must be between {1} and {2} (all inclusive).", + end, _impl.MinValue, _impl.MaxValue)); + } + } + + if (interval < 1) + interval = 1; + + int i; + + // + // Populate the _bits table by setting all the bits corresponding to + // the valid field values. + // + + for (i = start - minValue; i <= (end - minValue); i += interval) + _bits[i] = true; + + // + // Make sure we remember the minimum value set so far Keep track of + // the highest and lowest values that have been added to this field + // so far. + // + + if (_minValueSet > start) + _minValueSet = start; + + i += (minValue - interval); + + if (_maxValueSet < i) + _maxValueSet = i; + } + + public override string ToString() + { + return ToString(null); + } + + public string ToString(string format) + { + var writer = new StringWriter(CultureInfo.InvariantCulture); + + switch (format) + { + case "G": + case null: + Format(writer, true); + break; + case "N": + Format(writer); + break; + default: + throw new FormatException(); + } + + return writer.ToString(); + } + + public void Format(TextWriter writer) + { + Format(writer, false); + } + + public void Format(TextWriter writer, bool noNames) + { + _impl.Format(this, writer, noNames); + } + } +} diff --git a/src/NCrontab/CrontabFieldImpl.cs b/src/NCrontab/CrontabFieldImpl.cs new file mode 100644 index 0000000..5fcfe7d --- /dev/null +++ b/src/NCrontab/CrontabFieldImpl.cs @@ -0,0 +1,344 @@ +#region License, Terms and Author(s) +// +// NCrontab - Crontab for .NET +// Copyright (c) 2008 Atif Aziz. All rights reserved. +// +// Author(s): +// +// Atif Aziz, http://www.raboof.com +// +// This library is free software; you can redistribute it and/or modify it +// under the terms of the New BSD License, a copy of which should have +// been delivered along with this distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +#endregion + + +namespace NCrontab +{ + #region Imports + + using System; + using System.Collections.Generic; + using System.Collections.ObjectModel; + using System.Globalization; + using System.IO; + using System.Runtime.Serialization; + using Debug = System.Diagnostics.Debug; + + #endregion + + public delegate void CrontabFieldAccumulator(int start, int end, int interval); + + [ Serializable ] + public sealed class CrontabFieldImpl : IObjectReference + { + public static readonly CrontabFieldImpl Minute = new CrontabFieldImpl(CrontabFieldKind.Minute, 0, 59, null); + public static readonly CrontabFieldImpl Hour = new CrontabFieldImpl(CrontabFieldKind.Hour, 0, 23, null); + public static readonly CrontabFieldImpl Day = new CrontabFieldImpl(CrontabFieldKind.Day, 1, 31, null); + public static readonly CrontabFieldImpl Month = new CrontabFieldImpl(CrontabFieldKind.Month, 1, 12, new[] { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" }); + public static readonly CrontabFieldImpl DayOfWeek = new CrontabFieldImpl(CrontabFieldKind.DayOfWeek, 0, 6, new[] { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" }); + + private static readonly CrontabFieldImpl[] _fieldByKind = new[] { Minute, Hour, Day, Month, DayOfWeek }; + + private static readonly CompareInfo _comparer = CultureInfo.InvariantCulture.CompareInfo; + private static readonly char[] _comma = new[] { ',' }; + + private readonly CrontabFieldKind _kind; + private readonly int _minValue; + private readonly int _maxValue; + private readonly string[] _names; + + public static CrontabFieldImpl FromKind(CrontabFieldKind kind) + { + if (!Enum.IsDefined(typeof(CrontabFieldKind), kind)) + { + throw new ArgumentException(string.Format( + "Invalid crontab field kind. Valid values are {0}.", + string.Join(", ", Enum.GetNames(typeof(CrontabFieldKind)))), "kind"); + } + + return _fieldByKind[(int) kind]; + } + + private CrontabFieldImpl(CrontabFieldKind kind, int minValue, int maxValue, string[] names) + { + Debug.Assert(Enum.IsDefined(typeof(CrontabFieldKind), kind)); + Debug.Assert(minValue >= 0); + Debug.Assert(maxValue >= minValue); + Debug.Assert(names == null || names.Length == (maxValue - minValue + 1)); + + _kind = kind; + _minValue = minValue; + _maxValue = maxValue; + _names = names; + } + + public CrontabFieldKind Kind + { + get { return _kind; } + } + + public int MinValue + { + get { return _minValue; } + } + + public int MaxValue + { + get { return _maxValue; } + } + + public int ValueCount + { + get { return _maxValue - _minValue + 1; } + } + + public void Format(ICrontabField field, TextWriter writer) + { + Format(field, writer, false); + } + + public void Format(ICrontabField field, TextWriter writer, bool noNames) + { + if (field == null) + throw new ArgumentNullException("field"); + + if (writer == null) + throw new ArgumentNullException("writer"); + + var next = field.GetFirst(); + var count = 0; + + while (next != -1) + { + var first = next; + int last; + + do + { + last = next; + next = field.Next(last + 1); + } + while (next - last == 1); + + if (count == 0 + && first == _minValue && last == _maxValue) + { + writer.Write('*'); + return; + } + + if (count > 0) + writer.Write(','); + + if (first == last) + { + FormatValue(first, writer, noNames); + } + else + { + FormatValue(first, writer, noNames); + writer.Write('-'); + FormatValue(last, writer, noNames); + } + + count++; + } + } + + private void FormatValue(int value, TextWriter writer, bool noNames) + { + Debug.Assert(writer != null); + + if (noNames || _names == null) + { + if (value >= 0 && value < 100) + { + FastFormatNumericValue(value, writer); + } + else + { + writer.Write(value.ToString(CultureInfo.InvariantCulture)); + } + } + else + { + var index = value - _minValue; + writer.Write(_names[index]); + } + } + + private static void FastFormatNumericValue(int value, TextWriter writer) + { + Debug.Assert(value >= 0 && value < 100); + Debug.Assert(writer != null); + + if (value >= 10) + { + writer.Write((char) ('0' + (value / 10))); + writer.Write((char) ('0' + (value % 10))); + } + else + { + writer.Write((char) ('0' + value)); + } + } + + public void Parse(string str, CrontabFieldAccumulator acc) + { + if (acc == null) + throw new ArgumentNullException("acc"); + + if (string.IsNullOrEmpty(str)) + return; + + try + { + InternalParse(str, acc); + } + catch (FormatException e) + { + ThrowParseException(e, str); + } + catch (CrontabException e) + { + ThrowParseException(e, str); + } + } + + private static void ThrowParseException(Exception innerException, string str) + { + Debug.Assert(str != null); + Debug.Assert(innerException != null); + + throw new CrontabException(string.Format("'{0}' is not a valid crontab field expression.", str), innerException); + } + + private void InternalParse(string str, CrontabFieldAccumulator acc) + { + Debug.Assert(str != null); + Debug.Assert(acc != null); + + if (str.Length == 0) + throw new CrontabException("A crontab field value cannot be empty."); + + // + // Next, look for a list of values (e.g. 1,2,3). + // + + var commaIndex = str.IndexOf(","); + + if (commaIndex > 0) + { + foreach (var token in str.Split(_comma)) + InternalParse(token, acc); + } + else + { + var every = 1; + + // + // Look for stepping first (e.g. */2 = every 2nd). + // + + var slashIndex = str.IndexOf("/"); + + if (slashIndex > 0) + { + every = int.Parse(str.Substring(slashIndex + 1), CultureInfo.InvariantCulture); + str = str.Substring(0, slashIndex); + } + + // + // Next, look for wildcard (*). + // + + if (str.Length == 1 && str[0]== '*') + { + acc(-1, -1, every); + return; + } + + // + // Next, look for a range of values (e.g. 2-10). + // + + var dashIndex = str.IndexOf("-"); + + if (dashIndex > 0) + { + var first = ParseValue(str.Substring(0, dashIndex)); + var last = ParseValue(str.Substring(dashIndex + 1)); + + acc(first, last, every); + return; + } + + // + // Finally, handle the case where there is only one number. + // + + var value = ParseValue(str); + + if (every == 1) + { + acc(value, value, 1); + } + else + { + Debug.Assert(every != 0); + + acc(value, _maxValue, every); + } + } + } + + private int ParseValue(string str) + { + Debug.Assert(str != null); + + if (str.Length == 0) + throw new CrontabException("A crontab field value cannot be empty."); + + var firstChar = str[0]; + + if (firstChar >= '0' && firstChar <= '9') + return int.Parse(str, CultureInfo.InvariantCulture); + + if (_names == null) + { + throw new CrontabException(string.Format( + "'{0}' is not a valid value for this crontab field. It must be a numeric value between {1} and {2} (all inclusive).", + str, _minValue.ToString(), _maxValue.ToString())); + } + + for (var i = 0; i < _names.Length; i++) + { + if (_comparer.IsPrefix(_names[i], str, CompareOptions.IgnoreCase)) + return i + _minValue; + } + + throw new CrontabException(string.Format( + "'{0}' is not a known value name. Use one of the following: {1}.", + str, string.Join(", ", _names))); + } + + object IObjectReference.GetRealObject(StreamingContext context) + { + return FromKind(Kind); + } + } +} diff --git a/src/NCrontab/CrontabFieldKind.cs b/src/NCrontab/CrontabFieldKind.cs new file mode 100644 index 0000000..0076825 --- /dev/null +++ b/src/NCrontab/CrontabFieldKind.cs @@ -0,0 +1,41 @@ +#region License, Terms and Author(s) +// +// NCrontab - Crontab for .NET +// Copyright (c) 2008 Atif Aziz. All rights reserved. +// +// Author(s): +// +// Atif Aziz, http://www.raboof.com +// +// This library is free software; you can redistribute it and/or modify it +// under the terms of the New BSD License, a copy of which should have +// been delivered along with this distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +#endregion + +namespace NCrontab +{ + using System; + + [ Serializable ] + public enum CrontabFieldKind + { + Minute, + Hour, + Day, + Month, + DayOfWeek + } +} \ No newline at end of file diff --git a/src/NCrontab/CrontabSchedule.cs b/src/NCrontab/CrontabSchedule.cs new file mode 100644 index 0000000..24fb3fb --- /dev/null +++ b/src/NCrontab/CrontabSchedule.cs @@ -0,0 +1,272 @@ +#region License, Terms and Author(s) +// +// NCrontab - Crontab for .NET +// Copyright (c) 2008 Atif Aziz. All rights reserved. +// +// Author(s): +// +// Atif Aziz, http://www.raboof.com +// +// This library is free software; you can redistribute it and/or modify it +// under the terms of the New BSD License, a copy of which should have +// been delivered along with this distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +#endregion + +namespace NCrontab +{ + #region Imports + + using System; + using System.Collections.Generic; + using System.Globalization; + using System.IO; + using Debug = System.Diagnostics.Debug; + + #endregion + + /// + /// Represents a schedule initialized from the crontab expression. + /// + + [ Serializable ] + public sealed class CrontabSchedule + { + private readonly CrontabField _minutes; + private readonly CrontabField _hours; + private readonly CrontabField _days; + private readonly CrontabField _months; + private readonly CrontabField _daysOfWeek; + + private static readonly char[] _separators = new[] {' '}; + + // + // Crontab expression format: + // + // * * * * * + // - - - - - + // | | | | | + // | | | | +----- day of week (0 - 6) (Sunday=0) + // | | | +------- month (1 - 12) + // | | +--------- day of month (1 - 31) + // | +----------- hour (0 - 23) + // +------------- min (0 - 59) + // + // Star (*) in the value field above means all legal values as in + // braces for that column. The value column can have a * or a list + // of elements separated by commas. An element is either a number in + // the ranges shown above or two numbers in the range separated by a + // hyphen (meaning an inclusive range). + // + // Source: http://www.adminschoice.com/docs/crontab.htm + // + + public static CrontabSchedule Parse(string expression) + { + if (expression == null) + throw new ArgumentNullException("expression"); + + return new CrontabSchedule(expression); + } + + private CrontabSchedule(string expression) + { + Debug.Assert(expression != null); + + var fields = expression.Split(_separators, StringSplitOptions.RemoveEmptyEntries); + + if (fields.Length != 5) + { + throw new CrontabException(string.Format( + "'{0}' is not a valid crontab expression. It must contain at least 5 components of a schedule " + + "(in the sequence of minutes, hours, days, months, days of week).", + expression)); + } + + _minutes = CrontabField.Minutes(fields[0]); + _hours = CrontabField.Hours(fields[1]); + _days = CrontabField.Days(fields[2]); + _months = CrontabField.Months(fields[3]); + _daysOfWeek = CrontabField.DaysOfWeek(fields[4]); + } + + public IEnumerable GetNextOccurrences(DateTime baseTime, DateTime endTime) + { + for (var occurrence = GetNextOccurrence(baseTime, endTime); + occurrence < endTime; + occurrence = GetNextOccurrence(occurrence, endTime)) + { + yield return occurrence; + } + } + + public DateTime GetNextOccurrence(DateTime baseTime) + { + return GetNextOccurrence(baseTime, DateTime.MaxValue); + } + + public DateTime GetNextOccurrence(DateTime baseTime, DateTime endTime) + { + const int nil = -1; + + var baseYear = baseTime.Year; + var baseMonth = baseTime.Month; + var baseDay = baseTime.Day; + var baseHour = baseTime.Hour; + var baseMinute = baseTime.Minute; + + var endYear = endTime.Year; + var endMonth = endTime.Month; + var endDay = endTime.Day; + + var year = baseYear; + var month = baseMonth; + var day = baseDay; + var hour = baseHour; + var minute = baseMinute + 1; + + // + // Minute + // + + minute = _minutes.Next(minute); + + if (minute == nil) + { + minute = _minutes.GetFirst(); + hour++; + } + + // + // Hour + // + + hour = _hours.Next(hour); + + if (hour == nil) + { + minute = _minutes.GetFirst(); + hour = _hours.GetFirst(); + day++; + } + else if (hour > baseHour) + { + minute = _minutes.GetFirst(); + } + + // + // Day + // + + day = _days.Next(day); + + RetryDayMonth: + + if (day == nil) + { + minute = _minutes.GetFirst(); + hour = _hours.GetFirst(); + day = _days.GetFirst(); + month++; + } + else if (day > baseDay) + { + minute = _minutes.GetFirst(); + hour = _hours.GetFirst(); + } + + // + // Month + // + + month = _months.Next(month); + + if (month == nil) + { + minute = _minutes.GetFirst(); + hour = _hours.GetFirst(); + day = _days.GetFirst(); + month = _months.GetFirst(); + year++; + } + else if (month > baseMonth) + { + minute = _minutes.GetFirst(); + hour = _hours.GetFirst(); + day = _days.GetFirst(); + } + + // + // The day field in a cron expression spans the entire range of days + // in a month, which is from 1 to 31. However, the number of days in + // a month tend to be variable depending on the month (and the year + // in case of February). So a check is needed here to see if the + // date is a border case. If the day happens to be beyond 28 + // (meaning that we're dealing with the suspicious range of 29-31) + // and the date part has changed then we need to determine whether + // the day still makes sense for the given year and month. If the + // day is beyond the last possible value, then the day/month part + // for the schedule is re-evaluated. So an expression like "0 0 + // 15,31 * *" will yield the following sequence starting on midnight + // of Jan 1, 2000: + // + // Jan 15, Jan 31, Feb 15, Mar 15, Apr 15, Apr 31, ... + // + + var dateChanged = day != baseDay || month != baseMonth || year != baseYear; + + if (day > 28 && dateChanged && day > Calendar.GetDaysInMonth(year, month)) + { + if (year >= endYear && month >= endMonth && day >= endDay) + return endTime; + + day = nil; + goto RetryDayMonth; + } + + var nextTime = new DateTime(year, month, day, hour, minute, 0, 0, baseTime.Kind); + + if (nextTime >= endTime) + return endTime; + + // + // Day of week + // + + if (_daysOfWeek.Contains((int) nextTime.DayOfWeek)) + return nextTime; + + return GetNextOccurrence(new DateTime(year, month, day, 23, 59, 0, 0, baseTime.Kind), endTime); + } + + public override string ToString() + { + var writer = new StringWriter(CultureInfo.InvariantCulture); + + _minutes.Format(writer, true); writer.Write(' '); + _hours.Format(writer, true); writer.Write(' '); + _days.Format(writer, true); writer.Write(' '); + _months.Format(writer, true); writer.Write(' '); + _daysOfWeek.Format(writer, true); + + return writer.ToString(); + } + + private static Calendar Calendar + { + get { return CultureInfo.InvariantCulture.Calendar; } + } + } +} diff --git a/src/NCrontab/ICrontabField.cs b/src/NCrontab/ICrontabField.cs new file mode 100644 index 0000000..5efcaf4 --- /dev/null +++ b/src/NCrontab/ICrontabField.cs @@ -0,0 +1,36 @@ +#region License, Terms and Author(s) +// +// NCrontab - Crontab for .NET +// Copyright (c) 2008 Atif Aziz. All rights reserved. +// +// Author(s): +// +// Atif Aziz, http://www.raboof.com +// +// This library is free software; you can redistribute it and/or modify it +// under the terms of the New BSD License, a copy of which should have +// been delivered along with this distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +#endregion + +namespace NCrontab +{ + public interface ICrontabField + { + int GetFirst(); + int Next(int start); + bool Contains(int value); + } +} \ No newline at end of file diff --git a/src/NCrontab/NCrontab.csproj b/src/NCrontab/NCrontab.csproj new file mode 100644 index 0000000..e39ea6d --- /dev/null +++ b/src/NCrontab/NCrontab.csproj @@ -0,0 +1,147 @@ + + + Local + 9.0.21022 + 2.0 + {1948D266-8DCB-4AC5-98E6-A609713011CB} + Debug + AnyCPU + + + + + NCrontab + + + JScript + Grid + IE50 + false + Library + NCrontab + OnBuildSuccess + + + + + + + 2.0 + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + ..\..\bin\Debug\ + false + 285212672 + false + + + DEBUG;TRACE + + + true + 4096 + false + + + false + false + false + false + 4 + full + prompt + + + ..\..\bin\Release\ + false + 285212672 + false + + + TRACE + + + false + 4096 + false + + + true + false + false + false + 4 + none + prompt + + + + System + + + + + + + SolutionInfo.cs + + + Code + + + Code + + + Code + + + Code + + + + Code + + + Code + + + + + False + .NET Framework 2.0 %28x86%29 + true + + + False + .NET Framework 3.0 %28x86%29 + false + + + False + .NET Framework 3.5 + false + + + + + + + + + + \ No newline at end of file diff --git a/src/SolutionInfo.cs b/src/SolutionInfo.cs new file mode 100644 index 0000000..c1f5951 --- /dev/null +++ b/src/SolutionInfo.cs @@ -0,0 +1,49 @@ +#region License, Terms and Author(s) +// +// NCrontab - Crontab for .NET +// Copyright (c) 2008 Atif Aziz. All rights reserved. +// +// Author(s): +// +// Atif Aziz, http://www.raboof.com +// +// This library is free software; you can redistribute it and/or modify it +// under the terms of the New BSD License, a copy of which should have +// been delivered along with this distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +#endregion + +#region Imports + +using System.Reflection; + +using ComVisible = System.Runtime.InteropServices.ComVisibleAttribute; + +#endregion + +[assembly: AssemblyProduct("NCrontab")] + +[assembly: AssemblyCopyright("Copyright (c) 2008, Atif Aziz. All rights reserved.")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +#if DEBUG +[assembly: AssemblyConfiguration("DEBUG")] +#else +[assembly: AssemblyConfiguration("RELEASE")] +#endif + +[assembly: ComVisible(false)]