protected override object CreateRandomValueInternal(SqlRandomizer rand, SqlRandomTableColumn columnInfo)
 {
     int size = columnInfo.StorageSize.HasValue ? columnInfo.StorageSize.Value : DefaultCharSize;
     return rand.NextAnsiArray(0, size);
 }
 public override SqlRandomTableColumn CreateRandomColumn(SqlRandomizer rand, SqlRandomColumnOptions options)
 {
     int size = rand.NextAllocationSizeBytes(2, MaxCharSize * 2);
     size = size & 0xFFFE; // clean last bit to make it even
     return new SqlRandomTableColumn(this, options, size);
 }
Example #3
0
        /// <summary>
        /// adds a new row with random values and specified null bitmap
        /// </summary>
        public void AddRow(SqlRandomizer rand, BitArray nullBitmap)
        {
            object[] row = new object[_columns.Length];

            // non-sparse columns will always take fixed size, must add them now
            double rowSize = NonSparseValuesTotalSize;
            double maxRowSize = MaxRowSize;

            if (PrimaryKeyColumnIndex.HasValue)
            {
                // make sure pkey is set first
                // ignore the null bitmap in this case
                object pkeyValue = _rows.Count;
                row[PrimaryKeyColumnIndex.Value] = pkeyValue;
            }

            for (int c = 0; c < row.Length; c++)
            {
                if (IsPrimaryKey(c))
                {
                    // handled above
                    continue;
                }

                if (SkipOnInsert(c))
                {
                    row[c] = null; // this null value should not be used, assert triggered if it is
                }
                else if (rowSize >= maxRowSize)
                {
                    // reached the limit, cannot add more for this row
                    row[c] = DBNull.Value;
                }
                else if (nullBitmap[c])
                {
                    row[c] = DBNull.Value;
                }
                else
                {
                    object value = _columns[c].CreateRandomValue(rand);
                    if (value == null || value == DBNull.Value)
                    {
                        row[c] = DBNull.Value;
                    }
                    else if (IsSparse(c))
                    {
                        // check if the value fits
                        double newRowSize = rowSize + _columns[c].GetInRowSize(value);
                        if (newRowSize > maxRowSize)
                        {
                            // cannot fit it, zero this one and try to fit next column
                            row[c] = DBNull.Value;
                        }
                        else
                        {
                            // the value is OK, keep it
                            row[c] = value;
                            rowSize = newRowSize;
                        }
                    }
                    else
                    {
                        // non-sparse values are already counted in NonSparseValuesTotalSize
                        row[c] = value;
                    }
                }
            }

            _rows.Add(row);
        }
 public override SqlRandomTableColumn CreateRandomColumn(SqlRandomizer rand, SqlRandomColumnOptions options)
 {
     int size = rand.NextAllocationSizeBytes(1, MaxCharSize);
     return new SqlRandomTableColumn(this, options, size);
 }
 protected override object CreateRandomValueInternal(SqlRandomizer rand, SqlRandomTableColumn columnInfo)
 {
     int precision = columnInfo.Precision.HasValue ? columnInfo.Precision.Value : MaxFloatPrecision;
     if (precision <= RealPrecision)
         return rand.NextDouble(float.MinValue, float.MaxValue, precision);
     else
         return rand.NextDouble(double.MinValue, double.MaxValue, precision);
 }
 protected override object CreateRandomValueInternal(SqlRandomizer rand, SqlRandomTableColumn columnInfo)
 {
     // this method does not use Guid.NewGuid since it is not based on the given rand object
     return rand.NextUniqueIdentifier();
 }
 protected override object CreateRandomValueInternal(SqlRandomizer rand, SqlRandomTableColumn columnInfo)
 {
     return rand.NextDateTimeOffset();
 }
 protected override object CreateRandomValueInternal(SqlRandomizer rand, SqlRandomTableColumn columnInfo)
 {
     return rand.NextSmallMoney();
 }
 public object CreateRandomValue(SqlRandomizer rand) { return TypeInfo.CreateRandomValue(rand, this); }
Example #10
0
        private static void RunTestIteration(SqlConnection con, SqlRandomizer rand, SqlRandomTable table, string tableName)
        {
            // random list of columns
            int columnCount = table.Columns.Count;
            int[] columnIndicies = rand.NextIndicies(columnCount);
            int selectedCount = rand.NextIntInclusive(1, maxValueInclusive: columnCount);

            StringBuilder selectBuilder = new StringBuilder();
            table.GenerateSelectFromTableTSql(tableName, selectBuilder, columnIndicies, 0, selectedCount);
            SqlCommand cmd = con.CreateCommand();
            cmd.CommandType = CommandType.Text;
            cmd.CommandText = selectBuilder.ToString();

            bool cancel = rand.Next(100) == 0; // in 1% of the cases, call Cancel

            if (cancel)
            {
                int cancelAfterMilliseconds = rand.Next(5);
                int cancelAfterSpinCount = rand.Next(1000);

                ThreadPool.QueueUserWorkItem((object state) =>
                    {
                        for (int i = 0; cancel && i < cancelAfterMilliseconds; i++)
                        {
                            Thread.Sleep(1);
                        }
                        if (cancel && cancelAfterSpinCount > 0)
                        {
                            SpinWait.SpinUntil(() => false, new TimeSpan(cancelAfterSpinCount));
                        }
                        if (cancel)
                        {
                            cmd.Cancel();
                        }
                    });
            }

            int readerRand = rand.NextIntInclusive(0, maxValueInclusive: 256);
            CommandBehavior readerBehavior = CommandBehavior.Default;
            if (readerRand % 10 == 0)
                readerBehavior = CommandBehavior.SequentialAccess;
            try
            {
                using (SqlDataReader reader = cmd.ExecuteReader(readerBehavior))
                {
                    int row = 0;
                    while (reader.Read())
                    {
                        int rowRand = rand.NextIntInclusive();
                        if (rowRand % 1000 == 0)
                        {
                            // abandon this reader
                            break;
                        }
                        else if (rowRand % 25 == 0)
                        {
                            // skip the row
                            row++;
                            continue;
                        }

                        IList<object> expectedRow = table[row];
                        for (int c = 0; c < reader.FieldCount; c++)
                        {
                            if (rand.NextIntInclusive(0, maxValueInclusive: 10) == 0)
                            {
                                // skip the column
                                continue;
                            }

                            int expectedTableColumn = columnIndicies[c];
                            object expectedValue = expectedRow[expectedTableColumn];
                            if (table.Columns[expectedTableColumn].CanCompareValues)
                            {
                                Assert.True(expectedValue != null, "FAILED: Null is expected with CanCompareValues");

                                // read the value same way it was written
                                object actualValue = table.Columns[expectedTableColumn].Read(reader, c, expectedValue.GetType());
                                Assert.True(table.Columns[expectedTableColumn].CompareValues(expectedValue, actualValue),
                                    string.Format("FAILED: Data Comparison Failure:\n{0}", table.Columns[expectedTableColumn].BuildErrorMessage(expectedValue, actualValue)));
                            }
                        }

                        row++;
                    }
                }

                // keep last - this will stop the cancel task, if it is still active
                cancel = false;
            }
            catch (SqlException e)
            {
                if (!cancel)
                    throw;

                bool expected = false;

                foreach (SqlError error in e.Errors)
                {
                    if (error.Message == _operationCanceledErrorMessage)
                    {
                        // ignore this one - expected if canceled
                        expected = true;
                        break;
                    }
                    else if (error.Message == _severeErrorMessage)
                    {
                        // A severe error occurred on the current command.  The results, if any, should be discarded.
                        expected = true;
                        break;
                    }
                }

                if (!expected)
                {
                    // rethrow to the user
                    foreach (SqlError error in e.Errors)
                    {
                        Console.WriteLine("{0} {1}", error.Number, error.Message);
                    }
                    throw;
                }
            }
            catch (InvalidOperationException e)
            {
                bool expected = false;

                if (e.Message == _operationCanceledErrorMessage)
                {
                    // "Operation canceled" exception is raised as a SqlException (as one of SqlError objects) and as InvalidOperationException
                    expected = true;
                }

                if (!expected)
                {
                    throw;
                }
            }
        }
Example #11
0
 public static SqlRandomTable Create(SqlRandomizer rand, SqlRandomTypeInfoCollection sourceCollection, int maxColumnsCount, int rowCount, bool createPrimaryKeyColumn)
 {
     SqlRandomTableColumn[] testTypes = CreateRandTypes(rand, sourceCollection, maxColumnsCount, createPrimaryKeyColumn);
     SqlRandomTable table = new SqlRandomTable(testTypes, primaryKeyColumnIndex: createPrimaryKeyColumn ? (Nullable<int>)0 : null, estimatedRowCount: rowCount);
     table.AddRows(rand, rowCount);
     return table;
 }
Example #12
0
        /// <summary>
        /// Creates random list of columns from the given source collection. The rules are:
        /// * table cannot contain more than 1024 non-sparse columns
        /// * total row size of non-sparse columns should not exceed 8060 or 8018 (with sparse)
        /// * column set column must be added if number of columns in total exceeds 1024
        /// </summary>
        public static SqlRandomTableColumn[] CreateRandTypes(SqlRandomizer rand, SqlRandomTypeInfoCollection sourceCollection, int maxColumnsCount, bool createIdColumn)
        {
            var retColumns = new List<SqlRandomTableColumn>(maxColumnsCount);
            bool hasTimestamp = false;
            double totalRowSize = 0;
            int totalRegularColumns = 0;

            bool hasColumnSet = false;
            bool hasSparseColumns = false;
            int maxRowSize = MaxBytesPerRow; // set to MaxBytesPerRowWithSparse when sparse column is first added

            int i = 0;
            if (createIdColumn)
            {
                SqlRandomTypeInfo keyType = sourceCollection[SqlDbType.Int];
                SqlRandomTableColumn keyColumn = keyType.CreateDefaultColumn(SqlRandomColumnOptions.None);
                retColumns.Add(keyColumn);
                totalRowSize += keyType.GetInRowSize(keyColumn, null);
                i++;
                totalRegularColumns++;
            }

            for (; i < maxColumnsCount; i++)
            {
                // select column options (sparse/column-set)
                bool isSparse; // must be set in the if/else flow below
                bool isColumnSet = false;

                if (totalRegularColumns >= MaxNonSparseColumns)
                {
                    // reached the limit for regular columns

                    if (!hasColumnSet)
                    {
                        // no column-set yet, stop unconditionally
                        // this can happen if large char/binary value brought the row size total to a limit leaving no space for column-set
                        break;
                    }

                    // there is a column set, enforce sparse from this point
                    isSparse = true;
                }
                else if (i == (MaxNonSparseColumns - 1) && hasSparseColumns && !hasColumnSet)
                {
                    // we almost reached the limit of regular & sparse columns with, but no column set added
                    // to increase chances for >1024 columns, enforce column set now
                    isColumnSet = true;
                    isSparse = false;
                }
                else if (totalRowSize > MaxBytesPerRowWithSparse)
                {
                    Debug.Assert(totalRowSize <= MaxBytesPerRow, "size over the max limit");
                    Debug.Assert(!hasSparseColumns, "should not have sparse columns after MaxBytesPerRowWithSparse (check maxRowSize)");
                    // cannot insert sparse from this point
                    isSparse = false;
                    isColumnSet = false;
                }
                else
                {
                    // check how close we are to the limit of the row size
                    int sparseProbability;
                    if (totalRowSize < 100)
                    {
                        sparseProbability = 2;
                    }
                    else if (totalRowSize < MaxBytesPerRowWithSparse / 2)
                    {
                        sparseProbability = 10;
                    }
                    else if (totalRowSize < (MaxBytesPerRowWithSparse - s_columnSetSafetyRange))
                    {
                        sparseProbability = 50;
                    }
                    else
                    {
                        // close to the row size limit, special case
                        if (!hasColumnSet)
                        {
                            // if we have not added column set column yet
                            // column-set is a regular column and its size counts towards row size, so time to add it
                            isColumnSet = true;
                            sparseProbability = -1; // not used
                        }
                        else
                        {
                            sparseProbability = 90;
                        }
                    }

                    if (!isColumnSet)
                    {
                        isSparse = (rand.Next(100) < sparseProbability);

                        if (!isSparse && !hasColumnSet)
                        {
                            // if decided to add regular column, give it a (low) chance to inject a column set at any position
                            isColumnSet = rand.Next(100) < 1;
                        }
                    }
                    else
                    {
                        isSparse = false;
                    }
                }

                // select the type
                SqlRandomTypeInfo ti;
                SqlRandomColumnOptions options = SqlRandomColumnOptions.None;

                if (isSparse)
                {
                    Debug.Assert(!isColumnSet, "should not have both sparse and column set flags set");
                    ti = sourceCollection.NextSparse(rand);
                    Debug.Assert(ti.CanBeSparseColumn, "NextSparse must return only types that can be sparse");
                    options |= SqlRandomColumnOptions.Sparse;
                }
                else if (isColumnSet)
                {
                    Debug.Assert(!hasColumnSet, "there is already a column set, we should not set isColumnSet again above");
                    ti = sourceCollection[SqlDbType.Xml];
                    options |= SqlRandomColumnOptions.ColumnSet;
                }
                else
                {
                    // regular column
                    ti = sourceCollection.Next(rand);

                    if (ti.Type == SqlDbType.Timestamp)
                    {
                        // while table can contain single timestamp column only, there is no way to insert values into it. 
                        // thus, do not allow this
                        if (hasTimestamp || maxColumnsCount == 1)
                        {
                            ti = sourceCollection[SqlDbType.Int];
                        }
                        else
                        {
                            // table cannot have two timestamp columns
                            hasTimestamp = true;
                        }
                    }
                }

                SqlRandomTableColumn col = ti.CreateRandomColumn(rand, options);

                if (!isSparse)
                {
                    double rowSize = ti.GetInRowSize(col, DBNull.Value);
                    int overhead = GetRowOverhead(retColumns.Count + 1); // +1 for this column

                    if (totalRowSize + rowSize + overhead > maxRowSize)
                    {
                        // cannot use this column
                        // note that if this column is a column set column
                        continue;
                    }

                    totalRowSize += rowSize;
                    totalRegularColumns++;
                }
                // else - sparse columns are not counted towards row size when table is created (they are when inserting new row with non-null value in the sparse column)...

                retColumns.Add(col);

                // after adding the column, update the state
                if (isColumnSet)
                {
                    hasColumnSet = true;
                }

                if (isSparse)
                {
                    hasSparseColumns = true;
                    maxRowSize = MaxBytesPerRowWithSparse; // reduce the max row size
                }
            }

            return retColumns.ToArray();
        }
Example #13
0
 public void AddRows(SqlRandomizer rand, int rowCount)
 {
     for (int i = 0; i < rowCount; i++)
         AddRow(rand);
 }
 protected override object CreateRandomValueInternal(SqlRandomizer rand, SqlRandomTableColumn columnInfo)
 {
     int storageSize = GetCharSize(columnInfo) * 2;
     return rand.NextUcs2Array(0, storageSize);
 }
        protected override object CreateRandomValueInternal(SqlRandomizer rand, SqlRandomTableColumn columnInfo)
        {
            SqlRandomTypeInfo subType = s_variantSubTypes[rand.NextIntInclusive(0, maxValueInclusive: s_variantSubTypes.Length - 1)];
            object val = subType.CreateRandomValue(rand, new SqlRandomTableColumn(subType, SqlRandomColumnOptions.None, 8000));
            char[] cval = val as char[];
            if (cval != null)
            {
                int maxLength = IsUnicodeType(subType.Type) ? 4000 : 8000;
                Debug.Assert(cval.Length < maxLength, "char array length cannot be greater than " + maxLength);
                // cannot insert char[] into variant
                val = new string((char[])val);
            }
            else
            {
                byte[] bval = val as byte[];
                if (bval != null)
                    Debug.Assert(bval.Length < 8000, "byte array length cannot be greater than 8000");
            }

            return val;
        }
 protected override object CreateRandomValueInternal(SqlRandomizer rand, SqlRandomTableColumn columnInfo)
 {
     return (decimal)Math.Round(rand.NextDouble());
 }
        protected override object CreateRandomValueInternal(SqlRandomizer rand, SqlRandomTableColumn columnInfo)
        {
            if ((columnInfo.Options & SqlRandomColumnOptions.ColumnSet) != 0)
            {
                // use the sparse columns themselves to insert values
                // testing column set column correctness is not a goal for the stress test
                throw new NotImplementedException("should not use this method for column set columns");
            }

            int charSize = rand.NextAllocationSizeBytes(0, columnInfo.StorageSize);
            const string prefix = "<x>";
            const string suffix = "</x>";
            if (charSize > (prefix.Length + suffix.Length))
            {
                string randValue = new string('a', charSize - (prefix.Length + suffix.Length));
                return string.Format("<x>{0}</x>", randValue).ToCharArray();
            }
            else
            {
                // for accurate comparison, use the short form
                return "<x />".ToCharArray();
            }
        }
 public override SqlRandomTableColumn CreateRandomColumn(SqlRandomizer rand, SqlRandomColumnOptions options)
 {
     return CreateDefaultColumn(options);
 }
 protected override object CreateRandomValueInternal(SqlRandomizer rand, SqlRandomTableColumn columnInfo)
 {
     return rand.NextIntInclusive();
 }
 protected override object CreateRandomValueInternal(SqlRandomizer rand, SqlRandomTableColumn columnInfo)
 {
     return rand.NextRowVersion();
 }
 protected override object CreateRandomValueInternal(SqlRandomizer rand, SqlRandomTableColumn columnInfo)
 {
     return rand.NextByteArray(0, columnInfo.StorageSize);
 }
 public object CreateRandomValue(SqlRandomizer rand)
 {
     return(TypeInfo.CreateRandomValue(rand, this));
 }
Example #23
0
 /// <summary>
 /// adds new row with random values, each column has 50% chance to have null value
 /// </summary>
 public void AddRow(SqlRandomizer rand)
 {
     BitArray nullBitmap = rand.NextBitmap(_columns.Length);
     AddRow(rand, nullBitmap);
 }