public ModelCreditOperationRequest( ModelMidType midType, ModelCreditCharge creditCharge, ModelCreditRequestNum creditRequestNum, ModelPayloadSize payloadSize, ModelPayloadType payloadType) : base(0) { this.midType = midType; this.creditCharge = creditCharge; this.creditRequestNum = creditRequestNum; this.payloadSize = payloadSize; this.payloadType = payloadType; }
public static void CreditOperationRequest( ModelMidType midType, ModelCreditCharge creditCharge, ModelCreditRequestNum creditRequestNum, ModelPayloadSize payloadSize, ModelPayloadType payloadType) { Condition.IsTrue(state == ModelState.Connected); Condition.IsNull(request); Combination.Isolated(midType == ModelMidType.UsedMid); Combination.Isolated(midType == ModelMidType.UnavailableMid); Combination.Isolated(creditCharge == ModelCreditCharge.CreditChargeExceedBoundary); Combination.Isolated(payloadSize == ModelPayloadSize.PayloadSizeLargerThanBoundary); //Pairwise the rest parameters Combination.NWise(2, creditCharge, creditRequestNum, payloadSize, payloadType); request = new ModelCreditOperationRequest( midType, creditCharge, creditRequestNum, payloadSize, payloadType); // NOTE: creditCharge will be ignored if multicredit is not supported if (midType == ModelMidType.UsedMid || midType == ModelMidType.UnavailableMid || (isMultiCreditSupported && creditCharge == ModelCreditCharge.CreditChargeExceedBoundary)) { ModelHelper.Log( LogType.Requirement, "3.3.5.2.3: If the server determines that the MessageId or the range of MessageIds for the incoming request is not valid," + " the server SHOULD<202> terminate the connection. Otherwise, the server MUST remove the MessageId or the range of MessageIds from the Connection.CommandSequenceWindow."); //Not add Platform!=NonWindows because NonWindows could also drop connection if (midType == ModelMidType.UsedMid || midType == ModelMidType.UnavailableMid) { ModelHelper.Log(LogType.TestTag, TestTag.InvalidIdentifier); } if (isMultiCreditSupported && creditCharge == ModelCreditCharge.CreditChargeExceedBoundary) { ModelHelper.Log(LogType.TestTag, TestTag.OutOfBoundary); } expectDisconnection = true; ModelHelper.Log( LogType.TestInfo, "Test case is expecting server disconnect the connection"); ModelHelper.Log( LogType.TestInfo, "Connection.SupportsMultiCredit is set to {0}, messageId type is {1}, creditCharge type is {2}", isMultiCreditSupported, midType, creditCharge); return; } if (!isMultiCreditSupported && payloadSize == ModelPayloadSize.PayloadSizeLargerThanBoundary) { ModelHelper.Log( LogType.Requirement, "3.3.5.2: If Connection.SupportsMultiCredit is FALSE and the size of the request is greater than 68*1024 bytes," + " the server SHOULD<200> terminate the connection"); //Ignore following product behavior as known issue for now ModelHelper.Log( LogType.Requirement, "<200> Section 3.3.5.2: Windows 7 without [MSKB-2536275], and Windows Server 2008 R2 without [MSKB-2536275] terminate the connection when the size of the request is greater than 64*1024 bytes." + " Windows Vista SP1 and Windows Server 2008 on Direct TCP transport disconnect the connection if the size of the message exceeds 128*1024 bytes, and Windows Vista SP1 and Windows Server 2008 on NetBIOS over TCP transport will disconnect the connection if the size of the message exceeds 64*1024 bytes"); ModelHelper.Log(LogType.TestTag, TestTag.OutOfBoundary); expectDisconnection = true; ModelHelper.Log( LogType.TestInfo, "Test case is expecting server to drop the connection"); ModelHelper.Log( LogType.TestInfo, "Connection.SupportsMultiCredit is set to {0}, messageId type is {1}, creditCharge type is {2}", isMultiCreditSupported, midType, creditCharge); } }
public void CreditOperationRequest( ModelMidType midType, ModelCreditCharge creditCharge, ModelCreditRequestNum creditRequestNum, ModelPayloadSize payloadSize, ModelPayloadType payloadType) { #region Customize message id ulong smallestAvailableMId = testClient.SequenceWindow.Min; ulong largestAvailableMId = testClient.SequenceWindow.Max; ulong customizedMId = 0; switch (midType) { case ModelMidType.UnavailableMid: { customizedMId = largestAvailableMId + 1; break; } case ModelMidType.UsedMid: { customizedMId = smallestAvailableMId - 1; break; } case ModelMidType.ValidMid: { customizedMId = (ulong)(smallestAvailableMId + largestAvailableMId) / 2; break; } default: throw new ArgumentException("midType"); } testClient.GenerateMessageId = (sequenceWindow) => customizedMId; Site.Log.Add( LogEntryKind.Debug, "*****customizedMId = {0}", customizedMId); #endregion #region Customize credit charge ushort customizedCreditCharge = 0; // Only customize credit charge when midType is valid if (midType == ModelMidType.ValidMid) { switch (creditCharge) { case ModelCreditCharge.CreditChargeWithinBoundary: { customizedCreditCharge = (ushort)((largestAvailableMId - customizedMId + 2) / 2); break; } case ModelCreditCharge.CreditChargeExceedBoundary: { customizedCreditCharge = (ushort)(largestAvailableMId - customizedMId + 2); break; } case ModelCreditCharge.CreditChargeSetZero: { customizedCreditCharge = 0; break; } default: { Site.Assume.Fail("Unexpected creditCharge {0}", creditCharge); break; } } } testClient.GenerateCreditCharge = (size) => customizedCreditCharge; Site.Log.Add( LogEntryKind.Debug, "*****customizedCreditCharge = {0}", customizedCreditCharge); #endregion #region Customize credit request ushort customizedCreditRequest = 0; switch (creditRequestNum) { case ModelCreditRequestNum.CreditRequestSetNonZero: { customizedCreditRequest = (ushort)((1 + testClient.CreditGoal) / 2); break; } case ModelCreditRequestNum.CreditRequestSetZero: { customizedCreditRequest = 0; break; } default: { Site.Assume.Fail("Unexpected creditRequestNum {0}", creditRequestNum); break; } } testClient.GenerateCreditRequest = (sequeceWindow, creditGoal, charge) => customizedCreditRequest; Site.Log.Add( LogEntryKind.Debug, "*****customizedCreditRequest = {0}", customizedCreditRequest); #endregion #region Calculate payload size int dataLengthInByte = 0; switch (payloadSize) { case ModelPayloadSize.PayloadSizeEqualToBoundary: { if (customizedCreditCharge == 0 && isMultiCreditSupportedOnConnection) { dataLengthInByte = 64 * 1024; } else if (!isMultiCreditSupportedOnConnection) { //3.3.5.2: If Connection.SupportsMultiCredit is FALSE and the size of the request is greater than 68*1024 bytes, the server SHOULD<200> terminate the connection //Note 1. 68*1024 byte is total size of Smb2 packet including header, so need to subtract such overhead to calculate payload size // 2. This case is only for WRITE but here does not distiguish READ and WRITE for simplicity uint maxSize = 0; if (testConfig.UnderlyingTransport == Smb2TransportType.NetBios) { maxSize = MaxNetbiosBufferSize; } else { maxSize = 68 * 1024; } dataLengthInByte = (int)(maxSize - Smb2PacketHeaderSizeInByte - Smb2WriteRequestBodySizeInByte); } else { dataLengthInByte = customizedCreditCharge * 64 * 1024; } break; } case ModelPayloadSize.PayloadSizeLargerThanBoundary: { if (customizedCreditCharge == 0 && isMultiCreditSupportedOnConnection) { dataLengthInByte = 64 * 1024 + 1; } else if (!isMultiCreditSupportedOnConnection) { //3.3.5.2: If Connection.SupportsMultiCredit is FALSE and the size of the request is greater than 68*1024 bytes, the server SHOULD<200> terminate the connection //Note 1. 68*1024 byte is total size of Smb2 packet including header, so need to subtract such overhead to calculate payload size // 2. This case is only for WRITE but here does not distiguish READ and WRITE for simplicity uint maxSize = 0; if (testConfig.UnderlyingTransport == Smb2TransportType.NetBios) { maxSize = MaxNetbiosBufferSize; } else { maxSize = 68 * 1024; } dataLengthInByte = (int)(maxSize - Smb2PacketHeaderSizeInByte - Smb2WriteRequestBodySizeInByte + 1); } else { dataLengthInByte = customizedCreditCharge * 64 * 1024 + 1; } break; } case ModelPayloadSize.PayloadSizeLessThanBoundary: { if (customizedCreditCharge == 0 && isMultiCreditSupportedOnConnection) { dataLengthInByte = 32 * 1024; } else if (!isMultiCreditSupportedOnConnection) { dataLengthInByte = 34 * 1024; } else { dataLengthInByte = customizedCreditCharge * 32 * 1024; } break; } default: { Site.Assume.Fail("Unexpected creditRequestNum {0}", creditRequestNum); break; } } Site.Log.Add( LogEntryKind.Debug, "*****dataLengthInByte = {0}", dataLengthInByte); #endregion #region Send request uint status = 0; uint creditResponse = 0; switch (payloadType) { case ModelPayloadType.RequestPayload: { try { string contentToWrite = Smb2Utility.CreateRandomStringInByte(dataLengthInByte); testClient.Write( treeId, fileId, contentToWrite, checker: (header, response) => { status = header.Status; creditResponse = header.CreditRequestResponse; }); if (dataLengthInByte > testClient.MaxBufferSize && config.Platform != Platform.WindowsServer2008) { // The server MUST validate that the length to write is within its configured maximum write size. // If not, it SHOULD<283> fail the request with STATUS_INVALID_PARAMETER. // <283> Section 3.3.5.13: Windows 7 and Windows Server 2008 R2 fail the request with STATUS_BUFFER_OVERFLOW instead of // STATUS_INVALID_PARAMETER if the Length field is greater than Connection.MaxWriteSize. // Windows Vista SP1 and Windows Server 2008 do not validate the Length field in SMB2 Write Request. if (config.Platform == Platform.WindowsServer2008R2) { Site.Assert.AreEqual( ModelSmb2Status.STATUS_BUFFER_OVERFLOW, (ModelSmb2Status)status, "Windows 7, Windows Server 2008 R2 fail the request with STATUS_BUFFER_OVERFLOW if exceeds max write size"); } else { Site.Assert.AreNotEqual( ModelSmb2Status.STATUS_SUCCESS, (ModelSmb2Status)status, "Server SHOULD fail the request with STATUS_INVALID_PARAMETER if exceeds max write data"); } // Bypass the situation when data length exceeds max size that connection allows CreditOperationResponse(ModelSmb2Status.STATUS_SUCCESS, creditResponse, config); } else { if (config.Platform == Platform.WindowsServer2008 && dataLengthInByte > testClient.MaxBufferSize) { Site.Assert.AreEqual( ModelSmb2Status.STATUS_SUCCESS, (ModelSmb2Status)status, "Windows Vista SP1 and Windows Server 2008 do not validate the Length field in SMB2 Write Request."); // Bypass the situation when data length exceeds max size that connection allows CreditOperationResponse(ModelSmb2Status.STATUS_INVALID_PARAMETER, creditResponse, config); } else { CreditOperationResponse((ModelSmb2Status)status, creditResponse, config); } } PostOperation(); } catch (Exception ex) { // Make sure testClient was set to null during disconnection correctly // In case we catch a timeout exception first // Temp fix for test suite bug 6349 as per discussion // For an SMB2 Write request with an invalid MessageId, Windows 8 and Windows Server 2012 will stop processing // the request and any further requests on that connection. // So Smb2Client will throw a timeout exception instead of disconnect event. // The test case should handle the timeout exception the same with disconnect event. if (ex is TimeoutException || testClient.Smb2Client.IsServerDisconnected) { OnServerDisconnected(); } else { throw; } return; } break; } case ModelPayloadType.ResponsePayload: { CreateFile(uncSharePath, fileName, dataLengthInByte); try { string contentToRead = null; testClient.Read( treeId, fileId, 0, (uint)dataLengthInByte, out contentToRead, (header, response) => { status = header.Status; creditResponse = header.CreditRequestResponse; }); if (dataLengthInByte > testClient.MaxBufferSize) { // The server MUST validate that the length to read is within its configured maximum read size. // If not, it SHOULD<277> fail the request with STATUS_INVALID_PARAMETER. // <277> Section 3.3.5.12: Windows 7 and Windows Server 2008 R2 fail the request with STATUS_BUFFER_OVERFLOW if the Length field is greater than Connection.MaxReadSize. // Windows Vista SP1 and Windows Server 2008 will fail the request with STATUS_BUFFER_OVERFLOW if the Length field is greater than 524288(0x80000). if (config.Platform == Platform.WindowsServer2008 || config.Platform == Platform.WindowsServer2008R2) { if (config.Platform == Platform.WindowsServer2008R2) { Site.Assert.AreEqual( ModelSmb2Status.STATUS_BUFFER_OVERFLOW, (ModelSmb2Status)status, "Windows 7, and Windows Server 2008 R2 fail the request with STATUS_BUFFER_OVERFLOW if exceeds max read size"); } else if (dataLengthInByte > 524288) { Site.Assert.AreEqual( ModelSmb2Status.STATUS_BUFFER_OVERFLOW, (ModelSmb2Status)status, "Windows Vista SP1 and Windows Server 2008 will fail the request with STATUS_BUFFER_OVERFLOW if the Length field is greater than 524288"); } } else if (config.Platform == Platform.WindowsServer2012 || config.Platform == Platform.WindowsServer2012R2) { // The server MUST validate that the length to read is within its configured maximum read size. // If not, it SHOULD<277> fail the request with STATUS_INVALID_PARAMETER. Site.Assert.AreEqual( ModelSmb2Status.STATUS_INVALID_PARAMETER, (ModelSmb2Status)status, "The server SHOULD fail the request with STATUS_INVALID_PARAMETER if the length is NOT within its configured maximum size."); } else // NonWindows { Site.Assert.AreNotEqual( ModelSmb2Status.STATUS_SUCCESS, (ModelSmb2Status)status, "Server SHOULD fail the request with STATUS_INVALID_PARAMETER if exceeds max read size"); } // Bypass the situation when data length exceeds max size that connection allows CreditOperationResponse(ModelSmb2Status.STATUS_SUCCESS, creditResponse, config); } else { CreditOperationResponse((ModelSmb2Status)status, creditResponse, config); } PostOperation(); } catch (Exception ex) { // Make sure testClient was set to null during disconnection correctly // In case we catch a timeout exception first // Temp fix for test suite bug 6349 as per discussion // For an SMB2 Write request with an invalid MessageId, Windows 8 and Windows Server 2012 will stop processing // the request and any further requests on that connection. // So Smb2Client will throw a timeout exception instead of disconnect event. // The test case should handle the timeout exception the same with disconnect event. if (ex is TimeoutException || testClient.Smb2Client.IsServerDisconnected) { OnServerDisconnected(); } else { throw; } return; } break; } default: throw new ArgumentException("payloadType"); } #endregion }