public static void Set_InvalidIndex_ThrowsArgumentOutOfRangeException() { WireReadyBitArray WireReadyBitArray = new WireReadyBitArray(16); Assert.Throws <ArgumentOutOfRangeException>(() => WireReadyBitArray.Set(-1, true)); Assert.Throws <ArgumentOutOfRangeException>(() => WireReadyBitArray.Set(WireReadyBitArray.Length, true)); Assert.Throws <ArgumentOutOfRangeException>(() => WireReadyBitArray[-1] = true); Assert.Throws <ArgumentOutOfRangeException>(() => WireReadyBitArray[WireReadyBitArray.Length] = true); }
public static void Get_Set(bool def, bool[] newValues) { WireReadyBitArray WireReadyBitArray = new WireReadyBitArray(newValues.Length, def); for (int i = 0; i < newValues.Length; i++) { WireReadyBitArray.Set(i, newValues[i]); Assert.AreEqual(newValues[i], WireReadyBitArray[i]); Assert.AreEqual(newValues[i], WireReadyBitArray.Get(i)); } }
/*========================================================================= ** Allocates a new BitArray with the same length and bit values as bits. ** ** Exceptions: ArgumentException if bits == null. ** =========================================================================*/ public WireReadyBitArray(WireReadyBitArray bits) { if (bits == null) { throw new ArgumentNullException(nameof(bits)); } int arrayLength = bits.InternalArray.Length; //TODO: This could be slower for some lengths: https://stackoverflow.com/a/33865267 InternalArray = new byte[arrayLength]; Buffer.BlockCopy(bits.InternalArray, 0, InternalArray, 0, arrayLength); }
/// <inheritdoc /> public FieldValueUpdate([NotNull] WireReadyBitArray fieldValueUpdateMask, [NotNull] int[] fieldValueUpdates) { //We shouldn't send an a field value update if there are no fields to even update. It's pointless bandwidth wasted if (fieldValueUpdates == null) { throw new ArgumentNullException(nameof(fieldValueUpdates)); } //if(fieldValueUpdates.Length == 0) throw new ArgumentException("Value cannot be an empty collection.", nameof(fieldValueUpdates)); //TODO: Should we do a debug assert or whatever for testing if lengths match or field update isn't empty? FieldValueUpdateMask = fieldValueUpdateMask ?? throw new ArgumentNullException(nameof(fieldValueUpdateMask)); _FieldValueUpdates = fieldValueUpdates; }
public static void Get_InvalidIndex_ThrowsArgumentOutOfRangeException() { WireReadyBitArray bitArray = new WireReadyBitArray(16); Assert.Throws <ArgumentOutOfRangeException>(() => bitArray.Get(-1)); Assert.Throws <ArgumentOutOfRangeException>(() => bitArray.Get(bitArray.Length)); Assert.Throws <ArgumentOutOfRangeException>(() => { var l = bitArray[-1]; }); Assert.Throws <ArgumentOutOfRangeException>(() => { var l = bitArray[bitArray.Length]; }); }
/// <summary> /// Overloaded constructor which will actually take an initial <see cref="ChangeTrackingArray"/>. /// Useful for initial creation if you want initial values to be viewed as changes. /// </summary> /// <param name="entityDataCollection"></param> /// <param name="initialChangeTrackBitArray"></param> public ChangeTrackingEntityFieldDataCollectionDecorator(IEntityDataFieldContainer entityDataCollection, [NotNull] WireReadyBitArray initialChangeTrackBitArray) { if (initialChangeTrackBitArray == null) { throw new ArgumentNullException(nameof(initialChangeTrackBitArray)); } if (initialChangeTrackBitArray.Length != entityDataCollection.DataSetIndicationArray.Length) { throw new InvalidOperationException($"Cannot set fields in {nameof(ChangeTrackingEntityFieldDataCollectionDecorator)} since provided collections {nameof(entityDataCollection)} and {nameof(initialChangeTrackBitArray)} do not have matching lengths."); } EntityDataCollection = entityDataCollection ?? throw new ArgumentNullException(nameof(entityDataCollection)); ChangeTrackingArray = initialChangeTrackBitArray; //just the size of the initial data indiciation bitarray //TODO: Technically we can't ASSUME it has any changes, but probably more efficient to than to check. HasPendingChanges = true; }
public static void SetAll(int size, bool defaultValue) { WireReadyBitArray WireReadyBitArray = new WireReadyBitArray(size, defaultValue); WireReadyBitArray.SetAll(!defaultValue); for (int i = 0; i < WireReadyBitArray.Length; i++) { Assert.AreEqual(!defaultValue, WireReadyBitArray[i]); Assert.AreEqual(!defaultValue, WireReadyBitArray.Get(i)); } WireReadyBitArray.SetAll(defaultValue); for (int i = 0; i < WireReadyBitArray.Length; i++) { Assert.AreEqual(defaultValue, WireReadyBitArray[i]); Assert.AreEqual(defaultValue, WireReadyBitArray.Get(i)); } }
/// <summary> /// Overload that supports initializing custom (by the exactly sized) /// <see cref="initialDataSetIndicationArray"/> and entity data <see cref="entityData"/>. /// </summary> /// <param name="initialDataSetIndicationArray">The initial data set array.</param> /// <param name="entityData"></param> public EntityFieldDataCollection(WireReadyBitArray initialDataSetIndicationArray, byte[] entityData) { if (initialDataSetIndicationArray == null) { throw new ArgumentNullException(nameof(initialDataSetIndicationArray)); } //TODO: Make this allocation more efficient. Maybe even use pooling. InternalDataFields = entityData ?? throw new ArgumentNullException(nameof(entityData)); //Internal data representation is bytes. Soooo, we must reduce it to 4 byte chunks which is what the bitlength for the wireready //bitarray represents. if ((InternalDataFields.Length / 4) != initialDataSetIndicationArray.Length) { throw new ArgumentException($"Failed to initialize entity field data collection due to incorrect Length: {initialDataSetIndicationArray.Length} vs Field Length: {(InternalDataFields.Length / 4)}"); } DataSetIndicationArray = initialDataSetIndicationArray; }
public void Test_ChangeTracker_Doesnt_Set_Change_Bits_On_Same_Value_After_Clear_FieldValueUpdate() { //arrange WireReadyBitArray bitArray = new WireReadyBitArray(1328); bitArray.Set(1, true); bitArray.Set(2, true); bitArray.Set(4, true); //Reference the actual client's visibile field update computation. IEntityDataFieldContainer dataCollection = NetworkVisibilityCreationBlockToVisibilityEventFactory.CreateInitialEntityFieldContainer(new FieldValueUpdate(bitArray, new int[] { 5, 4, 7 })); ChangeTrackingEntityFieldDataCollectionDecorator collection = new ChangeTrackingEntityFieldDataCollectionDecorator(dataCollection, bitArray); FieldValueUpdateFactory updateFactory = new FieldValueUpdateFactory(); //act FieldValueUpdate fieldValueUpdate = updateFactory.Create(new EntityFieldUpdateCreationContext(collection, collection.ChangeTrackingArray)); Assert.AreEqual(3, fieldValueUpdate.FieldValueUpdateMask.EnumerateSetBitsByIndex().Count(), $"Found more than 1 set bit."); Assert.AreEqual(5, fieldValueUpdate.FieldValueUpdates.First(), $"Serialized value was not expected value."); Assert.AreEqual(1, fieldValueUpdate.FieldValueUpdateMask.EnumerateSetBitsByIndex().First(), $"Index: {1} was expected to be first index."); collection.ClearTrackedChanges(); //Check they're event before setting them again Assert.AreEqual(collection.GetFieldValue <int>(1), 5, $"Values not the same."); Assert.AreEqual(collection.GetFieldValue <int>(2), 4, $"Values not the same."); collection.SetFieldValue(1, 5); collection.SetFieldValue(2, 4); fieldValueUpdate = updateFactory.Create(new EntityFieldUpdateCreationContext(collection, collection.ChangeTrackingArray)); //assert Assert.AreEqual(0, fieldValueUpdate.FieldValueUpdateMask.EnumerateSetBitsByIndex().Count(), $"Found more than 1 set bit."); Assert.AreEqual(0, fieldValueUpdate.FieldValueUpdates.Count, $"Field updates should be empty due to no changes.."); }
/// <inheritdoc /> public ChangeTrackingEntityFieldDataCollectionDecorator(IEntityDataFieldContainer entityDataCollection) { EntityDataCollection = entityDataCollection ?? throw new ArgumentNullException(nameof(entityDataCollection)); ChangeTrackingArray = new WireReadyBitArray(entityDataCollection.DataSetIndicationArray.Length); //just the size of the initial data indiciation bitarray }
/// <inheritdoc /> public EntityFieldUpdateCreationContext([NotNull] IEntityDataFieldContainer dataCollection, [NotNull] WireReadyBitArray fieldsToUpdateBitArray) { DataCollection = dataCollection ?? throw new ArgumentNullException(nameof(dataCollection)); FieldsToUpdateBitArray = fieldsToUpdateBitArray ?? throw new ArgumentNullException(nameof(fieldsToUpdateBitArray)); }
public EntityFieldDataCollection(int fieldCount) { //TODO: Make this allocation more efficient. Maybe even use pooling. InternalDataFields = new byte[fieldCount * sizeof(int)]; DataSetIndicationArray = new WireReadyBitArray(fieldCount); }