/// <summary> /// Parse the QueryColumns request type response body. /// </summary> /// <param name="rawData">The raw data of response.</param> /// <returns>The QueryColumns request type response body.</returns> public static QueryColumnsResponseBody Parse(byte[] rawData) { QueryColumnsResponseBody responseBody = new QueryColumnsResponseBody(); int index = 0; responseBody.StatusCode = BitConverter.ToUInt32(rawData, index); index += sizeof(uint); responseBody.ErrorCode = BitConverter.ToUInt32(rawData, index); index += sizeof(uint); responseBody.HasColumns = BitConverter.ToBoolean(rawData, index); index += sizeof(bool); if (responseBody.HasColumns) { responseBody.Columns = LargePropertyTagArray.Parse(rawData, ref index); } else { responseBody.Columns = null; } responseBody.AuxiliaryBufferSize = BitConverter.ToUInt32(rawData, index); index += 4; responseBody.AuxiliaryBuffer = new byte[responseBody.AuxiliaryBufferSize]; Array.Copy(rawData, index, responseBody.AuxiliaryBuffer, 0, responseBody.AuxiliaryBufferSize); return(responseBody); }
/// <summary> /// Parse the ResolveNames request type response body. /// </summary> /// <param name="rawData">The raw data of response.</param> /// <returns>The ResolveNames request type response body.</returns> public static ResolveNamesResponseBody Parse(byte[] rawData) { ResolveNamesResponseBody responseBody = new ResolveNamesResponseBody(); int index = 0; responseBody.StatusCode = BitConverter.ToUInt32(rawData, index); index += sizeof(uint); responseBody.ErrorCode = BitConverter.ToUInt32(rawData, index); index += sizeof(uint); responseBody.CodePage = BitConverter.ToUInt32(rawData, index); index += sizeof(uint); responseBody.HasMinimalIds = BitConverter.ToBoolean(rawData, index); index += sizeof(bool); if (responseBody.HasMinimalIds) { responseBody.MinimalIdCount = BitConverter.ToUInt32(rawData, index); index += sizeof(uint); responseBody.MinimalIds = new uint[(uint)responseBody.MinimalIdCount]; for (int i = 0; i < responseBody.MinimalIdCount; i++) { responseBody.MinimalIds[i] = BitConverter.ToUInt32(rawData, index); index += sizeof(uint); } } else { responseBody.MinimalIdCount = null; responseBody.MinimalIds = null; } responseBody.HasRowsAndPropertyTags = BitConverter.ToBoolean(rawData, index); index += sizeof(bool); if (responseBody.HasRowsAndPropertyTags) { responseBody.PropertyTags = LargePropertyTagArray.Parse(rawData, ref index); responseBody.RowCount = BitConverter.ToUInt32(rawData, index); index += sizeof(uint); responseBody.RowData = new AddressBookPropertyRow[(uint)responseBody.RowCount]; for (int i = 0; i < responseBody.RowCount; i++) { responseBody.RowData[i] = AddressBookPropertyRow.Parse(rawData, (LargePropertyTagArray)responseBody.PropertyTags, ref index); } } responseBody.AuxiliaryBufferSize = BitConverter.ToUInt32(rawData, index); index += 4; responseBody.AuxiliaryBuffer = new byte[responseBody.AuxiliaryBufferSize]; Array.Copy(rawData, index, responseBody.AuxiliaryBuffer, 0, responseBody.AuxiliaryBufferSize); return(responseBody); }
/// <summary> /// Parse the SeekEntries request type response body. /// </summary> /// <param name="rawData">The raw data of response.</param> /// <returns>The SeekEntries request type response body.</returns> public static SeekEntriesResponseBody Parse(byte[] rawData) { SeekEntriesResponseBody responseBody = new SeekEntriesResponseBody(); int index = 0; responseBody.StatusCode = BitConverter.ToUInt32(rawData, index); index += sizeof(uint); responseBody.ErrorCode = BitConverter.ToUInt32(rawData, index); index += sizeof(uint); responseBody.HasState = BitConverter.ToBoolean(rawData, index); index += sizeof(bool); if (responseBody.HasState) { responseBody.State = STAT.Parse(rawData, ref index); } else { responseBody.State = null; } responseBody.HasColumnsAndRows = BitConverter.ToBoolean(rawData, index); index += sizeof(bool); if (responseBody.HasColumnsAndRows) { responseBody.Columns = LargePropertyTagArray.Parse(rawData, ref index); responseBody.RowCount = BitConverter.ToUInt32(rawData, index); responseBody.RowData = new AddressBookPropertyRow[(uint)responseBody.RowCount]; index += sizeof(uint); for (int i = 0; i < responseBody.RowCount; i++) { responseBody.RowData[i] = AddressBookPropertyRow.Parse(rawData, (LargePropertyTagArray)responseBody.Columns, ref index); } } else { responseBody.Columns = null; responseBody.RowCount = null; responseBody.RowData = null; } responseBody.AuxiliaryBufferSize = BitConverter.ToUInt32(rawData, index); index += 4; responseBody.AuxiliaryBuffer = new byte[responseBody.AuxiliaryBufferSize]; Array.Copy(rawData, index, responseBody.AuxiliaryBuffer, 0, responseBody.AuxiliaryBufferSize); return(responseBody); }
/// <summary> /// Compare whether two LargePropertyTagArrays are equal. /// </summary> /// <param name="propertyTagArray1">The first LargePropertyTagArray used to compare.</param> /// <param name="propertyTagArray2">The second LargePropertyTagArray used to compare.</param> /// <returns>Returns true if they are equal; otherwise false.</returns> public static bool AreTwoLargePropertyTagArrayEqual(LargePropertyTagArray propertyTagArray1, LargePropertyTagArray propertyTagArray2) { if (propertyTagArray1.PropertyTagCount != propertyTagArray2.PropertyTagCount) { site.Log.Add( LogEntryKind.Debug, "The length the two property tag array are not equal. The length of propertyTagArray1 is {0}, the length of propertyTagArray2 is {1}.", propertyTagArray1.PropertyTagCount, propertyTagArray2.PropertyTagCount); return(false); } else { PropertyTag[] propertyTags1 = propertyTagArray1.PropertyTags; PropertyTag[] propertyTags2 = propertyTagArray2.PropertyTags; for (int i = 0; i < propertyTags1.Length; i++) { if (propertyTags1[i].PropertyId != propertyTags2[i].PropertyId) { site.Log.Add( LogEntryKind.Debug, "The property ID of property {0} in the two property tag array are not equal. The property ID of propertyTags1 is {1}, the property ID of propertyTags2 is {2}", i, propertyTags1[i].PropertyId, propertyTags2[i].PropertyId); return(false); } else if (propertyTags1[i].PropertyType != propertyTags2[i].PropertyType) { site.Log.Add( LogEntryKind.Debug, "The property type of property {0} in the two property tag array are not equal. The property type of propertyTags1 is {1}, the property type of propertyTags2 is {2}", i, propertyTags1[i].PropertyType, propertyTags2[i].PropertyType); return(false); } } } return(true); }
/// <summary> /// Parse the Large property tag array from the response data. /// </summary> /// <param name="rawData">The response data.</param> /// <param name="index">The start index of response data.</param> /// <returns>The result of parse the response data</returns> public static LargePropertyTagArray Parse(byte[] rawData, ref int index) { LargePropertyTagArray largePropTagArray = new LargePropertyTagArray(); largePropTagArray.PropertyTagCount = BitConverter.ToUInt32(rawData, index); index += sizeof(uint); largePropTagArray.PropertyTags = new PropertyTag[largePropTagArray.PropertyTagCount]; int count = 0; while (largePropTagArray.PropertyTagCount > count) { largePropTagArray.PropertyTags[count].PropertyType = BitConverter.ToUInt16(rawData, index); index += 2; largePropTagArray.PropertyTags[count].PropertyId = BitConverter.ToUInt16(rawData, index); index += 2; count++; } return largePropTagArray; }
/// <summary> /// Parse the Large property tag array from the response data. /// </summary> /// <param name="rawData">The response data.</param> /// <param name="index">The start index of response data.</param> /// <returns>The result of parse the response data</returns> public static LargePropertyTagArray Parse(byte[] rawData, ref int index) { LargePropertyTagArray largePropTagArray = new LargePropertyTagArray(); largePropTagArray.PropertyTagCount = BitConverter.ToUInt32(rawData, index); index += sizeof(uint); largePropTagArray.PropertyTags = new PropertyTag[largePropTagArray.PropertyTagCount]; int count = 0; while (largePropTagArray.PropertyTagCount > count) { largePropTagArray.PropertyTags[count].PropertyType = BitConverter.ToUInt16(rawData, index); index += 2; largePropTagArray.PropertyTags[count].PropertyId = BitConverter.ToUInt16(rawData, index); index += 2; count++; } return(largePropTagArray); }
/// <summary> /// Parse the AddressBookPropertyRow structure. /// </summary> /// <param name="rawBuffer">The raw data returned from server.</param> /// <param name="propTagArray">The list of property tags.</param> /// <param name="index">The start index.</param> /// <returns>Return an instance of AddressBookPropertyRow.</returns> public static AddressBookPropertyRow Parse(byte[] rawBuffer, LargePropertyTagArray propTagArray, ref int index) { AddressBookPropertyRow addressBookPropertyRow = new AddressBookPropertyRow(); addressBookPropertyRow.Flag = rawBuffer[index]; index++; List <AddressBookPropertyValue> valueArray = new List <AddressBookPropertyValue>(); Context.Instance.PropertyBytes = rawBuffer; Context.Instance.CurIndex = index; Context.Instance.CurProperty = new Property(PropertyType.PtypUnspecified); // If the value of the Flags field is set to 0x00: The array contains either a AddressBookPropertyValue structure, or a AddressBookTypedPropertyValue structure. // If the value of the Flags field is set to 0x01: The array contains either a AddressBookFlaggedPropertyValue structure, or a AddressBookFlaggedPropertyValueWithType structure. if (addressBookPropertyRow.Flag == 0x00) { foreach (PropertyTag propertyTag in propTagArray.PropertyTags) { if (propertyTag.PropertyType == 0x0000) { // If the value of the Flags field is set to 0x00: The array contains a AddressBookTypedPropertyValue structure, if the type of property is PtyUnspecified. AddressBookTypedPropertyValue typedPropertyValue = new AddressBookTypedPropertyValue(); // Parse the AddressBookTypedPropertyValue with the instance of the context which contains the datas and start index. typedPropertyValue.Parse(Context.Instance); valueArray.Add(typedPropertyValue); index = Context.Instance.CurIndex; } else { // If the value of the Flags field is set to 0x00: The array contains a AddressBookPropertyValue structure, if the type of property is specified. Context.Instance.CurProperty.Type = (PropertyType)propertyTag.PropertyType; AddressBookPropertyValue propertyValue = new AddressBookPropertyValue(); // Parse the AddressBookTypedPropertyValue with the instance of the context which contains the datas and start index. propertyValue.Parse(Context.Instance); valueArray.Add(propertyValue); index = Context.Instance.CurIndex; } } } else if (addressBookPropertyRow.Flag == 0x01) { foreach (PropertyTag propertyTag in propTagArray.PropertyTags) { if (propertyTag.PropertyType == 0x0000) { // If the value of the Flags field is set to 0x01: The array contains a AddressBookFlaggedPropertyValueWithType structure, if the type of property is PtyUnspecified. AddressBookFlaggedPropertyValueWithType flaggedPropertyValue = new AddressBookFlaggedPropertyValueWithType(); // Parse the AddressBookTypedPropertyValue with the instance of the context which contains the datas and start index. flaggedPropertyValue.Parse(Context.Instance); valueArray.Add(flaggedPropertyValue); index = Context.Instance.CurIndex; } else { // If the value of the Flags field is set to 0x01: The array contains a AddressBookFlaggedPropertyValue structure, if the type of property is specified. Context.Instance.CurProperty.Type = (PropertyType)propertyTag.PropertyType; AddressBookFlaggedPropertyValue propertyValue = new AddressBookFlaggedPropertyValue(); // Parse the AddressBookTypedPropertyValue with the instance of the context which contains the datas and start index. propertyValue.Parse(Context.Instance); valueArray.Add(propertyValue); index = Context.Instance.CurIndex; } } } addressBookPropertyRow.ValueArray = valueArray.ToArray(); return(addressBookPropertyRow); }
public void MSOXCMAPIHTTP_S02_TC11_QueryRowsRequestType() { this.CheckMapiHttpIsSupported(); #region Call Bind request type to established a session context with the address book server. this.Bind(); #endregion #region Call QueryRows with all optional fields exist and the type of all properties specified. uint tableCount = 0; uint[] table = null; uint rowCount = ConstValues.QueryRowsRequestedRowNumber; STAT stat = new STAT(); stat.InitiateStat(); LargePropertyTagArray columns = new LargePropertyTagArray() { PropertyTagCount = 2, PropertyTags = new PropertyTag[] { new PropertyTag { PropertyType = (ushort)PropertyType.PtypString, PropertyId = (ushort)PropertyID.PidTagDisplayName }, new PropertyTag { PropertyType = (ushort)PropertyType.PtypInteger32, PropertyId = (ushort)PropertyID.PidTagDisplayType } } }; QueryRowsRequestBody queryRowsRequestBody = this.BuildQueryRowsRequestBody(true, stat, tableCount, table, rowCount, true, columns); QueryRowsResponseBody queryRowsResponseBody = this.Adapter.QueryRows(queryRowsRequestBody); Site.Assert.AreEqual<uint>((uint)0, queryRowsResponseBody.ErrorCode, "QueryRows operation should succeed and 0 is expected to be returned. The return value is {0}.", queryRowsResponseBody.ErrorCode); #region Capture code // Add the debug information this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCMAPIHTTP_R802"); // Verify MS-OXCMAPIHTTP requirement: MS-OXCMAPIHTTP_R802 this.Site.CaptureRequirementIfAreEqual<uint>( columns.PropertyTagCount, queryRowsResponseBody.Columns.Value.PropertyTagCount, 802, @"[In QueryRows Request Type] The QueryRows request type is used by the client to get a number of rows from the specified Explicit Table."); // Add the debug information this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCMAPIHTTP_R827"); // Verify MS-OXCMAPIHTTP requirement: MS-OXCMAPIHTTP_R827 this.Site.CaptureRequirementIfIsTrue( AdapterHelper.AreTwoLargePropertyTagArrayEqual(queryRowsRequestBody.Columns, queryRowsResponseBody.Columns.Value), 827, @"[In QueryRows Request Type Request Body] Columns (optional) (variable): A LargePropTagArray structure (section 2.2.1.3) that specifies the properties that the client requires for each row returned."); AddressBookPropertyRow[] rowData = queryRowsResponseBody.RowData; for (int i = 0; i < rowData.Length; i++) { // Add the debug information this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCDATA_R455"); int lengthString = rowData[i].ValueArray[0].Value.Length; bool result = (rowData[i].ValueArray[0].Value[lengthString - 1] == 0) && (rowData[i].ValueArray[0].Value[lengthString - 2] == 0); // Verify MS-OXCDATA requirement: MS-OXCDATA_R455 this.Site.CaptureRequirementIfIsTrue( result, "MS-OXCDATA", 455, @"[In PropertyValue Structure] PropertyValue (variable): If the property value being passed is a string, the data includes the terminating null characters."); List<AddressBookPropertyValue> valueArray = new List<AddressBookPropertyValue>(rowData[i].ValueArray); for (int j = 0; j < valueArray.Count; j++) { // Add the debug information this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCMAPIHTTP_R18"); bool isVerifyR18 = rowData[i].Flag == 0x0 || rowData[i].Flag == 0x1; // Verify MS-OXCMAPIHTTP requirement: MS-OXCMAPIHTTP_R18 this.Site.CaptureRequirementIfIsTrue( isVerifyR18, 18, @"[In AddressBookPropertyRow Structure] [Flags] The flag MUST be set to one of the values [0x0 and 0x1] in the following table."); // Add the debug information this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCMAPIHTTP_R2036"); // MS-OXCMAPIHTTP_R18 is verified, and AddressBookPropertyRow structure in QueryRows response body is parsed successfully, // so MS-OXCMAPIHTTP_R2036 can be verified directly if code can reach here. this.Site.CaptureRequirement( 2036, @"[In AddressBookPropertyRow Structure] [ValueArray] Each structure in the array MUST be interpreted based on the Flag field."); if (rowData[i].Flag == 0x0) { // Add the debug information this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCMAPIHTTP_R450"); // Verify MS-OXCMAPIHTTP requirement: MS-OXCMAPIHTTP_R450 // In this step, the type of all properties required to be returned is not PtypUnspecified, that is, their type is specified. // So if the type of each value returned in the response is AddressBookPropertyValue, MS-OXCMAPIHTTP_R450 can be verified. this.Site.CaptureRequirementIfIsInstanceOfType( valueArray[j], typeof(AddressBookPropertyValue), 450, @"[In AddressBookPropertyRow Structure] [Flags] If the value of the Flags field is set to 0x0: The ValueArray field contains either an AddressBookPropertyValue structure, see section 2.2.1.1, if the type of the property is specified."); if (valueArray[j].HasValue == 0xFF) { // Add the debug information this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCMAPIHTTP_R2006"); // Verify MS-OXCMAPIHTTP_R2006 this.Site.CaptureRequirementIfIsNotNull( valueArray[j].Value, 2006, @"[In AddressBookPropertyValue Structure] [HasValue] A TRUE value means that the PropertyValue field is present."); } else { if(valueArray[j].HasValue == null) { // Add the debug information this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCMAPIHTTP_R2010"); // Verify MS-OXCMAPIHTTP_R2010 this.Site.CaptureRequirementIfIsNotNull( valueArray[j].Value, 2010, @"[In AddressBookPropertyValue Structure] [PropertyValue] This field is always present when HasValue is not present."); } // Add the debug information this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCMAPIHTTP_R2009"); // Verify MS-OXCMAPIHTTP_R2009 this.Site.CaptureRequirementIfIsNotNull( valueArray[j].Value, 2009, @"[In AddressBookPropertyValue Structure] PropertyValue (optional) (variable): A PropertyValue structure ([MS-OXCDATA] section 2.11.2.1), unless HasValue is present with a value of FALSE (0x00)."); } // Add the debug information this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCDATA_R454"); // Verify MS-OXCDATA requirement: MS-OXCDATA_R454 // In this step, the type of all properties required to be returned is not PtypUnspecified, that is, their type is specified. // So if the type of each value returned in the response is AddressBookPropertyValue, MS-OXCMAPIHTTP_R454 can be verified. this.Site.CaptureRequirementIfIsInstanceOfType( valueArray[j], typeof(AddressBookPropertyValue), "MS-OXCDATA", 454, @"[In PropertyValue Structure] PropertyValue (variable): For multivalue types, the first element in the ROP buffer is a 16-bit integer specifying the number of entries."); } } } // The list of property tags is already specified in columns field in QueryRows request body, and AddressBookPropertyRow structure in QueryRows response body is parsed successfully, // so MS-OXCMAPIHTTP_R16 can be verified directly if code can reach here. this.Site.CaptureRequirement( 16, @"[In AddressBookPropertyRow Structure] [AddressBookPropertyRow] This structure is used when the list of property tags is known in advance."); #endregion #endregion #region Call QueryRows with Flags set to one value other than fEphID (0x00000002) and fSkipObjects (0x00000001). queryRowsRequestBody.Flags = 0x3; QueryRowsResponseBody queryRowsResponseBody1 = this.Adapter.QueryRows(queryRowsRequestBody); Site.Assert.AreEqual<uint>((uint)0, queryRowsResponseBody1.ErrorCode, "QueryRows operation should succeed and 0 is expected to be returned. The return value is {0}.", queryRowsResponseBody1.ErrorCode); #endregion #region Call QueryRows with Flags set to another value other than fEphID (0x00000002) and fSkipObjects (0x00000001). queryRowsRequestBody.Flags = 0x4; QueryRowsResponseBody queryRowsResponseBody2 = this.Adapter.QueryRows(queryRowsRequestBody); Site.Assert.AreEqual<uint>((uint)0, queryRowsResponseBody2.ErrorCode, "QueryRows operation should succeed and 0 is expected to be returned. The return value is {0}.", queryRowsResponseBody2.ErrorCode); // Add the debug information this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCMAPIHTTP_R1326."); // Verify MS-OXCMAPIHTTP requirement: MS-OXCMAPIHTTP_R1326 this.Site.CaptureRequirementIfIsTrue( AdapterHelper.AreTwoAddressBookPropertyRowEqual(queryRowsResponseBody1.RowData, queryRowsResponseBody2.RowData), 1326, @"[In QueryRows Request Type Request Body] If this field [Flags] is set to different values other than the bit flag fEphID (0x00000002) and fSkipObjects (0x00000001), the server will return the same result."); #endregion #region Call QueryRows with HasState field set to false and HasColumns set to true. queryRowsRequestBody = this.BuildQueryRowsRequestBody(false, stat, tableCount, table, rowCount, true, columns); queryRowsResponseBody = this.Adapter.QueryRows(queryRowsRequestBody); Site.Assert.AreEqual<uint>((uint)0, queryRowsResponseBody.StatusCode, "QueryRows operation should succeed and 0 is expected to be returned. The return value is {0}.", queryRowsResponseBody.StatusCode); #endregion #region Call QueryRows with HasState field set to false and HasColumns set to false. queryRowsRequestBody = this.BuildQueryRowsRequestBody(false, stat, tableCount, table, rowCount, false, columns); queryRowsResponseBody = this.Adapter.QueryRows(queryRowsRequestBody); Site.Assert.AreEqual<uint>((uint)0, queryRowsResponseBody.StatusCode, "QueryRows operation should succeed and 0 is expected to be returned. The return value is {0}.", queryRowsResponseBody.StatusCode); #endregion #region Call QueryRows with HasState field set to true and HasColumns set to false. queryRowsRequestBody = this.BuildQueryRowsRequestBody(true, stat, tableCount, table, rowCount, false, columns); queryRowsResponseBody = this.Adapter.QueryRows(queryRowsRequestBody); Site.Assert.AreEqual<uint>((uint)0, queryRowsResponseBody.ErrorCode, "QueryRows operation should succeed and 0 is expected to be returned. The return value is {0}.", queryRowsResponseBody.ErrorCode); AddressBookPropertyRow[] rowData2 = queryRowsResponseBody.RowData; for (int i = 0; i < rowData2.Length; i++) { List<AddressBookPropertyValue> valueArray = new List<AddressBookPropertyValue>(rowData2[i].ValueArray); for (int j = 0; j < valueArray.Count; j++) { if (rowData2[i].Flag == 0x01) { // Add the debug information this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCMAPIHTTP_R453"); // Verify MS-OXCMAPIHTTP requirement: MS-OXCMAPIHTTP_R453 // In this step, the type of all properties required to be returned is not PtypUnspecified, that is, their type is specified. // So if the type of each value returned in the response is AddressBookFlaggedPropertyValue, MS-OXCMAPIHTTP_R451 can be verified. this.Site.CaptureRequirementIfIsInstanceOfType( valueArray[j], typeof(AddressBookFlaggedPropertyValue), 453, @"[In AddressBookPropertyRow Structure] [Flags] If the value of the Flags field is set to 0x1: The ValueArray field contains either an AddressBookFlaggedPropertyValue structure, see section 2.2.1.5, if the type of the property is specified."); AddressBookFlaggedPropertyValue flaggedPropertyValueForMapiHTTP = (AddressBookFlaggedPropertyValue)valueArray[j]; // Add the debug information this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCMAPIHTTP_R473"); // Verify MS-OXCMAPIHTTP requirement: MS-OXCDATA_R473 // In this step, the type of all properties required to be returned is not PtypUnspecified, that is, their type is specified. // So if the flag type of each value returned in the response is byte, MS-OXCMAPIHTTP_R473 can be verified. this.Site.CaptureRequirementIfIsInstanceOfType( flaggedPropertyValueForMapiHTTP.Flag, typeof(byte), "MS-OXCDATA", 473, @"[In FlaggedPropertyValue Structure] Flag (1 byte): An unsigned integer."); // Add the debug information this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCDATA_R475"); // Verify MS-OXCMAPIHTTP requirement: MS-OXCDATA_R475 // In this step, the type of all properties required to be returned is not PtypUnspecified, that is, their type is specified. // So if the value of Flag in the response is one of the values [0x0, 0x1, 0xA], MS-OXCDATA_R475 can be verified. bool isVerifiedR475 = flaggedPropertyValueForMapiHTTP.Flag == 0x0 || flaggedPropertyValueForMapiHTTP.Flag == 0x1 || flaggedPropertyValueForMapiHTTP.Flag == 0xA; this.Site.CaptureRequirementIfIsTrue( isVerifiedR475, "MS-OXCDATA", 475, @"[In FlaggedPropertyValue Structure] Flag (1 byte): The flag MUST be set to one of the values [0x0, 0x1, 0xA] in the following table."); // Add the debug information this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCMAPIHTTP_R2021"); //Since MS-OXCDATA_R475 is verified, MS-OXCMAPIHTTP_R2021 can be captured directly. this.Site.CaptureRequirement( 2021, @"[In AddressBookFlaggedPropertyValue Structure] [Flag]The flag MUST be set to one of the values [0x0, 0x1, 0xA] in the following table."); AddressBookFlaggedPropertyValue propertyValue = (AddressBookFlaggedPropertyValue)valueArray[j]; if (propertyValue.Flag != 0x01) { // Add the debug information this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCDATA_R479."); // Verify MS-OXCDATA requirement: MS-OXCDATA_R479 // If the value of property exists, it indicates that the PropertyValue field exists. this.Site.CaptureRequirementIfIsNotNull( propertyValue.Value, "MS-OXCDATA", 479, @"[In FlaggedPropertyValue Structure] PropertyValue (optional) (variable): A PropertyValue structure, as specified in section 2.11.2.1, unless the Flag field is set to 0x1."); if (propertyValue.Flag == 0x0) { // Add the debug information this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCDATA_R476."); // Verify MS-OXCDATA requirement: MS-OXCDATA_R476 // The parser code parses the PropertyValue field according to the property type. So R476 can be verified if the returned property value is not null. this.Site.CaptureRequirementIfIsNotNull( propertyValue.Value, "MS-OXCDATA", 476, @"[In FlaggedPropertyValue Structure] The Flag value 0x0 means the PropertyValue field will be a PropertyValue structure containing a value compatible with the property type implied by the context."); // Add the debug information this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCMAPIHTTP_R2022."); // Verify MS-OXCDATA requirement: MS-OXCMAPIHTTP_R2022 // The parser code parses the PropertyValue field according to the property type. So R2022 can be verified if the returned property value is not null. this.Site.CaptureRequirementIfIsNotNull( propertyValue.Value, 2022, @"[In AddressBookFlaggedPropertyValue Structure] Flag value 0x0 meaning The PropertyValue field will be an AddressBookPropertyValue structure (section 2.2.1.1) containing a value compatible with the property type implied by the context."); } } } } } #endregion #region Call the Unbind request type to destroy the session context. this.Unbind(); #endregion }
public void MSOXCMAPIHTTP_S02_TC10_GetMatchesRequestType() { this.CheckMapiHttpIsSupported(); #region Call Bind request type to established a session context with the address book server. this.Bind(); #endregion #region Call GetMatches request type without MinimalIds, PropertyNameGuid or PropertyNameId. STAT stat = new STAT(); stat.InitiateStat(); PropertyTag pidTagDisplayNameTag = new PropertyTag((ushort)PropertyID.PidTagDisplayName, (ushort)PropertyTypeValues.PtypString); LargePropertyTagArray propTagArray = new LargePropertyTagArray(); propTagArray.PropertyTagCount = 1; propTagArray.PropertyTags = new PropertyTag[] { pidTagDisplayNameTag }; ExistRestriction existRestriction = new ExistRestriction() { PropTag = new PropertyTag((ushort)PropertyID.PidTagEntryId, (ushort)PropertyTypeValues.PtypBinary) }; byte[] filter = existRestriction.Serialize(); Guid propertyGuid = new Guid(); uint propertyNameId = new uint(); GetMatchesRequestBody getMatchRequestBody = this.BuildGetMatchRequestBody(true, stat, false, 0, null, true, filter, false, propertyGuid, propertyNameId, ConstValues.GetMatchesRequestedRowNumber, true, propTagArray); GetMatchesResponseBody getMatchesResponseBody = this.Adapter.GetMatches(getMatchRequestBody); this.Site.Assert.AreEqual<uint>(0, getMatchesResponseBody.ErrorCode, "GetMatches request should be executed successfully, the returned error code is {0}", getMatchesResponseBody.ErrorCode); // Add the debug information this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCMAPIHTTP_R443, the return count of rows in GetMatchs response is {0}", getMatchesResponseBody.RowCount); // If ErrorCode field is 0x0000000 and the RowsCount has values, then server returns the Explicit Table. // So R443 will be verified. this.Site.CaptureRequirementIfIsTrue( getMatchesResponseBody.ErrorCode == 0 && getMatchesResponseBody.RowData != null, 443, @"[In GetMatches Request Type] The GetMatches request type is used by the client to get an Explicit Table, in which the rows are determined by the specified criteria."); #endregion #region Call GetMatches request type without State. STAT emptyStat = new STAT(); getMatchRequestBody = this.BuildGetMatchRequestBody(false, emptyStat, false, 0, null, true, filter, false, propertyGuid, propertyNameId, 1, true, propTagArray); getMatchesResponseBody = this.Adapter.GetMatches(getMatchRequestBody); this.Site.Assert.AreEqual<uint>(0, getMatchesResponseBody.StatusCode, "GetMatches request should be executed successfully, the returned error code is {0}", getMatchesResponseBody.StatusCode); #endregion #region Call the Unbind request type to destroy the session context. this.Unbind(); #endregion }
public void MSOXCMAPIHTTP_S02_TC06_ResortRestriction() { this.CheckMapiHttpIsSupported(); #region Call Bind request type to established a session context with the address book server. this.Bind(); #endregion #region Call DNToMId to get a set of Minimal Entry IDs. These IDs will be used as the parameter of ResortRestriction. StringArray_r names = new StringArray_r { CValues = 2, LppzA = new string[] { this.AdminUserDN, Common.GetConfigurationPropertyValue("GeneralUserEssdn", this.Site) } }; DNToMinIdRequestBody requestBodyOfDNToMId = this.BuildDNToMinIdRequestBody(true, names); DnToMinIdResponseBody responseBodyOfDNToMinId = this.Adapter.DnToMinId(requestBodyOfDNToMId); Site.Assert.AreEqual<uint>(0, responseBodyOfDNToMinId.ErrorCode, "DnToMinId should succeed and 0 is expected to be returned. The returned value is {0}.", responseBodyOfDNToMinId.ErrorCode); #endregion #region Call ResortRestriction to sort the objects in a restricted address book container. STAT stat = new STAT(); stat.InitiateStat(); ResortRestrictionRequestBody resortRestrictionRequestBody = this.BuildResortRestriction(true, stat, true, responseBodyOfDNToMinId.MinimalIdCount.Value, responseBodyOfDNToMinId.MinimalIds); ResortRestrictionResponseBody resortRestrictionResponseBody = this.Adapter.ResortRestriction(resortRestrictionRequestBody); Site.Assert.AreEqual<uint>(0, resortRestrictionResponseBody.ErrorCode, "ResortRestriction should succeed and 0 is expected to be returned. The returned value is {0}.", resortRestrictionResponseBody.ErrorCode); #endregion #region Call QueryRows method to query rows which contain the specific properties. LargePropertyTagArray columns = new LargePropertyTagArray { PropertyTagCount = 1, PropertyTags = new PropertyTag[1] { new PropertyTag { PropertyType = (ushort)PropertyTypeValues.PtypString, PropertyId = (ushort)PropertyID.PidTagDisplayName } } }; QueryRowsRequestBody queryRowsRequestBody = this.BuildQueryRowsRequestBody( true, resortRestrictionResponseBody.State.Value, resortRestrictionResponseBody.MinimalIdCount.Value, resortRestrictionResponseBody.MinimalIds, resortRestrictionResponseBody.MinimalIdCount.Value, true, columns); QueryRowsResponseBody queryRowsResponseBody = this.Adapter.QueryRows(queryRowsRequestBody); Site.Assert.AreEqual<uint>(0, queryRowsResponseBody.ErrorCode, "QueryRows should succeed and 0 is expected to be returned. The returned value is {0}.", queryRowsResponseBody.ErrorCode); bool isCorrectOrder = true; AddressBookPropertyRow[] rowData = queryRowsResponseBody.RowData; for (int i = 0; i < queryRowsResponseBody.RowCount - 1; i++) { List<AddressBookPropertyValue> valueArray1 = new List<AddressBookPropertyValue>(rowData[i].ValueArray); List<AddressBookPropertyValue> valueArray2 = new List<AddressBookPropertyValue>(rowData[i + 1].ValueArray); if (string.Compare(valueArray1[0].Value.ToString(), valueArray2[0].Value.ToString()) > 0) { isCorrectOrder = false; break; } } // Add the debug information this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCMAPIHTTP_R958"); // Verify MS-OXCMAPIHTTP requirement: MS-OXCMAPIHTTP_R958 this.Site.CaptureRequirementIfIsTrue( isCorrectOrder, 958, @"[In ResortRestriction Request Type] The ResortRestriction request type is used by the client to sort the objects in a restricted address book container."); #endregion #region Call ResortRestriction without state or minimal IDs. ResortRestrictionRequestBody resortRestrictionRequestBody2 = this.BuildResortRestriction(false, stat, false, responseBodyOfDNToMinId.MinimalIdCount.Value, responseBodyOfDNToMinId.MinimalIds); ResortRestrictionResponseBody resortRestrictionResponseBody2 = this.Adapter.ResortRestriction(resortRestrictionRequestBody2); Site.Assert.AreEqual<uint>(0, resortRestrictionResponseBody2.StatusCode, "ResortRestriction should succeed and 0 is expected to be returned. The returned value is {0}.", resortRestrictionResponseBody2.StatusCode); #endregion #region Call ResortRestriction with state and without minimal IDs. ResortRestrictionRequestBody resortRestrictionRequestBody3 = this.BuildResortRestriction(true, stat, false, responseBodyOfDNToMinId.MinimalIdCount.Value, responseBodyOfDNToMinId.MinimalIds); ResortRestrictionResponseBody resortRestrictionResponseBody3 = this.Adapter.ResortRestriction(resortRestrictionRequestBody3); Site.Assert.AreEqual<uint>(0, resortRestrictionResponseBody3.StatusCode, "ResortRestriction should succeed and 0 is expected to be returned. The returned value is {0}.", resortRestrictionResponseBody3.StatusCode); #endregion #region Call ResortRestriction without state but with minimal IDs. ResortRestrictionRequestBody resortRestrictionRequestBody4 = this.BuildResortRestriction(false, stat, true, responseBodyOfDNToMinId.MinimalIdCount.Value, responseBodyOfDNToMinId.MinimalIds); ResortRestrictionResponseBody resortRestrictionResponseBody4 = this.Adapter.ResortRestriction(resortRestrictionRequestBody4); Site.Assert.AreEqual<uint>(0, resortRestrictionResponseBody4.StatusCode, "ResortRestriction should succeed and 0 is expected to be returned. The returned value is {0}.", resortRestrictionResponseBody4.StatusCode); #endregion #region Call the Unbind request type to destroy the session context. this.Unbind(); #endregion }
/// <summary> /// Build the GetMatches request body. /// </summary> /// <param name="hasState">A Boolean value that specifies whether the State field is present.</param> /// <param name="state">A STAT structure that specifies the state of a specific address book container. </param> /// <param name="hasTarget">A Boolean value that specifies whether the Target field is present.</param> /// <param name="target">A PropertyValue_r structure that specifies the property value being sought.</param> /// <param name="hasExplicitTable">A Boolean value that specifies whether the ExplicitTableCount and ExplicitTable fields are present.</param> /// <param name="explicitableCount">An unsigned integer that specifies the number of structures present in the ExplicitTable field.</param> /// <param name="explicitTable">An array of unsigned integer that constitute an Explicit Table.</param> /// <param name="hasColumns">A Boolean value that specifies whether the Columns field is present.</param> /// <param name="columns">A LargePropTagArray structure that specifies the columns that the client is requesting.</param> /// <returns>Return an instance of SeekEntriesRequestBody class.</returns> private SeekEntriesRequestBody BuildSeekEntriesRequestBody(bool hasState, STAT state, bool hasTarget, PropertyValue_r target, bool hasExplicitTable, uint explicitableCount, uint[] explicitTable, bool hasColumns, LargePropertyTagArray columns) { SeekEntriesRequestBody requestBody = new SeekEntriesRequestBody(); // Reserved. The client MUST set this field to 0x00000000 and the server MUST ignore this field. requestBody.Reserved = 0x00000000; requestBody.HasState = hasState; if (hasState) { requestBody.State = state; } requestBody.HasTarget = hasTarget; if (hasTarget) { requestBody.Target = target; } requestBody.HasExplicitTable = hasExplicitTable; if (hasExplicitTable) { requestBody.ExplicitableCount = explicitableCount; requestBody.ExplicitTable = explicitTable; } requestBody.HasColumns = hasColumns; if (hasColumns) { requestBody.Columns = columns; } requestBody.AuxiliaryBufferSize = 0; requestBody.AuxiliaryBuffer = new byte[] { }; return requestBody; }
public void MSOXCMAPIHTTP_S02_TC17_ModProps() { this.CheckMapiHttpIsSupported(); #region Call Bind request type to established a session context with the address book server. this.Bind(); #endregion #region Call DNToMId to get the MIDs of specified user. STAT stat = new STAT(); stat.InitiateStat(); byte[] auxIn = new byte[] { }; uint reserved = 0; string userESSDN = this.AdminUserDN; DNToMinIdRequestBody requestBodyOfDNToMId = new DNToMinIdRequestBody() { Reserved = reserved, HasNames = true, Names = new StringArray_r { CValues = 1, LppzA = new string[] { userESSDN } }, AuxiliaryBuffer = auxIn, AuxiliaryBufferSize = (uint)auxIn.Length }; DnToMinIdResponseBody responseBodyOfdnToMinId = this.Adapter.DnToMinId(requestBodyOfDNToMId); this.Site.Assert.AreEqual((uint)0, responseBodyOfdnToMinId.ErrorCode, "DnToMinId method should be succeed and 0 is expected to be returned. The returned value is {0}.", responseBodyOfdnToMinId.ErrorCode); #endregion #region Call GetMatches to get the specific PidTagAddressBookX509Certificate property to be modified. stat.CurrentRec = responseBodyOfdnToMinId.MinimalIds[0]; uint[] minimalIds = new uint[1] { (uint)responseBodyOfdnToMinId.MinimalIds[0] }; byte[] filter = new byte[] { }; Guid propertyGuid = new Guid(); uint propertyNameId = new uint(); LargePropertyTagArray columns = new LargePropertyTagArray { PropertyTagCount = 1, PropertyTags = new PropertyTag[] { new PropertyTag { PropertyType = (ushort)PropertyTypeValues.PtypMultipleBinary, PropertyId = (ushort)PropertyID.PidTagAddressBookX509Certificate } } }; GetMatchesRequestBody getMatchRequestBody = this.BuildGetMatchRequestBody(true, stat, true, 1, minimalIds, false, filter, false, propertyGuid, propertyNameId, 1, true, columns); GetMatchesResponseBody getMatchResponseBody = this.Adapter.GetMatches(getMatchRequestBody); this.Site.Assert.AreEqual((uint)0, getMatchResponseBody.ErrorCode, "GetMatches method should be succeed and 0 is expected to be returned. The returned value is {0}.", getMatchResponseBody.ErrorCode); #endregion #region Call ModProps request type with all optional fields. PropertyTag[] propertyTags = new PropertyTag[1]; propertyTags[0].PropertyId = (ushort)PropertyID.PidTagAddressBookX509Certificate; propertyTags[0].PropertyType = (ushort)PropertyTypeValues.PtypMultipleBinary; LargePropertyTagArray propertyTagsToRemove = new LargePropertyTagArray() { PropertyTagCount = 1, PropertyTags = new PropertyTag[] { new PropertyTag { PropertyType = (ushort)PropertyTypeValues.PtypMultipleBinary, PropertyId = (ushort)PropertyID.PidTagAddressBookX509Certificate } } }; ModPropsRequestBody modPropsRequestBody = this.BuildModPropsRequestBody(true, getMatchResponseBody.State.Value, true, propertyTags[0], true, propertyTagsToRemove); ModPropsResponseBody modPropsResponseBody = this.Adapter.ModProps(modPropsRequestBody); Site.Assert.AreEqual<uint>((uint)0, modPropsResponseBody.StatusCode, "ModProps request should succeed and 0 is expected to be returned. The return value is {0}.", modPropsResponseBody.StatusCode); #endregion #region Call ModProps request type without all optional fields. ModPropsRequestBody modPropsRequestBody1 = this.BuildModPropsRequestBody(false, getMatchResponseBody.State.Value, false, propertyTags[0], false, propertyTagsToRemove); ModPropsResponseBody modPropsResponseBody1 = this.Adapter.ModProps(modPropsRequestBody); Site.Assert.AreEqual<uint>((uint)0, modPropsResponseBody1.StatusCode, "ModProps request should succeed and 0 is expected to be returned. The return value is {0}.", modPropsResponseBody1.StatusCode); #endregion #region Call ModProps request type without PropertyTagsToRemove field. ModPropsRequestBody modPropsRequestBody2 = this.BuildModPropsRequestBody(true, getMatchResponseBody.State.Value, true, propertyTags[0], false, propertyTagsToRemove); ModPropsResponseBody modPropsResponseBody2 = this.Adapter.ModProps(modPropsRequestBody); Site.Assert.AreEqual<uint>((uint)0, modPropsResponseBody2.StatusCode, "ModProps request should succeed and 0 is expected to be returned. The return value is {0}.", modPropsResponseBody2.StatusCode); #endregion #region Call ModProps request type without PropertyValues field. ModPropsRequestBody modPropsRequestBody3 = this.BuildModPropsRequestBody(true, getMatchResponseBody.State.Value, false, propertyTags[0], true, propertyTagsToRemove); ModPropsResponseBody modPropsResponseBody3 = this.Adapter.ModProps(modPropsRequestBody); Site.Assert.AreEqual<uint>((uint)0, modPropsResponseBody3.StatusCode, "ModProps request should succeed and 0 is expected to be returned. The return value is {0}.", modPropsResponseBody3.StatusCode); #endregion #region Call ModProps request type without PropertyValues and state fields. ModPropsRequestBody modPropsRequestBody4 = this.BuildModPropsRequestBody(false, getMatchResponseBody.State.Value, false, propertyTags[0], true, propertyTagsToRemove); ModPropsResponseBody modPropsResponseBody4 = this.Adapter.ModProps(modPropsRequestBody); Site.Assert.AreEqual<uint>((uint)0, modPropsResponseBody4.StatusCode, "ModProps request should succeed and 0 is expected to be returned. The return value is {0}.", modPropsResponseBody4.StatusCode); #endregion #region Call ModProps request type without PropertyTagsToRemove and state fields. ModPropsRequestBody modPropsRequestBody5 = this.BuildModPropsRequestBody(false, getMatchResponseBody.State.Value, true, propertyTags[0], false, propertyTagsToRemove); ModPropsResponseBody modPropsResponseBody5 = this.Adapter.ModProps(modPropsRequestBody); Site.Assert.AreEqual<uint>((uint)0, modPropsResponseBody5.StatusCode, "ModProps request should succeed and 0 is expected to be returned. The return value is {0}.", modPropsResponseBody5.StatusCode); #endregion #region Call the Unbind request type to destroy the session context. this.Unbind(); #endregion }
public void MSOXCMAPIHTTP_S02_TC13_SeekEntriesRequestType() { this.CheckMapiHttpIsSupported(); #region Call Bind request type to established a session context with the address book server. this.Bind(); #endregion #region Call QueryRows request type with propTags set to null. STAT stat = new STAT(); stat.InitiateStat(); LargePropertyTagArray columns = new LargePropertyTagArray(); QueryRowsRequestBody queryRowsRequestBody = this.BuildQueryRowsRequestBody(true, stat, 0, null, ConstValues.QueryRowsRequestedRowNumber, false, columns); QueryRowsResponseBody queryRowsResponseBody = this.Adapter.QueryRows(queryRowsRequestBody); Site.Assert.AreEqual<uint>((uint)0, queryRowsResponseBody.ErrorCode, "QueryRows operation should succeed and 0 is expected to be returned. The return value is {0}.", queryRowsResponseBody.ErrorCode); uint[] outMids = new uint[queryRowsResponseBody.RowCount.Value]; for (int i = 0; i < queryRowsResponseBody.RowCount; i++) { outMids[i] = BitConverter.ToUInt32(queryRowsResponseBody.RowData[i].ValueArray[0].Value, 0); } stat = queryRowsResponseBody.State.Value; #endregion #region Call UpdateStat request type to update the STAT block that represents the position in a table to reflect positioning changes requested by the client. stat.Delta = 1; byte[] auxIn = new byte[] { }; UpdateStatRequestBody updateStatRequestBody = this.BuildUpdateStatRequestBody(true, stat, true); UpdateStatResponseBody updateStatResponseBody = this.Adapter.UpdateStat(updateStatRequestBody); Site.Assert.AreEqual<uint>(0, updateStatResponseBody.ErrorCode, "UpdateStat should succeed and 0 is expected to be returned. The returned value is {0}.", updateStatResponseBody.ErrorCode); #endregion #region Call SeekEntries request type which contains fields State, Trage and Columns. PropertyTag pidTagDisplayNameTag = new PropertyTag((ushort)PropertyID.PidTagDisplayName, (ushort)PropertyTypeValues.PtypString); string displayName = Common.GetConfigurationPropertyValue("GeneralUserName", this.Site) + "\0"; PropertyValue_r target = new PropertyValue_r() { PropTag = pidTagDisplayNameTag, Reserved = 0, Value = System.Text.Encoding.Unicode.GetBytes(displayName) }; columns = new LargePropertyTagArray() { PropertyTagCount = 1, PropertyTags = new PropertyTag[1] { target.PropTag } }; SeekEntriesRequestBody seekEntriesRequestBody = this.BuildSeekEntriesRequestBody(true, updateStatResponseBody.State.Value, true, target, true, (uint)outMids.Length, outMids, true, columns); SeekEntriesResponseBody seekEntriesResponseBody = this.Adapter.SeekEntries(seekEntriesRequestBody); Site.Assert.AreEqual<uint>(0, seekEntriesResponseBody.ErrorCode, "SeekEntries should succeed and 0 is expected to be returned. The returned value is {0}.", seekEntriesResponseBody.ErrorCode); #endregion #region Call QueryRows request type using a new list of minimal entry ids as input parameter according to the parameters of SeekEntries request type response. uint[] newTable = new uint[outMids.Length - (int)seekEntriesResponseBody.State.Value.NumPos]; Array.Copy(outMids, (int)seekEntriesResponseBody.State.Value.NumPos, newTable, 0, newTable.Length); queryRowsRequestBody = this.BuildQueryRowsRequestBody(true, stat, (uint)newTable.Length, newTable, ConstValues.QueryRowsRequestedRowNumber, true, columns); queryRowsRequestBody.Flags = (uint)RetrievePropertyFlags.fEphID; queryRowsResponseBody = this.Adapter.QueryRows(queryRowsRequestBody); Site.Assert.AreEqual<uint>((uint)0, queryRowsResponseBody.StatusCode, "QueryRows operation should succeed and 0 is expected to be returned. The return value is {0}.", queryRowsResponseBody.StatusCode); if (seekEntriesResponseBody.HasColumnsAndRows == false) { seekEntriesResponseBody = this.Adapter.SeekEntries(seekEntriesRequestBody); Site.Assert.AreEqual<uint>(0, seekEntriesResponseBody.ErrorCode, "SeekEntries should succeed and 0 is expected to be returned. The returned value is {0}.", seekEntriesResponseBody.ErrorCode); } // Add the debug information this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCMAPIHTTP_R1013"); // If the RowData is not Null, then client retrieves information about rows in an Explicit Table by the SeekEntries request type. // So R1013 will be verified. this.Site.CaptureRequirementIfIsTrue( seekEntriesResponseBody.ErrorCode == 0x00000000 && seekEntriesResponseBody.RowData != null, 1013, @"[In SeekEntries Request Type] Optionally, the SeekEntries request type can also be used to retrieve information about rows in an Explicit Table."); bool isTheValueGreaterThanOrEqualTo = false; for (int i = 0; i < seekEntriesResponseBody.RowData.Length; i++) { // Check whether the returned property value is greater than or equal to the input property PidTagDisplayName. string dispalyNameReturnedFromServer = System.Text.Encoding.UTF8.GetString(seekEntriesResponseBody.RowData[i].ValueArray[0].Value); // Value Condition greater than zero indicates the returned property value follows the input PidTagDisplayName property value. int result = dispalyNameReturnedFromServer.CompareTo(displayName); if (result < 0) { this.Site.Log.Add(LogEntryKind.Debug, "The display name returned from server is {0}, the expected display name is {1}", dispalyNameReturnedFromServer.Replace("\0", string.Empty), displayName.Replace("\0", string.Empty)); isTheValueGreaterThanOrEqualTo = false; break; } else { isTheValueGreaterThanOrEqualTo = true; } } // Add the debug information this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCMAPIHTTP_R1012"); this.Site.CaptureRequirementIfIsTrue( isTheValueGreaterThanOrEqualTo, 1012, @"[In SeekEntries Request Type] The SeekEntries request type is used by the client to search for and set the logical position in a specific table to the first entry greater than or equal to a specified value."); bool isLargePropertyTagArrayEqual = AdapterHelper.AreTwoLargePropertyTagArrayEqual(seekEntriesRequestBody.Columns, seekEntriesResponseBody.Columns.Value); // Add the debug information this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCMAPIHTTP_R1047"); this.Site.CaptureRequirementIfIsTrue( isLargePropertyTagArrayEqual, 1047, @"[In SeekEntries Request Type Success Response Body] Columns (optional) (variable): A LargePropTagArray structure (section 2.2.1.3) that specifies the columns used for the rows returned."); // Add the debug information this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCMAPIHTTP_R1053"); // Verify MS-OXCMAPIHTTP requirement: MS-OXCMAPIHTTP_R1053 this.Site.CaptureRequirementIfIsInstanceOfType( seekEntriesResponseBody.RowData, typeof(AddressBookPropertyRow[]), 1053, @"[In SeekEntries Request Type Success Response Body] RowData (optional) (variable): An array of AddressBookPropertyRow structures (section 2.2.1.2), each of which specifies the row data for the entries queried."); #endregion #region Call SeekEntries request type without State field. seekEntriesRequestBody = this.BuildSeekEntriesRequestBody(false, stat, true, target, false, 0, null, true, columns); seekEntriesResponseBody = this.Adapter.SeekEntries(seekEntriesRequestBody); Site.Assert.AreEqual<uint>(0, seekEntriesResponseBody.StatusCode, "SeekEntries should succeed and 0 is expected to be returned. The returned value is {0}.", seekEntriesResponseBody.StatusCode); #endregion #region Call the Unbind request type to destroy the session context. this.Unbind(); #endregion }
/// <summary> /// Build the GetMatches request body. /// </summary> /// <param name="hasState">A Boolean value that specifies whether the State field is present.</param> /// <param name="state">A STAT structure that specifies the state of a specific address book container.</param> /// <param name="hasMinimalIds">A Boolean value that specifies whether the MinimalIdCount and MinimalIds fields are present.</param> /// <param name="minimalIdCount">An unsigned integer that specifies the number of structures present in the MinimalIds field.</param> /// <param name="minimalIds">An array of MinimalEntryID structures that constitute an Explicit Table.</param> /// <param name="hasFilter">A Boolean value that specifies whether the Filter field is present.</param> /// <param name="filter">A restriction that is to be applied to the rows in the address book container.</param> /// <param name="hasPropertyName">A Boolean value that specifies whether the PropertyNameGuid and PropertyNameId fields are present.</param> /// <param name="propertyNameGuid">The GUID of the property to be opened.</param> /// <param name="propertyNameId">A 4-byte value that specifies the ID of the property to be opened.</param> /// <param name="rowCount">An unsigned integer that specifies the number of rows the client is requesting.</param> /// <param name="hasColumns">A Boolean value that specifies whether the Columns field is present.</param> /// <param name="columns">A LargePropertyTagArray structure that specifies the columns that the client is requesting.</param> /// <returns>The GetMatches request body.</returns> private GetMatchesRequestBody BuildGetMatchRequestBody(bool hasState, STAT state, bool hasMinimalIds, uint minimalIdCount, uint[] minimalIds, bool hasFilter, byte[] filter, bool hasPropertyName, Guid propertyNameGuid, uint propertyNameId, uint rowCount, bool hasColumns, LargePropertyTagArray columns) { GetMatchesRequestBody getMatchRequestBody = new GetMatchesRequestBody(); getMatchRequestBody.Reserved = 0x0; getMatchRequestBody.HasState = hasState; if (hasState) { getMatchRequestBody.State = state; } getMatchRequestBody.HasMinimalIds = hasMinimalIds; if (hasMinimalIds) { getMatchRequestBody.MinimalIdCount = minimalIdCount; getMatchRequestBody.MinimalIds = minimalIds; } getMatchRequestBody.InterfaceOptionFlags = 0x0; getMatchRequestBody.HasFilter = hasFilter; if (hasFilter) { getMatchRequestBody.Filter = filter; } getMatchRequestBody.HasPropertyName = hasPropertyName; if (hasPropertyName) { getMatchRequestBody.PropertyNameGuid = propertyNameGuid; getMatchRequestBody.PropertyNameId = propertyNameId; } getMatchRequestBody.RowCount = rowCount; getMatchRequestBody.HasColumns = hasColumns; if (hasColumns) { getMatchRequestBody.Columns = columns; } byte[] auxIn = new byte[] { }; getMatchRequestBody.AuxiliaryBuffer = auxIn; getMatchRequestBody.AuxiliaryBufferSize = (uint)auxIn.Length; return getMatchRequestBody; }
public void MSOXCMAPIHTTP_S02_TC21_TestHasValueWithPropertyTypePtypMultipleString() { this.CheckMapiHttpIsSupported(); byte[] auxIn = new byte[] { }; #region Call Bind request type to established a session context with the address book server. this.Bind(); #endregion #region Call QueryRows request type to get a set of valid rows used to matched entry ID as the input paramter of ModLinkAtt method. STAT stat = new STAT(); stat.InitiateStat(); uint tableCount = 0; uint[] table = null; LargePropertyTagArray largePropTagArray = new LargePropertyTagArray() { PropertyTagCount = 4, PropertyTags = new PropertyTag[] { new PropertyTag { PropertyType = (ushort)PropertyTypeValues.PtypString, PropertyId = (ushort)PropertyID.PidTagDisplayName }, new PropertyTag { PropertyType = (ushort)PropertyTypeValues.PtypBinary, PropertyId = (ushort)PropertyID.PidTagEntryId }, new PropertyTag { PropertyType = (ushort)PropertyTypeValues.PtypInteger32, PropertyId = (ushort)PropertyID.PidTagDisplayType }, new PropertyTag { PropertyType = (ushort)PropertyTypeValues.PtypMultipleString, PropertyId = (ushort)PropertyID.PidTagAddressBookMember } } }; QueryRowsRequestBody queryRowsRequestBody = new QueryRowsRequestBody(); queryRowsRequestBody.Flags = (uint)RetrievePropertyFlags.fSkipObjects; queryRowsRequestBody.HasState = true; queryRowsRequestBody.State = stat; queryRowsRequestBody.ExplicitTableCount = tableCount; queryRowsRequestBody.ExplicitTable = table; queryRowsRequestBody.RowCount = ConstValues.QueryRowsRequestedRowNumber; queryRowsRequestBody.HasColumns = true; queryRowsRequestBody.Columns = largePropTagArray; queryRowsRequestBody.AuxiliaryBuffer = auxIn; queryRowsRequestBody.AuxiliaryBufferSize = (uint)auxIn.Length; QueryRowsResponseBody queryRowsResponseBody = this.Adapter.QueryRows(queryRowsRequestBody); Site.Assert.AreEqual<uint>(0, queryRowsResponseBody.ErrorCode, "QueryRows request should be executed successfully, the returned value {0}.", queryRowsResponseBody.ErrorCode); #endregion #region Call ModLinkAtt with flags 0x00000000 to add the specified PidTagAddressBookMember value. uint flagsOfModLinkAtt = 0; PropertyTag propTagOfModLinkAtt = new PropertyTag { PropertyType = (ushort)PropertyTypeValues.PtypEmbeddedTable, PropertyId = (ushort)PropertyID.PidTagAddressBookMember }; uint midOfModLinkAtt = 0; byte[] entryId = null; GetPropsRequestBody getPropsRequestBodyForAddressBookMember = null; uint lengthOfErrorCodeValue = sizeof(uint); string dlistName = Common.GetConfigurationPropertyValue("DistributionListName", this.Site); string memberName = Common.GetConfigurationPropertyValue("GeneralUserName", this.Site); for (int i = 0; i < queryRowsResponseBody.RowCount; i++) { string name = System.Text.Encoding.Unicode.GetString(queryRowsResponseBody.RowData[i].ValueArray[0].Value); if (name.ToLower().Contains(dlistName.ToLower())) { PermanentEntryID entryID = AdapterHelper.ParsePermanentEntryIDFromBytes(queryRowsResponseBody.RowData[i].ValueArray[1].Value); DNToMinIdRequestBody requestBodyOfDNToMId = new DNToMinIdRequestBody() { Reserved = 0, HasNames = true, Names = new StringArray_r { CValues = 1, LppzA = new string[] { entryID.DistinguishedName } }, AuxiliaryBuffer = auxIn, AuxiliaryBufferSize = (uint)auxIn.Length }; DnToMinIdResponseBody responseBodyOfDNToMinId = this.Adapter.DnToMinId(requestBodyOfDNToMId); midOfModLinkAtt = responseBodyOfDNToMinId.MinimalIds[0]; stat.CurrentRec = midOfModLinkAtt; STAT? statForGetProps = stat; LargePropertyTagArray propertyTagForGetProps = new LargePropertyTagArray() { PropertyTagCount = 2, PropertyTags = new PropertyTag[] { new PropertyTag { PropertyType = (ushort)PropertyTypeValues.PtypInteger32, PropertyId = (ushort)PropertyID.PidTagDisplayType }, new PropertyTag { PropertyType = (ushort)PropertyTypeValues.PtypMultipleString, PropertyId = (ushort)PropertyID.PidTagAddressBookMember }, } }; getPropsRequestBodyForAddressBookMember = this.BuildGetPropsRequestBody((uint)0, true, statForGetProps, true, propertyTagForGetProps); GetPropsResponseBody getPropsResponseBody = this.Adapter.GetProps(getPropsRequestBodyForAddressBookMember); this.Site.Assert.AreEqual<uint>(0, getPropsResponseBody.StatusCode, "The GetProps request should be executed successfully, the returned status code is {0}", getPropsResponseBody.StatusCode); this.Site.Assert.AreEqual<uint>(lengthOfErrorCodeValue, (uint)getPropsResponseBody.PropertyValues.Value.PropertyValues[1].Value.Length, "The length of the property value should be equal the ErrorCodeValue: Not Found(0x8004010F)"); uint propertyValue = BitConverter.ToUInt32(getPropsResponseBody.PropertyValues.Value.PropertyValues[1].Value, 0); this.Site.Assert.AreEqual<uint>((uint)ErrorCodeValue.NotFound, propertyValue, "The property value of AddressBookMember should be Not Found(0x8004010F), actual value is {0}", propertyValue); } else if (name.ToLower().Contains(memberName.ToLower())) { entryId = queryRowsResponseBody.RowData[i].ValueArray[1].Value; } if (midOfModLinkAtt != 0 && entryId != null) { break; } } ModLinkAttRequestBody modLinkAttRequestBody = new ModLinkAttRequestBody(); modLinkAttRequestBody.Flags = flagsOfModLinkAtt; modLinkAttRequestBody.PropertyTag = propTagOfModLinkAtt; modLinkAttRequestBody.MinimalId = midOfModLinkAtt; modLinkAttRequestBody.HasEntryIds = true; modLinkAttRequestBody.EntryIdCount = 1; modLinkAttRequestBody.EntryIDs = new byte[][] { entryId }; modLinkAttRequestBody.AuxiliaryBuffer = auxIn; modLinkAttRequestBody.AuxiliaryBufferSize = (uint)auxIn.Length; this.minimalIDForDeleteAddressBookMember = midOfModLinkAtt; this.entryIDBufferForDeleteAddressBookMember = entryId; this.isAddressBookMemberDeleted = false; ModLinkAttResponseBody modLinkAttResponseBodyOfAdd = this.Adapter.ModLinkAtt(modLinkAttRequestBody); GetPropsResponseBody getPropsResponseBodyForAddAddressBookMember = this.Adapter.GetProps(getPropsRequestBodyForAddressBookMember); uint modifyDisplayType = BitConverter.ToUInt32(getPropsResponseBodyForAddAddressBookMember.PropertyValues.Value.PropertyValues[0].Value, 0); int propertyValuelength = getPropsResponseBodyForAddAddressBookMember.PropertyValues.Value.PropertyValues[1].Value.Length; if (getPropsResponseBodyForAddAddressBookMember.PropertyValues.Value.PropertyValues[1].PropertyType == 0x101F) { // Add the debug information this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCMAPIHTTP_R2257"); // Verify MS-OXCMAPIHTTP requirement: MS-OXCMAPIHTTP_R2257 this.Site.CaptureRequirementIfIsInstanceOfType( getPropsResponseBodyForAddAddressBookMember.PropertyValues.Value.PropertyValues[1].HasValue, typeof(byte), 2257, @"[In AddressBookPropertyValue Structure] HasValue (optional) (1 byte): An unsigned integer when the PropertyType ([MS-OXCDATA] section 2.11.1) is known to be PtypMultipleString ([MS-OXCDATA] section 2.11.1)."); } #endregion #region Call ModLinkAtt to delete the specified PidTagAddressBookMember value. modLinkAttRequestBody.Flags = 1; ModLinkAttResponseBody modLinkAttResponseBodyOfDelete = this.Adapter.ModLinkAtt(modLinkAttRequestBody); Site.Assert.AreEqual<uint>(0, modLinkAttResponseBodyOfDelete.ErrorCode, "ModLinkAtt request should be executed successfully, the returned error code is {0}.", modLinkAttResponseBodyOfDelete.ErrorCode); this.isAddressBookMemberDeleted = true; #endregion #region Call Unbind request to destroy the session between the client and the server. this.Unbind(); #endregion }
public void MSOXCMAPIHTTP_S02_TC20_TestHasValueWithPropertyTypePtypString8() { this.CheckMapiHttpIsSupported(); #region Call Bind request type to established a session context with the address book server. this.Bind(); #endregion #region Call QueryRows with all optional fields exist and the type of all properties specified. uint tableCount = 0; uint[] table = null; uint rowCount = ConstValues.QueryRowsRequestedRowNumber; STAT stat = new STAT(); stat.InitiateStat(); LargePropertyTagArray columns = new LargePropertyTagArray() { PropertyTagCount = 1, PropertyTags = new PropertyTag[] { new PropertyTag { PropertyType = (ushort)PropertyTypeValues.PtypString8, PropertyId = (ushort)PropertyID.PidTagDisplayName } } }; QueryRowsRequestBody queryRowsRequestBody = this.BuildQueryRowsRequestBody(true, stat, tableCount, table, rowCount, true, columns); QueryRowsResponseBody queryRowsResponseBody = this.Adapter.QueryRows(queryRowsRequestBody); Site.Assert.AreEqual<uint>((uint)0, queryRowsResponseBody.ErrorCode, "QueryRows operation should succeed and 0 is expected to be returned. The return value is {0}.", queryRowsResponseBody.ErrorCode); #endregion #region Capture code AddressBookPropertyRow[] rowData = queryRowsResponseBody.RowData; for (int i = 0; i < rowData.Length; i++) { List<AddressBookPropertyValue> valueArray = new List<AddressBookPropertyValue>(rowData[i].ValueArray); for (int j = 0; j < valueArray.Count; j++) { if (columns.PropertyTags[j].PropertyType == 0x1E) { // Add the debug information this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCMAPIHTTP_R2002"); // Verify MS-OXCMAPIHTTP requirement: MS-OXCMAPIHTTP_R2002 this.Site.CaptureRequirementIfIsInstanceOfType( valueArray[j].HasValue, typeof(byte), 2002, @"[In AddressBookPropertyValue Structure] HasValue (optional) (1 byte): An unsigned integer when the PropertyType ([MS-OXCDATA] section 2.11.1) is known to be PtypString8."); } } } #endregion #region Call Unbind request to destroy the session between the client and the server. this.Unbind(); #endregion }
public void MSOXCMAPIHTTP_S02_TC19_TestFlagWithPtypErrorCode() { this.CheckMapiHttpIsSupported(); #region Call Bind request type to established a session context with the address book server. this.Bind(); #endregion #region Call QueryRows with all optional fields exist and the type of all properties specified. uint tableCount = 0; uint[] table = null; uint rowCount = ConstValues.QueryRowsRequestedRowNumber; STAT stat = new STAT(); stat.InitiateStat(); LargePropertyTagArray columns = new LargePropertyTagArray() { PropertyTagCount = 1, PropertyTags = new PropertyTag[] { new PropertyTag { PropertyType = (ushort)PropertyType.PtypErrorCode, PropertyId = (ushort)PropertyID.PidTagDisplayName } } }; QueryRowsRequestBody queryRowsRequestBody = this.BuildQueryRowsRequestBody(true, stat, tableCount, table, rowCount, true, columns); QueryRowsResponseBody queryRowsResponseBody = this.Adapter.QueryRows(queryRowsRequestBody); Site.Assert.AreEqual<uint>((uint)0, queryRowsResponseBody.ErrorCode, "QueryRows operation should succeed and 0 is expected to be returned. The return value is {0}.", queryRowsResponseBody.ErrorCode); #endregion #region Capture code AddressBookPropertyRow[] rowData = queryRowsResponseBody.RowData; for (int i = 0; i < rowData.Length; i++) { List<AddressBookPropertyValue> valueArray = new List<AddressBookPropertyValue>(rowData[i].ValueArray); for (int j = 0; j < valueArray.Count; j++) { AddressBookFlaggedPropertyValue propertyValue = (AddressBookFlaggedPropertyValue)valueArray[j]; if (propertyValue.Flag == 0xA) { bool isVerifyR2024 = propertyValue.Value != null && columns.PropertyTags[j].PropertyType == 10; // Add the debug information this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCMAPIHTTP_R2024."); // Verify MS-OXCDATA requirement: MS-OXCMAPIHTTP_R2024 this.Site.CaptureRequirementIfIsTrue( isVerifyR2024, 2024, @"[In AddressBookFlaggedPropertyValue Structure] Flag value 0xA meaning The PropertyValue field will be an AddressBookPropertyValue structure containing a value of PtypErrorCode, as specified in [MS-OXCDATA] section 2.11.1. "); } } } #endregion #region Call Unbind request to destroy the session between the client and the server. this.Unbind(); #endregion }
public void MSOXCMAPIHTTP_S02_TC18_ModLinkAttRequestType() { this.CheckMapiHttpIsSupported(); byte[] auxIn = new byte[] { }; #region Call Bind request type to established a session context with the address book server. this.Bind(); #endregion #region Call QueryRows request type to get a set of valid rows used to matched entry ID as the input paramter of ModLinkAtt method. STAT stat = new STAT(); stat.InitiateStat(); uint tableCount = 0; uint[] table = null; LargePropertyTagArray largePropTagArray = new LargePropertyTagArray() { PropertyTagCount = 4, PropertyTags = new PropertyTag[] { new PropertyTag { PropertyType = (ushort)PropertyTypeValues.PtypString, PropertyId = (ushort)PropertyID.PidTagDisplayName }, new PropertyTag { PropertyType = (ushort)PropertyTypeValues.PtypBinary, PropertyId = (ushort)PropertyID.PidTagEntryId }, new PropertyTag { PropertyType = (ushort)PropertyTypeValues.PtypInteger32, PropertyId = (ushort)PropertyID.PidTagDisplayType }, new PropertyTag { PropertyType = (ushort)PropertyTypeValues.PtypMultipleString8, PropertyId = (ushort)PropertyID.PidTagAddressBookMember } } }; QueryRowsRequestBody queryRowsRequestBody = new QueryRowsRequestBody(); queryRowsRequestBody.Flags = (uint)RetrievePropertyFlags.fSkipObjects; queryRowsRequestBody.HasState = true; queryRowsRequestBody.State = stat; queryRowsRequestBody.ExplicitTableCount = tableCount; queryRowsRequestBody.ExplicitTable = table; queryRowsRequestBody.RowCount = ConstValues.QueryRowsRequestedRowNumber; queryRowsRequestBody.HasColumns = true; queryRowsRequestBody.Columns = largePropTagArray; queryRowsRequestBody.AuxiliaryBuffer = auxIn; queryRowsRequestBody.AuxiliaryBufferSize = (uint)auxIn.Length; QueryRowsResponseBody queryRowsResponseBody = this.Adapter.QueryRows(queryRowsRequestBody); Site.Assert.AreEqual<uint>(0, queryRowsResponseBody.ErrorCode, "QueryRows request should be executed successfully, the returned value {0}.", queryRowsResponseBody.ErrorCode); #endregion #region Capture code AddressBookPropertyRow[] rowData = queryRowsResponseBody.RowData; for (int i = 0; i < rowData.Length; i++) { List<AddressBookPropertyValue> valueArray = new List<AddressBookPropertyValue>(rowData[i].ValueArray); for (int j = 0; j < valueArray.Count; j++) { if (largePropTagArray.PropertyTags[j].PropertyType == 0x001F) { // Add the debug information this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCMAPIHTTP_R2001"); // Verify MS-OXCMAPIHTTP requirement: MS-OXCMAPIHTTP_R2001 this.Site.CaptureRequirementIfIsInstanceOfType( valueArray[j].HasValue, typeof(byte), 2001, @"[In AddressBookPropertyValue Structure] HasValue (optional) (1 byte): An unsigned integer when the PropertyType ([MS-OXCDATA] section 2.11.1) is known to be PtypString."); } if (largePropTagArray.PropertyTags[j].PropertyType == 0x0102) { // Add the debug information this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCMAPIHTTP_R2003"); // Verify MS-OXCMAPIHTTP requirement: MS-OXCMAPIHTTP_R2003 this.Site.CaptureRequirementIfIsInstanceOfType( valueArray[j].HasValue, typeof(byte), 2003, @"[In AddressBookPropertyValue Structure] HasValue (optional) (1 byte): An unsigned integer when the PropertyType ([MS-OXCDATA] section 2.11.1) is known to be PtypBinary."); } } } #endregion #region Call ModLinkAtt with flags 0x00000000 to add the specified PidTagAddressBookMember value. uint flagsOfModLinkAtt = 0; PropertyTag propTagOfModLinkAtt = new PropertyTag { PropertyType = (ushort)PropertyTypeValues.PtypEmbeddedTable, PropertyId = (ushort)PropertyID.PidTagAddressBookMember }; uint midOfModLinkAtt = 0; byte[] entryId = null; GetPropsRequestBody getPropsRequestBodyForAddressBookMember = null; uint lengthOfErrorCodeValue = sizeof(uint); string dlistName = Common.GetConfigurationPropertyValue("DistributionListName", this.Site); string memberName = Common.GetConfigurationPropertyValue("GeneralUserName", this.Site); for (int i = 0; i < queryRowsResponseBody.RowCount; i++) { string name = System.Text.Encoding.Unicode.GetString(queryRowsResponseBody.RowData[i].ValueArray[0].Value); if (name.ToLower().Contains(dlistName.ToLower())) { PermanentEntryID entryID = AdapterHelper.ParsePermanentEntryIDFromBytes(queryRowsResponseBody.RowData[i].ValueArray[1].Value); DNToMinIdRequestBody requestBodyOfDNToMId = new DNToMinIdRequestBody() { Reserved = 0, HasNames = true, Names = new StringArray_r { CValues = 1, LppzA = new string[] { entryID.DistinguishedName } }, AuxiliaryBuffer = auxIn, AuxiliaryBufferSize = (uint)auxIn.Length }; DnToMinIdResponseBody responseBodyOfDNToMinId = this.Adapter.DnToMinId(requestBodyOfDNToMId); midOfModLinkAtt = responseBodyOfDNToMinId.MinimalIds[0]; stat.CurrentRec = midOfModLinkAtt; STAT? statForGetProps = stat; LargePropertyTagArray propertyTagForGetProps = new LargePropertyTagArray() { PropertyTagCount = 2, PropertyTags = new PropertyTag[] { new PropertyTag { PropertyType = (ushort)PropertyTypeValues.PtypInteger32, PropertyId = (ushort)PropertyID.PidTagDisplayType }, new PropertyTag { PropertyType = (ushort)PropertyTypeValues.PtypMultipleString8, PropertyId = (ushort)PropertyID.PidTagAddressBookMember }, } }; getPropsRequestBodyForAddressBookMember = this.BuildGetPropsRequestBody((uint)0, true, statForGetProps, true, propertyTagForGetProps); GetPropsResponseBody getPropsResponseBody = this.Adapter.GetProps(getPropsRequestBodyForAddressBookMember); this.Site.Assert.AreEqual<uint>(0, getPropsResponseBody.StatusCode, "The GetProps request should be executed successfully, the returned status code is {0}", getPropsResponseBody.StatusCode); this.Site.Assert.AreEqual<uint>(lengthOfErrorCodeValue, (uint)getPropsResponseBody.PropertyValues.Value.PropertyValues[1].Value.Length, "The length of the property value should be equal the ErrorCodeValue: Not Found(0x8004010F)"); uint propertyValue = BitConverter.ToUInt32(getPropsResponseBody.PropertyValues.Value.PropertyValues[1].Value, 0); this.Site.Assert.AreEqual<uint>((uint)ErrorCodeValue.NotFound, propertyValue, "The property value of AddressBookMember should be Not Found(0x8004010F), actual value is {0}", propertyValue); } else if (name.ToLower().Contains(memberName.ToLower())) { entryId = queryRowsResponseBody.RowData[i].ValueArray[1].Value; } if (midOfModLinkAtt != 0 && entryId != null) { break; } } ModLinkAttRequestBody modLinkAttRequestBody = new ModLinkAttRequestBody(); modLinkAttRequestBody.Flags = flagsOfModLinkAtt; modLinkAttRequestBody.PropertyTag = propTagOfModLinkAtt; modLinkAttRequestBody.MinimalId = midOfModLinkAtt; modLinkAttRequestBody.HasEntryIds = true; modLinkAttRequestBody.EntryIdCount = 1; modLinkAttRequestBody.EntryIDs = new byte[][] { entryId }; modLinkAttRequestBody.AuxiliaryBuffer = auxIn; modLinkAttRequestBody.AuxiliaryBufferSize = (uint)auxIn.Length; this.minimalIDForDeleteAddressBookMember = midOfModLinkAtt; this.entryIDBufferForDeleteAddressBookMember = entryId; this.isAddressBookMemberDeleted = false; ModLinkAttResponseBody modLinkAttResponseBodyOfAdd = this.Adapter.ModLinkAtt(modLinkAttRequestBody); GetPropsResponseBody getPropsResponseBodyForAddAddressBookMember = this.Adapter.GetProps(getPropsRequestBodyForAddressBookMember); uint modifyDisplayType = BitConverter.ToUInt32(getPropsResponseBodyForAddAddressBookMember.PropertyValues.Value.PropertyValues[0].Value, 0); int propertyValuelength = getPropsResponseBodyForAddAddressBookMember.PropertyValues.Value.PropertyValues[1].Value.Length; if (getPropsResponseBodyForAddAddressBookMember.PropertyValues.Value.PropertyValues[1].PropertyType == 0x101E) { // Add the debug information this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCMAPIHTTP_R2258"); // Verify MS-OXCMAPIHTTP requirement: MS-OXCMAPIHTTP_R2258 this.Site.CaptureRequirementIfIsInstanceOfType( getPropsResponseBodyForAddAddressBookMember.PropertyValues.Value.PropertyValues[1].HasValue, typeof(byte), 2258, @"[In AddressBookPropertyValue Structure] HasValue (optional) (1 byte): An unsigned integer when the PropertyType ([MS-OXCDATA] section 2.11.1) is known to be PtypMultipleString8 ([MS-OXCDATA] section 2.11.1)."); } // Add the debug information this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCMAPIHTTP_R724"); // Verify MS-OXCMAPIHTTP requirement: MS-OXCMAPIHTTP_R724 this.Site.CaptureRequirementIfAreEqual<uint>( 0, modLinkAttResponseBodyOfAdd.ErrorCode, 724, @"[In ModLinkAtt Request Type] The ModLinkAtt request type is used by the client to modify a specific property of a row in the address book."); // Add the debug information this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCMAPIHTTP_R1333, the DisplayTypeValues should be {0}, the length of the property value was changed from {1} to {2}.", DisplayTypeValues.DT_DISTLIST.ToString(), lengthOfErrorCodeValue, propertyValuelength); // Verify MS-OXCMAPIHTTP requirement: MS-OXCMAPIHTTP_R1333 bool isVerifiedR1333 = (modifyDisplayType == (uint)DisplayTypeValues.DT_DISTLIST) && (propertyValuelength != lengthOfErrorCodeValue); this.Site.CaptureRequirementIfIsTrue( isVerifiedR1333, 1333, @"[In ModLinkAtt Request Type Request Body] The PidTagAddressBookMember property ([MS-OXOABK] section 2.2.6.1) can be modified on an Address Book object that has a display type of DT_DISTLIST."); #endregion #region Call ModLinkAtt to delete the specified PidTagAddressBookMember value. modLinkAttRequestBody.Flags = 1; ModLinkAttResponseBody modLinkAttResponseBodyOfDelete = this.Adapter.ModLinkAtt(modLinkAttRequestBody); Site.Assert.AreEqual<uint>(0, modLinkAttResponseBodyOfDelete.ErrorCode, "ModLinkAtt request should be executed successfully, the returned error code is {0}.", modLinkAttResponseBodyOfDelete.ErrorCode); this.isAddressBookMemberDeleted = true; #endregion #region Call ModLinkAtt with flags 0x00000002 to add the specified PidTagAddressBookMember value. this.Site.Assert.IsTrue(this.isAddressBookMemberDeleted, "The previous added address book member should be deleted, actual is {0}", this.isAddressBookMemberDeleted); modLinkAttRequestBody.Flags = 2; ModLinkAttResponseBody modLinkAttResponseBodyFlags2 = this.Adapter.ModLinkAtt(modLinkAttRequestBody); Site.Assert.AreEqual<uint>(0, modLinkAttResponseBodyFlags2.ErrorCode, "ModLinkAtt request should be executed successfully, the returned error code is {0}.", modLinkAttResponseBodyFlags2.ErrorCode); this.isAddressBookMemberDeleted = false; // Add the debug information this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCMAPIHTTP_R1325"); // Verify MS-OXCMAPIHTTP requirement: MS-OXCMAPIHTTP_R1325 this.Site.CaptureRequirementIfAreEqual<uint>( modLinkAttResponseBodyFlags2.ErrorCode, modLinkAttResponseBodyOfAdd.ErrorCode, 1325, @"[In ModLinkAtt Request Type Request Body] If this field [Flags] is set to different values other than the bit flag fDelete (0x00000001), the server will return the same result."); #endregion #region Call ModLinkAtt to delete the specified PidTagAddressBookMember value. modLinkAttRequestBody.Flags = 1; ModLinkAttResponseBody modLinkAttResponseBodyOfDeleteWithFlags2 = this.Adapter.ModLinkAtt(modLinkAttRequestBody); Site.Assert.AreEqual<uint>(0, modLinkAttResponseBodyOfDeleteWithFlags2.ErrorCode, "The ModLinkAtt request to delete the address book member should be executed successfully, the actual returned error code is {0}.", modLinkAttResponseBodyOfDeleteWithFlags2.ErrorCode); this.isAddressBookMemberDeleted = true; #endregion #region Call ModLinkAtt request to add the specified PidTagAddressBookPublicDelegates value midOfModLinkAtt = 0; entryId = null; GetPropsRequestBody getPropsRequestBodyForPublicDelegates = null; memberName = Common.GetConfigurationPropertyValue("GeneralUserName", this.Site); PropertyTag pidTagAddressBookPublicDelegates = new PropertyTag(); pidTagAddressBookPublicDelegates.PropertyType = (ushort)PropertyTypeValues.PtypMultipleString8; pidTagAddressBookPublicDelegates.PropertyId = (ushort)PropertyID.PidTagAddressBookPublicDelegates; for (int i = 0; i < queryRowsResponseBody.RowCount; i++) { string name = System.Text.Encoding.Unicode.GetString(queryRowsResponseBody.RowData[i].ValueArray[0].Value); if (name.ToLower().Contains(memberName.ToLower())) { PermanentEntryID entryID = AdapterHelper.ParsePermanentEntryIDFromBytes(queryRowsResponseBody.RowData[i].ValueArray[1].Value); DNToMinIdRequestBody requestBodyOfDNToMId = new DNToMinIdRequestBody() { Reserved = 0, HasNames = true, Names = new StringArray_r { CValues = 1, LppzA = new string[] { entryID.DistinguishedName } }, AuxiliaryBuffer = auxIn, AuxiliaryBufferSize = (uint)auxIn.Length }; DnToMinIdResponseBody responseBodyOfDNToMinId = this.Adapter.DnToMinId(requestBodyOfDNToMId); midOfModLinkAtt = responseBodyOfDNToMinId.MinimalIds[0]; stat.CurrentRec = midOfModLinkAtt; STAT? statForGetProps = stat; LargePropertyTagArray propertyTagForGetProps = new LargePropertyTagArray() { PropertyTagCount = 2, PropertyTags = new PropertyTag[] { new PropertyTag { PropertyType = (ushort)PropertyTypeValues.PtypInteger32, PropertyId = (ushort)PropertyID.PidTagDisplayType }, new PropertyTag { PropertyType = (ushort)PropertyTypeValues.PtypMultipleString8, PropertyId = (ushort)PropertyID.PidTagAddressBookPublicDelegates }, } }; getPropsRequestBodyForPublicDelegates = this.BuildGetPropsRequestBody((uint)0, true, statForGetProps, true, propertyTagForGetProps); GetPropsResponseBody getPropsResponseBody = this.Adapter.GetProps(getPropsRequestBodyForPublicDelegates); this.Site.Assert.AreEqual<uint>(0, getPropsResponseBody.StatusCode, "The GetProps request should be executed successfully, the returned status code is {0}", getPropsResponseBody.StatusCode); this.Site.Assert.AreEqual<uint>(lengthOfErrorCodeValue, (uint)getPropsResponseBody.PropertyValues.Value.PropertyValues[1].Value.Length, "The length of the property value should be equal the ErrorCodeValue: Not Found(0x8004010F)"); uint propertyValue = BitConverter.ToUInt32(getPropsResponseBody.PropertyValues.Value.PropertyValues[1].Value, 0); this.Site.Assert.AreEqual<uint>((uint)ErrorCodeValue.NotFound, propertyValue, "The property value of AddressBookPublicDelegates should be Not Found(0x8004010F), actual value is {0}", propertyValue); } else if (name.ToLower().Contains(this.AdminUserName.ToLower())) { entryId = queryRowsResponseBody.RowData[i].ValueArray[1].Value; } if (midOfModLinkAtt != 0 && entryId != null) { break; } } ModLinkAttRequestBody modLinkAttRequestBodyForPublicDelegates = new ModLinkAttRequestBody(); modLinkAttRequestBodyForPublicDelegates.Flags = 0; modLinkAttRequestBodyForPublicDelegates.PropertyTag = pidTagAddressBookPublicDelegates; modLinkAttRequestBodyForPublicDelegates.MinimalId = midOfModLinkAtt; modLinkAttRequestBodyForPublicDelegates.HasEntryIds = true; modLinkAttRequestBodyForPublicDelegates.EntryIdCount = 1; modLinkAttRequestBodyForPublicDelegates.EntryIDs = new byte[][] { entryId }; modLinkAttRequestBodyForPublicDelegates.AuxiliaryBuffer = auxIn; modLinkAttRequestBodyForPublicDelegates.AuxiliaryBufferSize = (uint)auxIn.Length; this.minimalIDForDeleteAddressBookPublicDelegate = midOfModLinkAtt; this.entryIDBufferForDeleteAddressBookPublicDelegate = entryId; this.isAddressBookPublicDelegateDeleted = false; ModLinkAttResponseBody modLinkAttResponseBodyForAddPublicDelegates = this.Adapter.ModLinkAtt(modLinkAttRequestBodyForPublicDelegates); GetPropsResponseBody getPropsResponseBodyForAddPublicDelegates = this.Adapter.GetProps(getPropsRequestBodyForPublicDelegates); modifyDisplayType = BitConverter.ToUInt32(getPropsResponseBodyForAddPublicDelegates.PropertyValues.Value.PropertyValues[0].Value, 0); propertyValuelength = getPropsResponseBodyForAddPublicDelegates.PropertyValues.Value.PropertyValues[1].Value.Length; // Add the debug information this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCMAPIHTTP_R1335, the DisplayTypeValues should be {0}, the length of the property value was changed from {1} to {2}.", DisplayTypeValues.DT_MAILUSER.ToString(), lengthOfErrorCodeValue, propertyValuelength); // Verify MS-OXCMAPIHTTP requirement: MS-OXCMAPIHTTP_R1335 bool isVerifiedR1335 = (modifyDisplayType == (uint)DisplayTypeValues.DT_MAILUSER) && (propertyValuelength != lengthOfErrorCodeValue); this.Site.CaptureRequirementIfIsTrue( isVerifiedR1335, 1335, @"[In ModLinkAtt Request Type Request Body] The PidTagAddressBookPublicDelegates property ([MS-OXOABK] section 2.2.5.5) can be modified on an Address Book object that has a display type of DT_MAILUSER."); // Add the debug information this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCMAPIHTTP_R740, the minimal ID should be {0}, the length of the property value was changed from {1} to {2}.", midOfModLinkAtt, lengthOfErrorCodeValue, propertyValuelength); // Verify MS-OXCMAPIHTTP requirement: MS-OXCMAPIHTTP_R740 bool isVerifiedR740 = (midOfModLinkAtt == (uint)getPropsRequestBodyForPublicDelegates.State.CurrentRec) && ((uint)propertyValuelength != lengthOfErrorCodeValue); this.Site.CaptureRequirementIfIsTrue( isVerifiedR740, 740, @"[In ModLinkAtt Request Type Request Body] MinimalId (4 bytes): A MinimalEntryID structure ([MS-OXNSPI] section 2.3.8.1) that specifies the Minimal Entry ID of the address book row to be modified."); // Add the debug information this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCMAPIHTTP_R746."); // Verify MS-OXCMAPIHTTP requirement: MS-OXCMAPIHTTP_R746, the length of the property value is different, means the property was modified. this.Site.CaptureRequirementIfAreNotEqual<uint>( lengthOfErrorCodeValue, (uint)propertyValuelength, 746, @"[In ModLinkAtt Request Type Request Body] EntryIds: Each entry ID in the array specifies an address book row in which the specified property is to be modified."); #endregion #region Call ModLinkAtt request to delete the specified PidTagAddressBookPublicDelegates value modLinkAttRequestBodyForPublicDelegates.Flags = 1; ModLinkAttResponseBody modLinkAttResponseBodyForDeletePublicDelegates = this.Adapter.ModLinkAtt(modLinkAttRequestBodyForPublicDelegates); this.Site.Assert.AreEqual<uint>((uint)0, modLinkAttResponseBodyForDeletePublicDelegates.ErrorCode, "The ModLinkAtt request to delete address book public delegates should be executed successfully, the returned value is {0}", modLinkAttResponseBodyForDeletePublicDelegates.ErrorCode); this.isAddressBookPublicDelegateDeleted = true; #endregion #region Call Unbind request to destroy the session between the client and the server. this.Unbind(); #endregion }
public void MSOXCMAPIHTTP_S02_TC12_ResolveNamesRequestType() { this.CheckMapiHttpIsSupported(); #region Call Bind request type to established a session context with the address book server. this.Bind(); #endregion #region Call ResolveNames request type to perform ANR. STAT stat = new STAT(); stat.InitiateStat(); byte[] auxIn = new byte[] { }; ResolveNamesRequestBody resolveNamesRequestBody = new ResolveNamesRequestBody(); resolveNamesRequestBody.Reserved = 0; resolveNamesRequestBody.HasState = true; resolveNamesRequestBody.State = stat; resolveNamesRequestBody.HasPropertyTags = true; LargePropertyTagArray largePropertyTagArray = new LargePropertyTagArray() { PropertyTagCount = 1, PropertyTags = new PropertyTag[] { new PropertyTag { PropertyType = (ushort)PropertyTypeValues.PtypString, PropertyId = (ushort)PropertyID.PidTagDisplayName } } }; resolveNamesRequestBody.PropertyTags = largePropertyTagArray; resolveNamesRequestBody.HasNames = true; WStringsArray_r stringsArray = new WStringsArray_r(); stringsArray.CValues = 5; stringsArray.LppszW = new string[stringsArray.CValues]; stringsArray.LppszW[0] = this.AdminUserDN; stringsArray.LppszW[1] = string.Empty; stringsArray.LppszW[2] = Common.GetConfigurationPropertyValue("AmbiguousName", this.Site); stringsArray.LppszW[3] = null; stringsArray.LppszW[4] = "XXXXXX"; resolveNamesRequestBody.Names = stringsArray; resolveNamesRequestBody.AuxiliaryBuffer = auxIn; resolveNamesRequestBody.AuxiliaryBufferSize = (uint)auxIn.Length; ResolveNamesResponseBody resolveNamesResponseBody = this.Adapter.ResolveNames(resolveNamesRequestBody); Site.Assert.AreEqual<uint>(0, resolveNamesResponseBody.ErrorCode, "ResolveNames should succeed and 0 is expected to be returned. The returned value is {0}.", resolveNamesResponseBody.ErrorCode); #region Capture code. bool isMinimalIdsCorrect = false; for (int i = 0; i < resolveNamesResponseBody.MinimalIds.Length; i++) { isMinimalIdsCorrect = resolveNamesResponseBody.MinimalIds[i] == (uint)ANRMinEntryIDs.MID_AMBIGUOUS || resolveNamesResponseBody.MinimalIds[i] == (uint)ANRMinEntryIDs.MID_RESOLVED || resolveNamesResponseBody.MinimalIds[i] == (uint)ANRMinEntryIDs.MID_UNRESOLVED; } // Add the debug information this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCMAPIHTTP_R895"); // Verify MS-OXCMAPIHTTP requirement: MS-OXCMAPIHTTP_R895 this.Site.CaptureRequirementIfIsTrue( isMinimalIdsCorrect, 895, @"[In ResolveNames Request Type] The ResolveNames request type is used by the client to perform ambiguous name resolution (ANR), as specified in [MS-OXNSPI] section 3.1.4.7."); // Add the debug information this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCMAPIHTTP_R913"); // Verify MS-OXCMAPIHTTP requirement: MS-OXCMAPIHTTP_R913 this.Site.CaptureRequirementIfIsTrue( AdapterHelper.AreTwoLargePropertyTagArrayEqual(resolveNamesRequestBody.PropertyTags, resolveNamesResponseBody.PropertyTags.Value), 913, @"[In ResolveNames Request Type Request Body] PropertyTags (optional) (variable): A LargePropTagArray structure (section 2.2.1.3) that specifies the properties that client requires for the rows returned."); // Add the debug information this.Site.Log.Add( LogEntryKind.Debug, "Verify MS-OXCMAPIHTTP_R946, the value of PropertyTags is {0}, the value of RowData is {1}.", resolveNamesResponseBody.PropertyTags.Value.PropertyTags, resolveNamesResponseBody.RowData); // Verify MS-OXCMAPIHTTP requirement: MS-OXCMAPIHTTP_R946 bool isVerifiedR946 = resolveNamesResponseBody.PropertyTags.GetType().Equals(typeof(LargePropertyTagArray)) && resolveNamesResponseBody.PropertyTags.Value.PropertyTags != null && resolveNamesResponseBody.RowData != null; this.Site.CaptureRequirementIfIsTrue( isVerifiedR946, 946, @"[In ResolveNames Request Type Success Response Body] PropertyTags (optional) (variable): A LargePropTagArray structure (section 2.2.1.3) that specifies the properties returned for the rows in the RowData field."); // Add the debug information this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCMAPIHTTP_R942"); // Verify MS-OXCMAPIHTTP requirement: MS-OXCMAPIHTTP_R942 bool isVerifiedR942 = resolveNamesResponseBody.MinimalIds.GetType().IsArray && isMinimalIdsCorrect; // Verify MS-OXCMAPIHTTP requirement: MS-OXCMAPIHTTP_R942 this.Site.CaptureRequirementIfIsTrue( isVerifiedR942, 942, @"[In ResolveNames Request Type Success Response Body] MinimalIds (optional) (variable): An array of MinimalEntryID structures ([MS-OXNSPI] section 2.3.8.1), each of which specifies a Minimal Entry ID matching a name requested by the client."); #endregion #endregion #region Call ResolveNames request type with HasState, HasPropertyTags and HasNames set to false to perform ambiguous name resolution (ANR). resolveNamesRequestBody.HasState = false; resolveNamesRequestBody.HasPropertyTags = false; resolveNamesRequestBody.HasNames = false; resolveNamesResponseBody = this.Adapter.ResolveNames(resolveNamesRequestBody); Site.Assert.AreEqual<uint>(0, resolveNamesResponseBody.StatusCode, "ResolveNames should succeed and 0 is expected to be returned. The returned value is {0}.", resolveNamesResponseBody.StatusCode); #endregion #region Call ResolveNames request type with HasState and HasPropertyTags set to true, HasNames set to false to perform ambiguous name resolution (ANR). resolveNamesRequestBody.HasState = true; resolveNamesRequestBody.HasPropertyTags = true; resolveNamesRequestBody.HasNames = false; resolveNamesResponseBody = this.Adapter.ResolveNames(resolveNamesRequestBody); Site.Assert.AreEqual<uint>(0, resolveNamesResponseBody.StatusCode, "ResolveNames should succeed and 0 is expected to be returned. The returned value is {0}.", resolveNamesResponseBody.StatusCode); #endregion #region Call ResolveNames request type with HasState and HasNames set to true, HasPropertyTags set to false to perform ambiguous name resolution (ANR). resolveNamesRequestBody.HasState = true; resolveNamesRequestBody.HasPropertyTags = false; resolveNamesRequestBody.HasNames = true; resolveNamesResponseBody = this.Adapter.ResolveNames(resolveNamesRequestBody); Site.Assert.AreEqual<uint>(0, resolveNamesResponseBody.ErrorCode, "ResolveNames should succeed and 0 is expected to be returned. The returned value is {0}.", resolveNamesResponseBody.ErrorCode); #endregion #region Call ResolveNames request type with HasState set to false, HasPropertyTags and HasNames set to true to perform ambiguous name resolution (ANR). resolveNamesRequestBody.HasState = false; resolveNamesRequestBody.HasPropertyTags = true; resolveNamesRequestBody.HasNames = true; resolveNamesResponseBody = this.Adapter.ResolveNames(resolveNamesRequestBody); Site.Assert.AreEqual<uint>(0, resolveNamesResponseBody.StatusCode, "ResolveNames should succeed and 0 is expected to be returned. The returned value is {0}.", resolveNamesResponseBody.StatusCode); #endregion #region Call the Unbind request type to destroy the session context. this.Unbind(); #endregion }
/// <summary> /// Build the QueryRows request body. /// </summary> /// <param name="hasState">A Boolean value that specifies whether the State field is present.</param> /// <param name="state">A STAT structure that specifies the state of a specific address book container.</param> /// <param name="explicitTableCount">An unsigned integer that specifies the number of structures present in the ExplicitTable field.</param> /// <param name="explicitTable">An array of MinimalEntryID structures that constitute the Explicit Table.</param> /// <param name="rowCount">An unsigned integer that specifies the number of rows the client is requesting.</param> /// <param name="hasColumns">A Boolean value that specifies whether the Columns field is present.</param> /// <param name="columns">A LargePropTagArray structure that specifies the properties that the client requires for each row returned.</param> /// <returns>Returns the QueryRows request body.</returns> private QueryRowsRequestBody BuildQueryRowsRequestBody(bool hasState, STAT state, uint explicitTableCount, uint[] explicitTable, uint rowCount, bool hasColumns, LargePropertyTagArray columns) { QueryRowsRequestBody queryRowsRequestBody = new QueryRowsRequestBody(); queryRowsRequestBody.Flags = (uint)RetrievePropertyFlags.fSkipObjects; queryRowsRequestBody.HasState = hasState; if (hasState) { queryRowsRequestBody.State = state; } queryRowsRequestBody.ExplicitTableCount = explicitTableCount; queryRowsRequestBody.ExplicitTable = explicitTable; queryRowsRequestBody.RowCount = rowCount; queryRowsRequestBody.HasColumns = hasColumns; if (hasColumns) { queryRowsRequestBody.Columns = columns; } byte[] auxIn = new byte[] { }; queryRowsRequestBody.AuxiliaryBuffer = auxIn; queryRowsRequestBody.AuxiliaryBufferSize = (uint)auxIn.Length; return queryRowsRequestBody; }
public void MSOXCMAPIHTTP_S02_TC16_GetProps() { this.CheckMapiHttpIsSupported(); #region Call Bind request type to established a session context with the address book server. this.Bind(); #endregion #region Call UpdateStat to update the STAT block to make CurrentRec point to the first row of the table. STAT stat = new STAT(); stat.InitiateStat(); UpdateStatRequestBody updateStatRequestBody = this.BuildUpdateStatRequestBody(true, stat, true); UpdateStatResponseBody updateStatResponseBody = this.Adapter.UpdateStat(updateStatRequestBody); Site.Assert.AreEqual<uint>((uint)0, updateStatResponseBody.ErrorCode, "UpdateStat operation should succeed and 0 is expected to be returned. The return value is {0}.", updateStatResponseBody.ErrorCode); #endregion #region Call GetProps request type with Flags set to fEphID. LargePropertyTagArray largePropTagArray = new LargePropertyTagArray(); largePropTagArray.PropertyTagCount = 1; // PidTagDisplayName property. PropertyTag[] propertyTags = new PropertyTag[1]; propertyTags[0].PropertyId = (ushort)PropertyID.PidTagDisplayName; propertyTags[0].PropertyType = (ushort)PropertyTypeValues.PtypString; largePropTagArray.PropertyTags = propertyTags; GetPropsRequestBody getPropertyRequestBody = this.BuildGetPropsRequestBody((uint)RetrievePropertyFlags.fEphID, true, updateStatResponseBody.State, true, largePropTagArray); GetPropsResponseBody getPropertyResponseBody = this.Adapter.GetProps(getPropertyRequestBody); Site.Assert.AreEqual<uint>((uint)0, getPropertyResponseBody.ErrorCode, "GetProps operation should succeed and 0 is expected to be returned. The return value is {0}.", getPropertyResponseBody.ErrorCode); AddressBookTaggedPropertyValue[] propertyValues = getPropertyResponseBody.PropertyValues.Value.PropertyValues; bool isVerifiedR624 = false; if (getPropertyResponseBody.PropertyValues.Value.PropertyValueCount != largePropTagArray.PropertyTagCount) { isVerifiedR624 = false; } else { for (int i = 0; i < getPropertyResponseBody.PropertyValues.Value.PropertyValueCount; i++) { if (propertyValues[i].PropertyId == propertyTags[i].PropertyId && propertyValues[i].PropertyType == propertyTags[i].PropertyType) { isVerifiedR624 = true; } else { isVerifiedR624 = false; break; } } } // Add the debug information this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCMAPIHTTP_R624. The returned property numbers is {0}.", getPropertyResponseBody.PropertyValues.Value.PropertyValueCount); // Verify MS-OXCMAPIHTTP requirement: MS-OXCMAPIHTTP_R624 this.Site.CaptureRequirementIfIsTrue( isVerifiedR624, 624, @"[In GetProps Request Type Success Response Body] PropertyValues (optional) (variable): An AddressBookPropertyValueList structure (section 2.2.1.1) that contains the values of the properties requested."); // Add the debug information this.Site.Log.Add( LogEntryKind.Debug, "Verify MS-OXCMAPIHTTP_R590. The returned property number is {0}, the returned property ID is {1}, the returned property type is {2}.", getPropertyResponseBody.PropertyValues.Value.PropertyValueCount, propertyValues[0].PropertyId, propertyValues[0].PropertyType); #endregion #region Call GetProps request type with Flags set to fSkipObjects. getPropertyRequestBody = this.BuildGetPropsRequestBody((uint)RetrievePropertyFlags.fSkipObjects, true, updateStatResponseBody.State, true, largePropTagArray); getPropertyResponseBody = this.Adapter.GetProps(getPropertyRequestBody); Site.Assert.AreEqual<uint>((uint)0, getPropertyResponseBody.ErrorCode, "GetProps operation should succeed and 0 is expected to be returned. The return value is {0}.", getPropertyResponseBody.ErrorCode); #endregion #region Call GetProps request type with Flags set to one value other than fEphID (0x2) and fSkipObjects (0x1). uint flags1 = 0x0; getPropertyRequestBody = this.BuildGetPropsRequestBody(flags1, true, updateStatResponseBody.State, true, largePropTagArray); GetPropsResponseBody getPropertyResponseBody1 = this.Adapter.GetProps(getPropertyRequestBody); Site.Assert.AreEqual<uint>((uint)0, getPropertyResponseBody1.ErrorCode, "GetProps operation should succeed and 0 is expected to be returned. The return value is {0}.", getPropertyResponseBody1.ErrorCode); #endregion #region Call GetProps request type with Flags set to one value other than fEphID (0x2) and fSkipObjects (0x1). uint flags2 = 0x8; getPropertyRequestBody = this.BuildGetPropsRequestBody(flags2, true, updateStatResponseBody.State, true, largePropTagArray); GetPropsResponseBody getPropertyResponseBody2 = this.Adapter.GetProps(getPropertyRequestBody); Site.Assert.AreEqual<uint>((uint)0, getPropertyResponseBody2.ErrorCode, "GetProps operation should succeed and 0 is expected to be returned. The return value is {0}.", getPropertyResponseBody2.ErrorCode); // Add the debug information this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCMAPIHTTP_R1323"); // Verify MS-OXCMAPIHTTP requirement: MS-OXCMAPIHTTP_R1323 this.Site.CaptureRequirementIfIsTrue( AdapterHelper.AreTwoAddressBookPropValueListEqual(getPropertyResponseBody1.PropertyValues.Value, getPropertyResponseBody2.PropertyValues.Value), 1323, @"[In GetProps Request Type Request Body] If this field [Flags] is set to different values other than the bit flags fEphID (0x00000002) and fSkipObjects (0x00000001), the server will return the same result."); #endregion #region Call GetProps request type with setting fields HasState and HasPropertyTags to false. getPropertyRequestBody = this.BuildGetPropsRequestBody((uint)RetrievePropertyFlags.fEphID, false, updateStatResponseBody.State, false, largePropTagArray); getPropertyResponseBody = this.Adapter.GetProps(getPropertyRequestBody); Site.Assert.AreEqual<uint>((uint)0, getPropertyResponseBody.StatusCode, "GetProps request should be executed successfully and 0 is expected to be returned. The return value is {0}.", getPropertyResponseBody.StatusCode); #endregion #region Call GetProps request type with HasState field set to false and HasPropertyTags set to true. getPropertyRequestBody = this.BuildGetPropsRequestBody((uint)RetrievePropertyFlags.fEphID, false, updateStatResponseBody.State, true, largePropTagArray); getPropertyResponseBody = this.Adapter.GetProps(getPropertyRequestBody); Site.Assert.AreEqual<uint>((uint)0, getPropertyResponseBody.StatusCode, "GetProps request should be executed successfully and 0 is expected to be returned. The return value is {0}.", getPropertyResponseBody.StatusCode); #endregion #region Call GetProps request type with Flags set to fEphID. largePropTagArray = new LargePropertyTagArray(); largePropTagArray.PropertyTagCount = 2; // PidTagDisplayName property. propertyTags = new PropertyTag[2]; propertyTags[0].PropertyId = (ushort)PropertyID.PidTagDisplayName; propertyTags[0].PropertyType = (ushort)PropertyTypeValues.PtypString; propertyTags[1].PropertyId = (ushort)PropertyID.PidTagAddressBookMember; propertyTags[1].PropertyType = (ushort)PropertyTypeValues.PtypEmbeddedTable; largePropTagArray.PropertyTags = propertyTags; getPropertyRequestBody = this.BuildGetPropsRequestBody((uint)RetrievePropertyFlags.fEphID, true, updateStatResponseBody.State, true, largePropTagArray); uint responseCodeHeader = 0; getPropertyResponseBody = this.Adapter.GetProps(getPropertyRequestBody, out responseCodeHeader); if (Common.IsRequirementEnabled(2237, this.Site)) { // Add the debug information this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCMAPIHTTP_R2237."); // Verify MS-OXCDATA requirement: MS-OXCMAPIHTTP_R2237 this.Site.CaptureRequirementIfAreEqual<uint>( 1, responseCodeHeader, 2237, @"[In Appendix A: Product Behavior] If the type of the returned property is PtypObject or PtypEmbeddedTable ([MS-OXCDATA] section 2.11.1), implementation will return value 1 for the X-ResponseCode header. (Exchange 2013 SP1 follows this behavior.)"); } #endregion #region Call the Unbind request type to destroy the session context. this.Unbind(); #endregion }
/// <summary> /// Verify the LargePropTagArray structure related requirements. /// </summary> /// <param name="largePropTagArray">The LargePropTagArray value to be verified.</param> private void VerifyLargePropertyTagArrayStructure(LargePropertyTagArray largePropTagArray) { // Add the debug information this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCMAPIHTTP_R24"); // Verify MS-OXCMAPIHTTP requirement: MS-OXCMAPIHTTP_R24 this.Site.CaptureRequirementIfIsInstanceOfType( largePropTagArray.PropertyTagCount, typeof(uint), 24, @"[In LargePropertyTagArray Structure] PropertyTagCount (4 bytes): An unsigned integer that specifies the number of structures contained in the PropertyTags field."); // Add the debug information this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCMAPIHTTP_R25, the value of PropertyTagCount is {0}.", largePropTagArray.PropertyTagCount); // Verify MS-OXCMAPIHTTP requirement: MS-OXCMAPIHTTP_R25 this.Site.CaptureRequirementIfIsTrue( largePropTagArray.PropertyTagCount <= 100000, 25, @"[In LargePropertyTagArray Structure] [PropertyTagCount (4 bytes)] The number is limited to 100,000."); // Add the debug information this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCMAPIHTTP_R26"); // Verify MS-OXCMAPIHTTP requirement: MS-OXCMAPIHTTP_R26 this.Site.CaptureRequirementIfIsInstanceOfType( largePropTagArray.PropertyTags, typeof(PropertyTag[]), 26, @"[In LargePropertyTagArray Structure] PropertyTags (variable): An array of PropertyTag structures ([MS-OXCDATA] section 2.9), each of which contains a property tag that specifies a property."); PropertyTag[] propertytags = largePropTagArray.PropertyTags; foreach (PropertyTag propertyTag in propertytags) { // Add the debug information this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCDATA_R181"); // Verify MS-OXCMAPIHTTP requirement: MS-OXCDATA_R181 this.Site.CaptureRequirementIfIsInstanceOfType( propertyTag.PropertyType, typeof(ushort), "MS-OXCDATA", 181, @"[In PropertyTag Structure] PropertyType (2 bytes): An unsigned integer that identifies the data type of the property value, as specified by the table in section 2.11.1."); // Add the debug information this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCDATA_R182"); // Verify MS-OXCMAPIHTTP requirement: MS-OXCDATA_R182 this.Site.CaptureRequirementIfIsInstanceOfType( propertyTag.PropertyId, typeof(ushort), "MS-OXCDATA", 182, @"[In PropertyTag Structure] PropertyId (2 bytes): An unsigned integer that identifies the property."); } // Since Test Suite parsed largePropTagArray structure according to Specification, and the PropertyTag has been walked in the upper step, // so if the program run to here, R23 can be verified directly. this.Site.CaptureRequirement( 23, @"[In LargePropertyTagArray Structure] The LargePropertyTagArray structure contains a list of property tags."); }
/// <summary> /// Initialize ModProps request body. /// </summary> /// <param name="hasState">A Boolean value that specifies whether the State field is present.</param> /// <param name="stat">A STAT structure that specifies the state of a specific address book container.</param> /// <param name="hasPropertyValues">A Boolean value that specifies whether the PropertyValues field is present.</param> /// <param name="propertyTag">A property tag both identifies a property and gives the data type its value.</param> /// <param name="hasPropertyTagsToRemove">A Boolean value that specifies whether the PropertyTagsToRemove field is present.</param> /// <param name="propertyTagsToRemove">A LargePropTagArray structure that specifies the properties that the client is requesting to be removed. </param> /// <returns>Returns the ModProps request body.</returns> private ModPropsRequestBody BuildModPropsRequestBody(bool hasState, STAT stat, bool hasPropertyValues, PropertyTag propertyTag, bool hasPropertyTagsToRemove, LargePropertyTagArray propertyTagsToRemove) { ModPropsRequestBody modPropsRequestBody = new ModPropsRequestBody(); modPropsRequestBody.Reserved = 0x0; byte[] auxIn = new byte[] { }; modPropsRequestBody.AuxiliaryBuffer = auxIn; modPropsRequestBody.AuxiliaryBufferSize = (uint)auxIn.Length; modPropsRequestBody.HasState = hasState; if (hasState) { modPropsRequestBody.State = stat; } modPropsRequestBody.HasPropertyValues = hasPropertyValues; if (hasPropertyValues) { AddressBookPropertyValueList addressBookProperties = new AddressBookPropertyValueList(); addressBookProperties.PropertyValueCount = 1; AddressBookTaggedPropertyValue[] taggedPropertyValues = new AddressBookTaggedPropertyValue[1]; AddressBookTaggedPropertyValue taggedPropertyValue = new AddressBookTaggedPropertyValue(); taggedPropertyValue.PropertyType = propertyTag.PropertyType; taggedPropertyValue.PropertyId = propertyTag.PropertyId; taggedPropertyValue.Value = new byte[] { 0x00, 0x00 }; taggedPropertyValues[0] = taggedPropertyValue; addressBookProperties.PropertyValues = taggedPropertyValues; modPropsRequestBody.PropertyVaules = addressBookProperties; } modPropsRequestBody.HasPropertyTagsToRemove = hasPropertyTagsToRemove; if (hasPropertyTagsToRemove) { modPropsRequestBody.PropertyTagsToRemove = propertyTagsToRemove; } return modPropsRequestBody; }
/// <summary> /// Compare whether two LargePropertyTagArrays are equal. /// </summary> /// <param name="propertyTagArray1">The first LargePropertyTagArray used to compare.</param> /// <param name="propertyTagArray2">The second LargePropertyTagArray used to compare.</param> /// <returns>Returns true if they are equal; otherwise false.</returns> public static bool AreTwoLargePropertyTagArrayEqual(LargePropertyTagArray propertyTagArray1, LargePropertyTagArray propertyTagArray2) { if (propertyTagArray1.PropertyTagCount != propertyTagArray2.PropertyTagCount) { site.Log.Add( LogEntryKind.Debug, "The length the two property tag array are not equal. The length of propertyTagArray1 is {0}, the length of propertyTagArray2 is {1}.", propertyTagArray1.PropertyTagCount, propertyTagArray2.PropertyTagCount); return false; } else { PropertyTag[] propertyTags1 = propertyTagArray1.PropertyTags; PropertyTag[] propertyTags2 = propertyTagArray2.PropertyTags; for (int i = 0; i < propertyTags1.Length; i++) { if (propertyTags1[i].PropertyId != propertyTags2[i].PropertyId) { site.Log.Add( LogEntryKind.Debug, "The property ID of property {0} in the two property tag array are not equal. The property ID of propertyTags1 is {1}, the property ID of propertyTags2 is {2}", i, propertyTags1[i].PropertyId, propertyTags2[i].PropertyId); return false; } else if (propertyTags1[i].PropertyType != propertyTags2[i].PropertyType) { site.Log.Add( LogEntryKind.Debug, "The property type of property {0} in the two property tag array are not equal. The property type of propertyTags1 is {1}, the property type of propertyTags2 is {2}", i, propertyTags1[i].PropertyType, propertyTags2[i].PropertyType); return false; } } } return true; }
/// <summary> /// Build the GetProps request body. /// </summary> /// <param name="flags">A set of bit flags that specify options to the server.</param> /// <param name="hasState">A Boolean value that specifies whether the State field is present.</param> /// <param name="stat">A STAT structure that specifies the state of a specific address book container.</param> /// <param name="hasPropertyTags">A Boolean value that specifies whether the PropertyTags field is present.</param> /// <param name="propetyTags">A LargePropertyTagArray structure that contains the property tags of the properties that the client is requesting.</param> /// <returns>The GetProps request body.</returns> private GetPropsRequestBody BuildGetPropsRequestBody(uint flags, bool hasState, STAT? stat, bool hasPropertyTags, LargePropertyTagArray propetyTags) { GetPropsRequestBody getPropertyRequestBody = new GetPropsRequestBody(); getPropertyRequestBody.Flags = flags; byte[] auxIn = new byte[] { }; getPropertyRequestBody.AuxiliaryBuffer = auxIn; getPropertyRequestBody.AuxiliaryBufferSize = (uint)auxIn.Length; getPropertyRequestBody.HasState = hasState; if (hasState) { getPropertyRequestBody.State = (STAT)stat; } getPropertyRequestBody.HasPropertyTags = hasPropertyTags; if (hasPropertyTags) { getPropertyRequestBody.PropertyTags = propetyTags; } return getPropertyRequestBody; }