public void AddRows(SqlRandomizer rand, int rowCount) { for (int i = 0; i < rowCount; i++) { AddRow(rand); } }
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)); }
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); }
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) { 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) { 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()); } }
protected override object CreateRandomValueInternal(SqlRandomizer rand, SqlRandomTableColumn columnInfo) { return(rand.NextReal()); }
protected override object CreateRandomValueInternal(SqlRandomizer rand, SqlRandomTableColumn columnInfo) { return((decimal)Math.Round(rand.NextDouble())); }
protected override object CreateRandomValueInternal(SqlRandomizer rand, SqlRandomTableColumn columnInfo) { int storageSize = GetCharSize(columnInfo) * 2; return(rand.NextUcs2Array(0, storageSize)); }
protected abstract object CreateRandomValueInternal(SqlRandomizer rand, SqlRandomTableColumn columnInfo);
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(1, MaxCharSize); return(new SqlRandomTableColumn(this, options, size)); }
/// <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); }
/// <summary> /// creates random, but valued value for the type, based on the given column definition /// </summary> public object CreateRandomValue(SqlRandomizer rand, SqlRandomTableColumn columnInfo) { ValidateColumnInfo(columnInfo); return(CreateRandomValueInternal(rand, columnInfo)); }
private void RunTest(SqlConnection con, RandomizerPool.Scope <SqlRandomizer> testScope, SqlRandomTypeInfoCollection types, Stopwatch watch) { Exception pendingException = null; string tempTableName = null; try { // select number of columns to use and null bitmap to test int columnsCount, rowsCount; testScope.Current.NextTableDimentions(MaxRows, MaxColumns, MaxTotal, out rowsCount, out columnsCount); SqlRandomTable table = SqlRandomTable.Create(testScope.Current, types, columnsCount, rowsCount, createPrimaryKeyColumn: true); long total = (long)rowsCount * columnsCount; Interlocked.Add(ref _totalValues, total); Interlocked.Increment(ref _totalTables); tempTableName = SqlRandomizer.GenerateUniqueTempTableNameForSqlServer(); table.GenerateTableOnServer(con, tempTableName); long prevTicks = watch.ElapsedTicks; watch.Start(); if (_randPool.ReproMode) { // perform one iteration only using (var iterationScope = testScope.NewScope <SqlRandomizer>()) { RunTestIteration(con, iterationScope.Current, table, tempTableName); Interlocked.Increment(ref _totalIterations); } } else { // continue with normal loop for (int i = 0; i < IterationsPerTableDefault && watch.Elapsed < TimeLimitDefault; i++) { using (var iterationScope = testScope.NewScope <SqlRandomizer>()) { RunTestIteration(con, iterationScope.Current, table, tempTableName); Interlocked.Increment(ref _totalIterations); } } } watch.Stop(); Interlocked.Add(ref _totalTicks, watch.ElapsedTicks - prevTicks); } catch (Exception e) { pendingException = e; throw; } finally { // keep the temp table for troubleshooting if debugger is attached // the thread is going down anyway and connection will be closed if (pendingException == null && tempTableName != null) { // destroy the temp table to free resources on the server SqlCommand cmd = con.CreateCommand(); cmd.CommandType = CommandType.Text; cmd.CommandText = "DROP TABLE " + tempTableName; try { cmd.ExecuteNonQuery(); } catch { } } } }
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()); }
/// <summary> /// returns random type info /// </summary> public SqlRandomTypeInfo Next(SqlRandomizer rand) { return(base[rand.NextIntInclusive(0, maxValueInclusive: Count - 1)]); }
/// <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()); }
/// <summary> /// returns random type info from the columns that can be sparse /// </summary> public SqlRandomTypeInfo NextSparse(SqlRandomizer rand) { var sparseColumns = SparseColumns; return(sparseColumns[rand.NextIntInclusive(0, maxValueInclusive: sparseColumns.Count - 1)]); }
public override SqlRandomTableColumn CreateRandomColumn(SqlRandomizer rand, SqlRandomColumnOptions options) { return(CreateDefaultColumn(options)); }
protected override object CreateRandomValueInternal(SqlRandomizer rand, SqlRandomTableColumn columnInfo) { return(rand.NextByteArray(0, columnInfo.StorageSize)); }
/// <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); }
private void RunTestIteration(SqlConnection con, SqlRandomizer rand, SqlRandomTable table, string tableName) { // random list of columns int columnCount = table.Columns.Count; int[] columnIndices = rand.NextIndices(columnCount); int selectedCount = rand.NextIntInclusive(1, maxValueInclusive: columnCount); StringBuilder selectBuilder = new StringBuilder(); table.GenerateSelectFromTableTSql(tableName, selectBuilder, columnIndices, 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 = columnIndices[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; } } }
public object CreateRandomValue(SqlRandomizer rand) { return(TypeInfo.CreateRandomValue(rand, this)); }