public void MSOXCFOLD_S03_TC01_StaticSearchVerification()
{
this.CheckWhetherSupportTransport();
this.Adapter.DoConnect(ConnectionType.PrivateMailboxServer);
this.GenericFolderInitialization();
#region Step 1. The client calls RopCreateFolder to create the general folder [MSOXCFOLDSubfolder1] under the root folder.
RopCreateFolderRequest createFolderRequest = new RopCreateFolderRequest
{
RopId = (byte)RopId.RopCreateFolder,
LogonId = Constants.CommonLogonId,
InputHandleIndex = Constants.CommonInputHandleIndex,
OutputHandleIndex = Constants.CommonOutputHandleIndex,
FolderType = (byte)FolderType.Genericfolder,
UseUnicodeStrings = 0x0,
OpenExisting = 0x00,
Reserved = 0x0,
DisplayName = Encoding.ASCII.GetBytes(Constants.Subfolder1),
Comment = Encoding.ASCII.GetBytes(Constants.Subfolder1)
};
RopCreateFolderResponse createFolderResponse = this.Adapter.CreateFolder(createFolderRequest, this.RootFolderHandle, ref this.responseHandles);
Site.Assert.AreEqual<uint>(Constants.SuccessCode, createFolderResponse.ReturnValue, "RopCreateFolder ROP operation performs successfully!");
uint subfolderHandle1 = this.responseHandles[0][createFolderResponse.OutputHandleIndex];
ulong subfolderId1 = createFolderResponse.FolderId;
#endregion
#region Step 2. The client creates two general messages under the folder [MSOXCFOLDSubfolder1].
uint messageHandle1 = 0;
ulong messageId1 = 0;
this.CreateSaveMessage(subfolderHandle1, subfolderId1, ref messageId1, ref messageHandle1);
uint messageHandle2 = 0;
ulong messageId2 = 0;
this.CreateSaveMessage(subfolderHandle1, subfolderId1, ref messageId2, ref messageHandle2);
#endregion
#region Step 3. The client calls RopCreateFolder to create the search folder [MSOXCFOLDSearchFolder2] under the root folder.
createFolderRequest.FolderType = (byte)FolderType.Searchfolder;
createFolderRequest.DisplayName = Encoding.ASCII.GetBytes(Constants.SearchFolder2);
createFolderRequest.Comment = Encoding.ASCII.GetBytes(Constants.SearchFolder2);
createFolderResponse = this.Adapter.CreateFolder(createFolderRequest, this.RootFolderHandle, ref this.responseHandles);
Site.Assert.AreEqual<uint>(Constants.SuccessCode, createFolderResponse.ReturnValue, "RopCreateFolder ROP operation performs successfully!");
uint searchFolderHandle2 = this.responseHandles[0][createFolderResponse.OutputHandleIndex];
#endregion
#region Step 4. The client calls RopSetSearchCriteria to establish search criteria for [MSOXCFOLDSearchFolder2].
RopSetSearchCriteriaRequest setSearchCriteriaRequest = new RopSetSearchCriteriaRequest
{
RopId = (byte)RopId.RopSetSearchCriteria,
LogonId = Constants.CommonLogonId,
InputHandleIndex = Constants.CommonInputHandleIndex
};
PropertyTag propertyTag = new PropertyTag
{
PropertyId = (ushort)MessagePropertyId.PidTagMessageClass,
PropertyType = (ushort)PropertyType.PtypString
};
ExistRestriction existRestriction = new ExistRestriction
{
PropTag = propertyTag
};
setSearchCriteriaRequest.RestrictionDataSize = (ushort)existRestriction.Size();
setSearchCriteriaRequest.RestrictionData = existRestriction.Serialize();
setSearchCriteriaRequest.FolderIds = new ulong[] { subfolderId1 };
setSearchCriteriaRequest.FolderIdCount = (ushort)setSearchCriteriaRequest.FolderIds.Length;
setSearchCriteriaRequest.SearchFlags = (uint)SetSearchFlags.ContentIndexedSearch | (uint)SetSearchFlags.StaticSearch | (uint)SetSearchFlags.RestartSearch;
RopSetSearchCriteriaResponse setSearchCriteriaResponse = this.Adapter.SetSearchCriteria(setSearchCriteriaRequest, searchFolderHandle2, ref this.responseHandles);
Site.Assert.AreEqual<uint>(Constants.SuccessCode, setSearchCriteriaResponse.ReturnValue, "RopSearchCriteria ROP operation performs successfully!");
#endregion
#region Step 5. The client calls RopGetSearchCriteria to obtain the search criteria and the status of the search folder [MSOXCFOLDSearchFolder2].
RopGetSearchCriteriaRequest getSearchCriteriaRequest = new RopGetSearchCriteriaRequest
{
RopId = (byte)RopId.RopGetSearchCriteria,
LogonId = Constants.CommonLogonId,
InputHandleIndex = Constants.CommonInputHandleIndex,
UseUnicode = 0x00,
IncludeRestriction = 0x01,
IncludeFolders = 0x01
};
RopGetSearchCriteriaResponse getSearchCriteriaResponse = this.Adapter.GetSearchCriteria(getSearchCriteriaRequest, searchFolderHandle2, ref this.responseHandles);
Site.Assert.AreEqual<uint>(Constants.SuccessCode, getSearchCriteriaResponse.ReturnValue, "RopGetSearchCriteria ROP operation performs successfully!");
#region Verify the requirements: MS-OXCFOLD_R1200 and MS-OXCFOLD_R1233.
// Add the debug information
Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R1200");
// Verify MS-OXCFOLD requirement: MS-OXCFOLD_R1200
// SHALLOW_SEARCH bit in the RopSetSearchCriteria ROP request means the search includes only the search folder containers that are specified in the FolderIds field.
// If the bit SEARCH_RECURSIVE in the RopGetSearchCriteria ROP response is not set means only the search folder containers that are specified in the last RopSetSearchCriteria ROP request are being searched.
// So, if the bit SEARCH_RECURSIVE in getSearchCriteriaResponse is not set, R1200 can be verified.
Site.CaptureRequirementIfAreNotEqual<uint>(
(uint)GetSearchFlags.Recursive,
getSearchCriteriaResponse.SearchFlags & (uint)GetSearchFlags.Recursive,
1200,
@"[In RopSetSearchCriteria ROP Request Buffer] SearchFlags (4 bytes): If neither bit [RECURSIVE_SEARCH or SHALLOW_SEARCH] is set, the default is SHALLOW_SEARCH.");
// Add the debug information
this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R1233");
List<ulong> folderIdsInGetSearchCriteriaResponse = new List<ulong>();
folderIdsInGetSearchCriteriaResponse.AddRange(getSearchCriteriaResponse.FolderIds);
// Verify MS-OXCFOLD requirement: MS-OXCFOLD_R1233
this.Site.CaptureRequirementIfIsFalse(
folderIdsInGetSearchCriteriaResponse.Contains(createFolderResponse.FolderId),
1233,
@"[In Setting Up a Search Folder] [A search folder cannot be included in its own search scope] Therefore, the FolderIds field MUST NOT include the FID of the search folder.");
#endregion
#endregion
#region Step 6. The client calls RopGetContentsTable to retrieve the contents table for the search folder [MSOXCFOLDSearchFolder2].
RopGetContentsTableRequest getContentsTableRequest = new RopGetContentsTableRequest();
RopGetContentsTableResponse getContentsTableResponse;
getContentsTableRequest.RopId = (byte)RopId.RopGetContentsTable;
getContentsTableRequest.LogonId = Constants.CommonLogonId;
getContentsTableRequest.InputHandleIndex = Constants.CommonInputHandleIndex;
getContentsTableRequest.OutputHandleIndex = Constants.CommonOutputHandleIndex;
getContentsTableRequest.TableFlags = (byte)FolderTableFlags.None;
int count = 0;
do
{
getContentsTableResponse = this.Adapter.GetContentsTable(getContentsTableRequest, searchFolderHandle2, ref this.responseHandles);
Site.Assert.AreEqual<uint>(Constants.SuccessCode, getContentsTableResponse.ReturnValue, "RopGetContentsTable ROP operation performs successfully!");
if (getContentsTableResponse.RowCount != 2)
{
Thread.Sleep(this.WaitTime);
}
else
{
break;
}
count++;
}
while (count < this.RetryCount);
uint rowCountBeforeHardDel = getContentsTableResponse.RowCount;
Site.Assert.AreEqual<uint>(2, rowCountBeforeHardDel, "The two general messages created in step 2 were fetched in search folder.");
#endregion
#region Step 7. The client calls RopHardDeleteMessage ROP operation to hard delete a message in the general folder [MSOXCFOLDSubfolder1] under the root folder.
ulong[] messageIds = new ulong[] { messageId1 };
RopHardDeleteMessagesRequest hardDeleteMessagesRequest = new RopHardDeleteMessagesRequest
{
RopId = (byte)RopId.RopHardDeleteMessages,
LogonId = Constants.CommonLogonId,
InputHandleIndex = Constants.CommonInputHandleIndex,
WantAsynchronous = 0x00,
NotifyNonRead = 0x00,
MessageIdCount = (ushort)messageIds.Length,
MessageIds = messageIds
};
RopHardDeleteMessagesResponse hardDeleteMessagesResponse = this.Adapter.HardDeleteMessages(hardDeleteMessagesRequest, subfolderHandle1, ref this.responseHandles);
Site.Assert.AreEqual<uint>(Constants.SuccessCode, hardDeleteMessagesResponse.ReturnValue, "RopHardDeleteMessages ROP operation performs successfully!");
Site.Assert.AreEqual<uint>(0x00, hardDeleteMessagesResponse.PartialCompletion, "RopHardDeleteMessages ROP operation is complete!");
#endregion
#region Step 8. The client calls RopGetContentsTable to retrieve the contents table for the search folder [MSOXCFOLDSearchFolder2].
count = 0;
bool searchFolderNotChange = false;
do
{
getContentsTableResponse = this.Adapter.GetContentsTable(getContentsTableRequest, searchFolderHandle2, ref this.responseHandles);
Site.Assert.AreEqual<uint>(Constants.SuccessCode, getContentsTableResponse.ReturnValue, "RopGetContentsTable ROP operation performs successfully!");
if (getContentsTableResponse.RowCount != rowCountBeforeHardDel)
{
Thread.Sleep(this.WaitTime);
}
else
{
searchFolderNotChange = true;
break;
}
count++;
}
while (count < this.RetryCount);
#region Verify the requirements: MS-OXCFOLD_R795, MS-OXCFOLD_R784, MS-OXCFOLD_R1084, MS-OXCFOLD_R549, MS-OXCFOLD_R1093, MS-OXCFOLD_R1094.
// Add the debug information
Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R795");
// Verify MS-OXCFOLD requirement: MS-OXCFOLD_R795
// The search folder contents didn't change after the message has been hard deleted, it indicates the current search is static search.
Site.CaptureRequirementIfIsTrue(
searchFolderNotChange,
795,
@"[In RopGetSearchCriteria ROP Response Buffer] SearchFlags (4 bytes): SEARCH_STATIC (0x00010000) means that the search is static.");
// Add the debug information
Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R784");
// Verify MS-OXCFOLD requirement: MS-OXCFOLD_R784
Site.CaptureRequirementIfIsTrue(
searchFolderNotChange,
784,
@"[In RopSetSearchCriteria ROP Request Buffer] SearchFlags (4 bytes): STATIC_SEARCH (0x00040000) means that the search is static, if set.");
// Add the debug information
Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R1084");
// Verify MS-OXCFOLD requirement: MS-OXCFOLD_R1084
Site.CaptureRequirementIfIsTrue(
searchFolderNotChange,
1084,
@"[In Processing a RopSetSearchCriteria ROP Request] For static search folders, the contents of the search folder are not updated after the initial population is complete.");
// Add the debug information
Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R549");
// Verify MS-OXCFOLD requirement: MS-OXCFOLD_R549
Site.CaptureRequirementIfIsTrue(
searchFolderNotChange,
549,
@"[In Processing a RopSetSearchCriteria ROP Request] A static search causes the search folder to be populated once with all messages that match the search criteria at the point in time when the search is started or restarted.");
// Add the debug information
Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R1093");
// Verify MS-OXCFOLD requirement: MS-OXCFOLD_R1093
Site.CaptureRequirementIfIsTrue(
searchFolderNotChange,
1093,
@"[In Processing a RopSetSearchCriteria ROP Request] The server MUST NOT update the search folder after the initial population when new messages that match the search criteria arrive in the search scope.");
// Add the debug information
Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R1094");
// Verify MS-OXCFOLD requirement: MS-OXCFOLD_R1094
Site.CaptureRequirementIfIsTrue(
searchFolderNotChange,
1094,
@"[In Processing a RopSetSearchCriteria ROP Request] Or the server MUST NOT update the search folder after the initial population when existing messages that fit the search criteria are deleted.");
#endregion
#endregion
#region Step 9. The client calls RopSetSearchCriteria to restart the search for [MSOXCFOLDSearchFolder2].
setSearchCriteriaRequest.SearchFlags = (uint)SetSearchFlags.ContentIndexedSearch | (uint)SetSearchFlags.RestartSearch;
setSearchCriteriaResponse = this.Adapter.SetSearchCriteria(setSearchCriteriaRequest, searchFolderHandle2, ref this.responseHandles);
Site.Assert.AreEqual<uint>(Constants.SuccessCode, setSearchCriteriaResponse.ReturnValue, "RopSearchCriteria ROP operation performs successfully!");
#endregion
#region Step 10. The client calls RopGetContentsTable to retrieve the contents table for the search folder [MSOXCFOLDSearchFolder2].
count = 0;
do
{
getContentsTableResponse = this.Adapter.GetContentsTable(getContentsTableRequest, searchFolderHandle2, ref this.responseHandles);
Site.Assert.AreEqual<uint>(Constants.SuccessCode, getContentsTableResponse.ReturnValue, "RopGetContentsTable ROP operation performs successfully!");
if (getContentsTableResponse.RowCount != 1)
{
Thread.Sleep(this.WaitTime);
}
else
{
break;
}
count++;
}
while (count < this.RetryCount);
// Add the debug information
Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R551");
// Verify MS-OXCFOLD requirement: MS-OXCFOLD_R551
// There should be 1 message found and copy to the search folder, so the RowCount should be 1.
Site.CaptureRequirementIfAreEqual<uint>(
1,
getContentsTableResponse.RowCount,
551,
@"[In Processing a RopSetSearchCriteria ROP Request] To trigger an update, another RopSetSearchCriteria ROP request with the RESTART_SEARCH bit set in the SearchFlags field, as specified in section 2.2.1.4.1, is required.");
#endregion
#region Step 11. The client calls RopSetSearchCriteria to establish search criteria for [MSOXCFOLDSearchFolder2] by a new RestrictionData.
setSearchCriteriaRequest = new RopSetSearchCriteriaRequest();
setSearchCriteriaRequest.RopId = (byte)RopId.RopSetSearchCriteria;
setSearchCriteriaRequest.LogonId = Constants.CommonLogonId;
setSearchCriteriaRequest.InputHandleIndex = Constants.CommonInputHandleIndex;
ContentRestriction contentRestriction = new ContentRestriction
{
FuzzyLevelLow = FuzzyLevelLowValues.FL_PREFIX,
FuzzyLevelHigh = FuzzyLevelHighValues.FL_IGNORECASE
};
propertyTag = new PropertyTag
{
PropertyId = (ushort)MessagePropertyId.PidTagMessageClass,
PropertyType = (ushort)PropertyType.PtypString
};
contentRestriction.PropertyTag = propertyTag;
TaggedPropertyValue taggedProperty = new TaggedPropertyValue
{
PropertyTag = propertyTag,
Value = Encoding.Unicode.GetBytes("IPM.Task" + Constants.StringNullTerminated)
};
contentRestriction.TaggedValue = taggedProperty;
setSearchCriteriaRequest.RestrictionDataSize = (ushort)contentRestriction.Size();
setSearchCriteriaRequest.RestrictionData = contentRestriction.Serialize();
setSearchCriteriaRequest.FolderIds = new ulong[] { subfolderId1 };
setSearchCriteriaRequest.FolderIdCount = (ushort)setSearchCriteriaRequest.FolderIds.Length;
setSearchCriteriaRequest.SearchFlags = (uint)SetSearchFlags.ContentIndexedSearch | (uint)SetSearchFlags.RestartSearch | (uint)SetSearchFlags.StaticSearch;
setSearchCriteriaResponse = this.Adapter.SetSearchCriteria(setSearchCriteriaRequest, searchFolderHandle2, ref this.responseHandles);
Site.Assert.AreEqual<uint>(Constants.SuccessCode, setSearchCriteriaResponse.ReturnValue, "RopSearchCriteria ROP operation performs successfully!");
#endregion
#region Step 12. The client calls RopGetContentsTable to retrieve the contents table for the search folder [MSOXCFOLDSearchFolder2].
count = 0;
do
{
getContentsTableResponse = this.Adapter.GetContentsTable(getContentsTableRequest, searchFolderHandle2, ref this.responseHandles);
Site.Assert.AreEqual<uint>(Constants.SuccessCode, getContentsTableResponse.ReturnValue, "RopGetContentsTable ROP operation performs successfully!");
if (getContentsTableResponse.RowCount != 0)
{
Thread.Sleep(this.WaitTime);
}
else
{
break;
}
count++;
}
while (count < this.RetryCount);
// Add the debug information
Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R519");
// Verify MS-OXCFOLD requirement: MS-OXCFOLD_R519
// For no message should be found so the search folder should empty, which means the RowCount is 0.
Site.CaptureRequirementIfAreEqual<uint>(
0,
getContentsTableResponse.RowCount,
519,
@"[In Processing a RopSetSearchCriteria ROP Request] When new search criteria are applied, the server modifies the search folder to include only the messages that match the new search criteria.");
#endregion
}