예제 #1
0
        private void ProcessComparisonResults(
            DataComparerResults results,
            int pkCompareResult,
            IDataReader expectedData,
            IDataReader actualData,
            ref bool expectedReaderHasMoreData,
            ref bool actualReaderHasMoreData,
            IDictionary <string, bool> additionalFieldsToIgnore)
        {
            switch (Math.Sign(pkCompareResult))
            {
            case -1:

                // Missing row in actuals
                HandleMissingActualRow(expectedData, results);
                expectedReaderHasMoreData = ReadDataReader(expectedData);
                break;

            case 0:

                // Row matches as expected, advance both readers
                HandleSameRow(expectedData, actualData, results, additionalFieldsToIgnore);
                expectedReaderHasMoreData = ReadDataReader(expectedData);
                actualReaderHasMoreData   = ReadDataReader(actualData);
                break;

            case 1:

                // Unexpected row in actuals
                HandleUnexpectedActualsRow(actualData, results);
                actualReaderHasMoreData = ReadDataReader(actualData);
                break;
            }
        }
예제 #2
0
        private void HandleSameRow(
            IDataReader expectedReader,
            IDataReader actualsReader,
            DataComparerResults results,
            IDictionary <string, bool> additionalFieldsToIgnore)
        {
            DataComparerRowResults rowResults = null;

            // Iterate through all the fields, comparing values
            for (int i = 0; i < actualsReader.FieldCount; i++)
            {
                string fieldName = actualsReader.GetName(i);

                if (ShouldSkipFieldValueComparison(fieldName, additionalFieldsToIgnore))
                {
                    continue;
                }

                // Get the expected value
                int expectedOrdinal = GetExpectedOrdinal(expectedReader, fieldName);

                if (expectedOrdinal < 0)
                {
                    _logger.WarnFormat("Expected row does not have column '{0}'", fieldName);
                    continue;
                }

                object expectedValue = expectedReader.GetValue(expectedOrdinal);

                object actualValue = actualsReader.GetValue(i);

                if (!expectedValue.Equals(actualValue))
                {
                    // Make sure row results object is created
                    if (rowResults == null)
                    {
                        rowResults = new DataComparerRowResults(DataComparerRowDifference.ValuesDiffer);
                    }

                    rowResults.ExpectedValues[fieldName] = MakeSerializable(expectedValue);
                    rowResults.ActualValues[fieldName]   = MakeSerializable(actualValue);
                }
            }

            if (rowResults != null)
            {
                CollectPrimaryKeyValues(actualsReader, rowResults.KeyValues);
                results.RowDifferences.Add(rowResults);

                // Add difference to the DataTables as well...
                if (dataCopyMode == DataCopyMode.DifferencesOnly)
                {
                    AddDataRowToTable(expectedReader, tablesByReader[expectedReader]);
                    AddDataRowToTable(actualsReader, tablesByReader[actualsReader]);
                }
            }
        }
예제 #3
0
        private void CompareAndDisposeDataReaders(
            DbDataReaderComparer comparer,
            DataComparerResults dataComparerResults,
            IDataReader actualData,
            IDataReader expectedData,
            IEnumerable <string> additionalColumnNamesToIgnore)
        {
            try
            {
                bool expectedReaderHasMoreData = ReadDataReader(expectedData);
                bool actualReaderHasMoreData   = ReadDataReader(actualData);

                // No data?  Quit now
                if (!actualReaderHasMoreData && !expectedReaderHasMoreData)
                {
                    return;
                }

                Dictionary <string, bool> additionalFieldsToIgnore =
                    GetAdditionalFieldsToIgnoreAsDictionary(additionalColumnNamesToIgnore);

                do
                {
                    // Using primary key values, determine whether readers are on same record, or one is "ahead" of the other
                    int pkCompareResult = CompareCurrentReadersPKValues(
                        comparer,
                        expectedData,
                        actualData,
                        expectedReaderHasMoreData,
                        actualReaderHasMoreData);

                    ProcessComparisonResults(
                        dataComparerResults,
                        pkCompareResult,
                        expectedData,
                        actualData,
                        ref expectedReaderHasMoreData,
                        ref actualReaderHasMoreData,
                        additionalFieldsToIgnore);
                }while ((expectedReaderHasMoreData || actualReaderHasMoreData) &&
                        dataComparerResults.RowDifferences.Count < MaximumDifferences);
            }
            finally
            {
                // Make sure the the data readers are properly disposed
                actualData.Dispose();
                expectedData.Dispose();
            }
        }
예제 #4
0
        private void HandleMissingActualRow(IDataReader expectedReader, DataComparerResults results)
        {
            // Missing actual row
            DataComparerRowResults diff = new DataComparerRowResults(DataComparerRowDifference.RowMissing);

            CollectPrimaryKeyValues(expectedReader, diff.KeyValues);
            CollectRowValues(expectedReader, diff.ExpectedValues);
            results.RowDifferences.Add(diff);

            // Add difference to the DataTable as well...
            if (dataCopyMode == DataCopyMode.DifferencesOnly)
            {
                AddDataRowToTable(expectedReader, tablesByReader[expectedReader]);
            }
        }
예제 #5
0
        private void HandleUnexpectedActualsRow(IDataReader actualsReader, DataComparerResults results)
        {
            // Unexpected actual row
            DataComparerRowResults diff = new DataComparerRowResults(DataComparerRowDifference.UnexpectedRow);

            CollectPrimaryKeyValues(actualsReader, diff.KeyValues);
            CollectRowValues(actualsReader, diff.ActualValues);
            results.RowDifferences.Add(diff);

            // Add difference to the DataTable as well...
            if (dataCopyMode == DataCopyMode.DifferencesOnly)
            {
                AddDataRowToTable(actualsReader, tablesByReader[actualsReader]);
            }
        }
예제 #6
0
        /// <summary>
        /// Compares the contents of two IDataReader instances, ignoring the specified columns, optionally creating DataTables for further inspection of the data.
        /// </summary>
        /// <param name="tableName">The name of the table for which the data comparison was performed.</param>
        /// <param name="expectedData">A <see cref="IDataReader"/> containing the expected data.</param>
        /// <param name="actualData">A <see cref="IDataReader"/> containing the actual data.</param>
        /// <param name="uniqueConstraintFieldNames">An array of the names of the primary key fields to use as the basis for identifying corresponding rows between the two readers.</param>
        /// <param name="isPrimaryKey"></param>
        /// <param name="dataCopyMode">Indicates whether or not a <see cref="DataTable"/> should be created for each <see cref="IDataReader"/> (expected and actual) and the data copied in while processing the readers.</param>
        /// <param name="additionalFieldsToIgnore">Fields to ignore for the current comparison (mismatches in data values will not be counted as failures).</param>
        /// <returns>The results of the comparison.</returns>
        public DataComparerResults Compare(
            string tableName,
            IDataReader expectedData,
            IDataReader actualData,
            string[] uniqueConstraintFieldNames,
            bool isPrimaryKey,
            DataCopyMode dataCopyMode,
            string[] additionalFieldsToIgnore)
        {
            //Initialize an empty array if the parameter is null.
            additionalFieldsToIgnore = additionalFieldsToIgnore ?? new string[0];

            var dataComparerResults = new DataComparerResults {
                TableName = tableName
            };

            this.dataCopyMode = dataCopyMode;

            // Prepare data tables, if necessary
            if (dataCopyMode == DataCopyMode.All || dataCopyMode == DataCopyMode.DifferencesOnly)
            {
                DataTable expectedTable = InitializeDataTable(expectedData, uniqueConstraintFieldNames, isPrimaryKey);
                expectedTable.TableName          = "ExpectedDataTable";
                tablesByReader[expectedData]     = expectedTable;
                dataComparerResults.ExpectedData = expectedTable;

                DataTable actualTable = InitializeDataTable(actualData, uniqueConstraintFieldNames, isPrimaryKey);
                actualTable.TableName          = "ActualDataTable";
                tablesByReader[actualData]     = actualTable;
                dataComparerResults.ActualData = actualTable;
            }

            primaryKeyFields = new List <string>(uniqueConstraintFieldNames);

            InitializeColumnNamesFromReader(dataComparerResults.ColumnNames, actualData);

            VerifyThatAllNonTestColumnsFromExpectedDataArePresent(
                dataComparerResults.TableName,
                dataComparerResults.ColumnNames,
                expectedData,
                additionalFieldsToIgnore);

            // Initialize counts
            rowCountsByReader[expectedData] = 0;
            rowCountsByReader[actualData]   = 0;

            int[] expectedPKOrdinals =
                (from field in uniqueConstraintFieldNames
                 select expectedData.GetOrdinal(field)).ToArray();

            actualPKOrdinals =
                (from field in uniqueConstraintFieldNames
                 select actualData.GetOrdinal(field)).ToArray();

            DbDataReaderComparer comparer = new DbDataReaderComparer(expectedPKOrdinals, actualPKOrdinals);

            CompareAndDisposeDataReaders(comparer, dataComparerResults, actualData, expectedData, additionalFieldsToIgnore);

            // Set counts
            dataComparerResults.ExpectedRowCount = rowCountsByReader[expectedData];
            dataComparerResults.ActualRowCount   = rowCountsByReader[actualData];

            return(dataComparerResults);
        }