/// <summary> /// This method is used to build a root node object from a byte array. /// </summary> /// <param name="fileContent">Specify the byte array.</param> /// <returns>Return a root node object build from the byte array.</returns> public RootNodeObject Build(byte[] fileContent) { RootNodeObject rootNode = new RootNodeObject(); rootNode.Signature = new SignatureObject(); rootNode.DataSize = new DataSizeObject(); rootNode.DataSize.DataSize = (ulong)fileContent.Length; rootNode.ExGuid = new ExGuid(SequenceNumberGenerator.GetCurrentSerialNumber(), Guid.NewGuid()); rootNode.IntermediateNodeObjectList = ChunkingFactory.CreateChunkingInstance(fileContent).Chunking(); return(rootNode); }
/// <summary> /// This method is used to create the instance of AbstractChunking. /// </summary> /// <param name="nodeObject">Specify the root node object.</param> /// <returns>The instance of AbstractChunking.</returns> public static AbstractChunking CreateChunkingInstance(RootNodeObject nodeObject) { byte[] fileContent = nodeObject.GetContent().ToArray(); if (EditorsTableUtils.IsEditorsTableHeader(fileContent)) { return(null); } if (ZipHeader.IsFileHeader(fileContent, 0)) { return(new ZipFilesChunking(fileContent)); } else { // For SharePoint Server 2013 compatible SUTs, always using the RDC Chunking method in the current test suite involved file resources. if (SharedContext.Current.CellStorageVersionType.MinorVersion >= 2) { return(new RDCAnalysisChunking(fileContent)); } // For SharePoint Server 2010 SP2 compatible SUTs, chunking method depends on file content and size. So first try using the simple chunking. AbstractChunking returnChunking = new SimpleChunking(fileContent); List <IntermediateNodeObject> nodes = returnChunking.Chunking(); if (nodeObject.IntermediateNodeObjectList.Count == nodes.Count) { bool isDataSizeMatching = true; for (int i = 0; i < nodes.Count; i++) { if (nodeObject.IntermediateNodeObjectList[i].DataSize.DataSize != nodes[i].DataSize.DataSize) { isDataSizeMatching = false; break; } } if (isDataSizeMatching) { return(returnChunking); } } // If the intermediate count number or data size does not equals, then try to use RDC chunking method. return(new RDCAnalysisChunking(fileContent)); } }
/// <summary> /// This method is used to create the instance of AbstractChunking. /// </summary> /// <param name="nodeObject">Specify the root node object.</param> /// <returns>The instance of AbstractChunking.</returns> public static AbstractChunking CreateChunkingInstance(RootNodeObject nodeObject) { byte[] fileContent = nodeObject.GetContent().ToArray(); if (EditorsTableUtils.IsEditorsTableHeader(fileContent)) { return null; } if (ZipHeader.IsFileHeader(fileContent, 0)) { return new ZipFilesChunking(fileContent); } else { // For SharePoint Server 2013 compatible SUTs, always using the RDC Chunking method in the current test suite involved file resources. if (SharedContext.Current.CellStorageVersionType.MinorVersion >= 2) { return new RDCAnalysisChunking(fileContent); } // For SharePoint Server 2010 SP2 compatible SUTs, chunking method depends on file content and size. So first try using the simple chunking. AbstractChunking returnChunking = new SimpleChunking(fileContent); List<IntermediateNodeObject> nodes = returnChunking.Chunking(); if (nodeObject.IntermediateNodeObjectList.Count == nodes.Count) { bool isDataSizeMatching = true; for (int i = 0; i < nodes.Count; i++) { if (nodeObject.IntermediateNodeObjectList[i].DataSize.DataSize != nodes[i].DataSize.DataSize) { isDataSizeMatching = false; break; } } if (isDataSizeMatching) { return returnChunking; } } // If the intermediate count number or data size does not equals, then try to use RDC chunking method. return new RDCAnalysisChunking(fileContent); } }
/// <summary> /// This method is used to create ObjectGroupObjectData instance from a root node object. /// </summary> /// <param name="node">Specify the node object.</param> /// <returns>Return the ObjectGroupObjectData instance.</returns> private ObjectGroupObjectData CreateObjectData(RootNodeObject node) { ObjectGroupObjectData objectData = new ObjectGroupObjectData(); objectData.CellIDArray = new CellIDArray(0u, null); List <ExGuid> extendedGuidList = new List <ExGuid>(); foreach (IntermediateNodeObject child in node.IntermediateNodeObjectList) { extendedGuidList.Add(child.ExGuid); } objectData.ObjectExGUIDArray = new ExGUIDArray(extendedGuidList); objectData.Data = new BinaryItem(node.SerializeToByteList()); return(objectData); }
/// <summary> /// This method is used to analyze the chunk for simple chunk. /// </summary> /// <param name="rootNode">Specify the root node object which is needed to be analyzed.</param> /// <param name="site">Specify the ITestSite instance.</param> public override void AnalyzeChunking(RootNodeObject rootNode, ITestSite site) { if (rootNode.DataSize.DataSize <= 1024 * 1024) { // These would be something ignored for MOSS2010, when the file size is less than 1MB. // In this case the server will response data without signature, but to be consistent with the behavior, // The Simple chunk still will be used, but empty signature check will be ignored. return; } else if (rootNode.DataSize.DataSize <= 250 * 1024 * 1024) { foreach (IntermediateNodeObject interNode in rootNode.IntermediateNodeObjectList) { SignatureObject expect = this.GetSignature(interNode.DataNodeObjectData.ObjectData); SignatureObject realValue = interNode.Signature; if (!expect.Equals(interNode.Signature)) { site.Assert.Fail("Expect the signature value {0}, but actual value is {1}", expect.ToString(), realValue.ToString()); } site.Assert.IsTrue(interNode.DataSize.DataSize <= 1024 * 1024, "The size of each chunk should be equal or less than 1MB for simple chunk."); site.Assert.AreEqual<ulong>( (ulong)interNode.GetContent().Count, interNode.DataSize.DataSize, "Expect the data size value equal the number represented by the chunk."); site.Assert.IsNotNull( interNode.DataNodeObjectData, "The Object References array of the Intermediate Node Object associated with this Data Node Object MUST have a single entry which MUST be the Object ID of the Data Node Object."); } site.Log.Add(LogEntryKind.Debug, "All the intermediate signature value matches."); if (SharedContext.Current.IsMsFsshttpRequirementsCaptured) { MsfsshttpdCapture.VerifySimpleChunk(SharedContext.Current.Site); } } else { throw new NotImplementedException("When the file size is larger than 250MB, because the signature method is not implemented, the analysis method is also not implemented."); } }
/// <summary> /// This method is used to analyze the chunk for simple chunk. /// </summary> /// <param name="rootNode">Specify the root node object which is needed to be analyzed.</param> /// <param name="site">Specify the ITestSite instance.</param> public override void AnalyzeChunking(RootNodeObject rootNode, ITestSite site) { if (rootNode.DataSize.DataSize <= 1024 * 1024) { // These would be something ignored for MOSS2010, when the file size is less than 1MB. // In this case the server will response data without signature, but to be consistent with the behavior, // The Simple chunk still will be used, but empty signature check will be ignored. return; } else if (rootNode.DataSize.DataSize <= 250 * 1024 * 1024) { foreach (IntermediateNodeObject interNode in rootNode.IntermediateNodeObjectList) { SignatureObject expect = this.GetSignature(interNode.DataNodeObjectData.ObjectData); SignatureObject realValue = interNode.Signature; if (!expect.Equals(interNode.Signature)) { site.Assert.Fail("Expect the signature value {0}, but actual value is {1}", expect.ToString(), realValue.ToString()); } site.Assert.IsTrue(interNode.DataSize.DataSize <= 1024 * 1024, "The size of each chunk should be equal or less than 1MB for simple chunk."); site.Assert.AreEqual <ulong>( (ulong)interNode.GetContent().Count, interNode.DataSize.DataSize, "Expect the data size value equal the number represented by the chunk."); site.Assert.IsNotNull( interNode.DataNodeObjectData, "The Object References array of the Intermediate Node Object associated with this Data Node Object MUST have a single entry which MUST be the Object ID of the Data Node Object."); } site.Log.Add(LogEntryKind.Debug, "All the intermediate signature value matches."); if (SharedContext.Current.IsMsFsshttpRequirementsCaptured) { MsfsshttpdCapture.VerifySimpleChunk(SharedContext.Current.Site); } } else { throw new NotImplementedException("When the file size is larger than 250MB, because the signature method is not implemented, the analysis method is also not implemented."); } }
/// <summary> /// This method is used to analyze the chunk for the RDC analysis chunk method. /// </summary> /// <param name="rootNode">Specify the root node object which is needed to be analyzed.</param> /// <param name="site">Specify the ITestSite instance.</param> public override void AnalyzeChunking(RootNodeObject rootNode, TestTools.ITestSite site) { List<IntermediateNodeObject> expectList = this.Chunking(); foreach (IntermediateNodeObject nodeObject in rootNode.IntermediateNodeObjectList) { IntermediateNodeObject expect = expectList.First(); if (!expect.Signature.Equals(nodeObject.Signature)) { site.Assert.Fail("For the RDC chunk method expect the signature {0}, actual signature {1}", expect.ToString(), nodeObject.Signature.ToString()); } if (expect.DataSize.DataSize != nodeObject.DataSize.DataSize) { site.Assert.Fail("For the RDC chunk method expect the chunk size, actual chunk size {1}", expect.DataSize.DataSize, nodeObject.DataSize.DataSize); } expectList.RemoveAt(0); } // If runs here, then all the requirements related for RDC analysis can be captured. MsfsshttpdCapture.VerifyRdcAnalysisChunk(SharedContext.Current.Site); }
/// <summary> /// This method is used to analyze the chunk for the RDC analysis chunk method. /// </summary> /// <param name="rootNode">Specify the root node object which is needed to be analyzed.</param> /// <param name="site">Specify the ITestSite instance.</param> public override void AnalyzeChunking(RootNodeObject rootNode, TestTools.ITestSite site) { List <IntermediateNodeObject> expectList = this.Chunking(); foreach (IntermediateNodeObject nodeObject in rootNode.IntermediateNodeObjectList) { IntermediateNodeObject expect = expectList.First(); if (!expect.Signature.Equals(nodeObject.Signature)) { site.Assert.Fail("For the RDC chunk method expect the signature {0}, actual signature {1}", expect.ToString(), nodeObject.Signature.ToString()); } if (expect.DataSize.DataSize != nodeObject.DataSize.DataSize) { site.Assert.Fail("For the RDC chunk method expect the chunk size, actual chunk size {1}", expect.DataSize.DataSize, nodeObject.DataSize.DataSize); } expectList.RemoveAt(0); } // If runs here, then all the requirements related for RDC analysis can be captured. MsfsshttpdCapture.VerifyRdcAnalysisChunk(SharedContext.Current.Site); }
/// <summary> /// This method is used to verify the root node related requirements. /// </summary> /// <param name="instance">Specify the intermediate node instance.</param> /// <param name="site">Specify the ITestSite instance.</param> public void VerifyRootNodeObject(RootNodeObject instance, ITestSite site) { // If the instance is not null and there are no parsing errors, then the RootNodeObject related adapter requirements can be directly captured. if (null == instance) { site.Assert.Fail("The instance of type RootNodeObject is null due to parsing error or type casting error."); } // Verify the stream object header related requirements. this.ExpectStreamObjectHeaderStart(instance.StreamObjectHeaderStart, instance.GetType(), site); // Capture requirement MS-FSSHTTPD_R37, if stream object start type is StreamObjectHeaderStart32bit. site.CaptureRequirement( "MS-FSSHTTPD", 37, @"[In Root Node Object Data] Root Node Start (2 bytes): A 16-bit stream object header, as specified in [MS-FSSHTTPB] section 2.2.1.5.1, with a Header Type of 0x00, Compound of 0x1, Type of 0x20, and Length of 0x00."); // Verify MS-FSSHTTPD requirement: MS-FSSHTTPD_R38 site.CaptureRequirementIfAreEqual<ushort>( 0x104, LittleEndianBitConverter.ToUInt16(instance.StreamObjectHeaderStart.SerializeToByteList().ToArray(), 0), "MS-FSSHTTPD", 38, @"[In Root Node Object Data] Root Node Start (2 bytes): The value of this field[Root Node Start] MUST be 0x0104."); // Directly capture requirement MS-FSSHTTPD_R38, if all above asserts pass. site.CaptureRequirementIfAreEqual<Type>( typeof(StreamObjectHeaderStart16bit), instance.DataSize.StreamObjectHeaderStart.GetType(), "MS-FSSHTTPD", 43, @"[In Root Node Object Data] Data Size Header (2 bytes): A 16-bit stream object header, as specified in [MS-FSSHTTPB] section 2.2.1.5.1, with a Header Type of 0x00, Compound of 0x0, Type of 0x22, and Length of 0x08 (the size, in bytes, of Data Size)."); // Verify MS-FSSHTTPD requirement: MS-FSSHTTPD_R8010 site.CaptureRequirementIfAreEqual<uint>( 0x1110, LittleEndianBitConverter.ToUInt16(instance.DataSize.StreamObjectHeaderStart.SerializeToByteList().ToArray(), 0), "MS-FSSHTTPD", 8010, @"[In Root Node Object Data] Data Size Header (2 bytes): The value of this field[Data Size Header] MUST be 0x1110."); // Verify MS-FSSHTTPD requirement: MS-FSSHTTPD_R39 site.CaptureRequirementIfAreEqual<Type>( typeof(StreamObjectHeaderStart16bit), instance.Signature.StreamObjectHeaderStart.GetType(), "MS-FSSHTTPD", 39, @"[In Root Node Object Data] Signature Header (2 bytes): A 16-bit stream object header, as specified in [MS-FSSHTTPB] section 2.2.1.5.1, with a Header Type of 0x00, Compound of 0x0, Type of 0x21, and Length equal to the size of Signature Data."); // Verify the stream object header end related requirements. this.ExpectStreamObjectHeaderEnd(instance.StreamObjectHeaderEnd, instance.GetType(), site); this.ExpectCompoundObject(instance.StreamObjectHeaderStart, site); // Verify MS-FSSHTTPD requirement: MS-FSSHTTPD_R45 site.CaptureRequirementIfAreEqual<Type>( typeof(StreamObjectHeaderEnd8bit), instance.StreamObjectHeaderEnd.GetType(), "MS-FSSHTTPD", 45, @"[In Root Node Object Data] Root Node End (1 byte): An 8-bit stream object header end, as specified in [MS-FSSHTTPB] section 2.2.1.5.3, that specifies a stream object of type 0x20."); // Verify MS-FSSHTTPD requirement: MS-FSSHTTPD_R46 site.CaptureRequirementIfAreEqual<byte>( 0x81, instance.StreamObjectHeaderEnd.SerializeToByteList()[0], "MS-FSSHTTPD", 46, @"[In Root Node Object Data] Root Node End (1 byte): The value of this field[Root Node End] MUST be 0x81."); }
/// <summary> /// This method is used to create ObjectGroupObjectData instance from a root node object. /// </summary> /// <param name="node">Specify the node object.</param> /// <returns>Return the ObjectGroupObjectData instance.</returns> private ObjectGroupObjectData CreateObjectData(RootNodeObject node) { ObjectGroupObjectData objectData = new ObjectGroupObjectData(); objectData.CellIDArray = new CellIDArray(0u, null); List<ExGuid> extendedGuidList = new List<ExGuid>(); foreach (IntermediateNodeObject child in node.IntermediateNodeObjectList) { extendedGuidList.Add(child.ExGuid); } objectData.ObjectExGUIDArray = new ExGUIDArray(extendedGuidList); objectData.Data = new BinaryItem(node.SerializeToByteList()); return objectData; }
/// <summary> /// This method is used to verify the requirements related with the RootNodeObject type. /// </summary> /// <param name="rootNode">Specify the RootNodeObject instance.</param> /// <param name="site">Specify the ITestSite instance.</param> public static void VerifyRootNodeObject(RootNodeObject rootNode, ITestSite site) { // Verify MS-FSSHTTPD requirement: MS-FSSHTTPD_R44 site.CaptureRequirementIfAreEqual<ulong>( (ulong)rootNode.GetContent().Count, rootNode.DataSize.DataSize, "MS-FSSHTTPD", 44, @"[In Root Node Object Data] Data Size (8 bytes): An unsigned 64-bit integer that specifies the size of the file data represented by this Root Node Object."); // Verify MS-FSSHTTPD requirement: MS-FSSHTTPD_R49 site.CaptureRequirementIfAreEqual<ulong>( (ulong)rootNode.GetContent().Count, rootNode.DataSize.DataSize, "MS-FSSHTTPD", 49, @"[In Root Node Object References] The sum of the Data Size values from all of the Intermediate Node Objects MUST equal the Data Size specified in the Object Data of this Root Node Object."); // When after build the Root node object successfully, the following requirements can be directly captured. site.CaptureRequirement( "MS-FSSHTTPD", 48, @"[In Root Node Object References] Each Object Extended GUID MUST specify an Intermediate Node Object."); // Verify MS-FSSHTTPD requirement: MS-FSSHTTPD_R8011 site.CaptureRequirement( "MS-FSSHTTPD", 8011, @"[In Root Node Object References] The Object Extended GUID Array, as specified in [MS-FSSHTTPB] section 2.2.1.12.6.4, of the Root Node Object MUST specify an ordered set of Object Extended GUIDs. "); // Verify MS-FSSHTTPD requirement: MS-FSSHTTPD_R8012 site.CaptureRequirement( "MS-FSSHTTPD", 8012, @"[In Root Node Object References] Object Extended GUID Array entries MUST be ordered based on the sequential file bytes represented by each Node Object."); }
/// <summary> /// This method is used to build intermediate node object from an list of object group data element. /// </summary> /// <param name="objectGroupList">Specify the list of object group data elements.</param> /// <param name="dataObj">Specify the object group object.</param> /// <param name="intermediateGuid">Specify the intermediate extended GUID.</param> /// <returns>Return the intermediate node object.</returns> public IntermediateNodeObject Build(List <ObjectGroupDataElementData> objectGroupList, ObjectGroupObjectData dataObj, ExGuid intermediateGuid) { IntermediateNodeObject node = null; RootNodeObject rootNode = null; int index = 0; if (StreamObject.TryGetCurrent <IntermediateNodeObject>(dataObj.Data.Content.ToArray(), ref index, out node)) { if (dataObj.ObjectExGUIDArray == null) { throw new InvalidOperationException("Failed to build intermediate node because the object extend GUID array does not exist."); } node.ExGuid = intermediateGuid; // Contain a single Data Node Object. if (dataObj.ObjectExGUIDArray.Count.DecodedValue == 1u) { ObjectGroupObjectDeclare dataNodeDeclare; ObjectGroupObjectData dataNodeData = this.FindByExGuid(objectGroupList, dataObj.ObjectExGUIDArray.Content[0], out dataNodeDeclare); BinaryItem data = dataNodeData.Data; node.DataNodeObjectData = new DataNodeObjectData(data.Content.ToArray(), 0, (int)data.Length.DecodedValue); node.DataNodeObjectData.ExGuid = dataObj.ObjectExGUIDArray.Content[0]; node.IntermediateNodeObjectList = null; if (SharedContext.Current.IsMsFsshttpRequirementsCaptured) { MsfsshttpdCapture.VerifyObjectGroupObjectDataForDataNodeObject(dataNodeData, dataNodeDeclare, objectGroupList, SharedContext.Current.Site); } } else { // Contain a list of IntermediateNodeObject node.IntermediateNodeObjectList = new List <IntermediateNodeObject>(); node.DataNodeObjectData = null; foreach (ExGuid extGuid in dataObj.ObjectExGUIDArray.Content) { ObjectGroupObjectDeclare intermediateDeclare; ObjectGroupObjectData intermediateData = this.FindByExGuid(objectGroupList, extGuid, out intermediateDeclare); node.IntermediateNodeObjectList.Add(new IntermediateNodeObjectBuilder().Build(objectGroupList, intermediateData, extGuid)); if (SharedContext.Current.IsMsFsshttpRequirementsCaptured) { MsfsshttpdCapture.VerifyObjectGroupObjectDataForIntermediateNode(intermediateData, intermediateDeclare, objectGroupList, SharedContext.Current.Site); } } } } else if (StreamObject.TryGetCurrent <RootNodeObject>(dataObj.Data.Content.ToArray(), ref index, out rootNode)) { // In Sub chunking for larger than 1MB zip file, MOSS2010 could return RootNodeObject. // For easy further process, the rootNode will be replaced by intermediate node instead. node = new IntermediateNodeObject(); node.IntermediateNodeObjectList = new List <IntermediateNodeObject>(); node.DataSize = rootNode.DataSize; node.ExGuid = rootNode.ExGuid; node.Signature = rootNode.Signature; node.DataNodeObjectData = null; foreach (ExGuid extGuid in dataObj.ObjectExGUIDArray.Content) { ObjectGroupObjectDeclare intermediateDeclare; ObjectGroupObjectData intermediateData = this.FindByExGuid(objectGroupList, extGuid, out intermediateDeclare); node.IntermediateNodeObjectList.Add(new IntermediateNodeObjectBuilder().Build(objectGroupList, intermediateData, extGuid)); if (SharedContext.Current.IsMsFsshttpRequirementsCaptured) { MsfsshttpdCapture.VerifyObjectGroupObjectDataForIntermediateNode(intermediateData, intermediateDeclare, objectGroupList, SharedContext.Current.Site); } } } else { throw new InvalidOperationException("In the ObjectGroupDataElement cannot only contain the RootNodeObject or IntermediateNodeOBject."); } return(node); }
/// <summary> /// This method is used to analyze the chunk. /// </summary> /// <param name="rootNode">Specify the root node object which is needed to be analyzed.</param> /// <param name="site">Specify the ITestSite instance.</param> public abstract void AnalyzeChunking(RootNodeObject rootNode, ITestSite site);
/// <summary> /// This method is used to build a root node object from an object group data element list with the specified root extended GUID. /// </summary> /// <param name="objectGroupList">Specify the object group data element list.</param> /// <param name="rootExGuid">Specify the root extended GUID.</param> /// <returns>Return a root node object build from the object group data element list.</returns> private RootNodeObject Build(List <ObjectGroupDataElementData> objectGroupList, ExGuid rootExGuid) { ObjectGroupObjectDeclare rootDeclare; ObjectGroupObjectData root = this.FindByExGuid(objectGroupList, rootExGuid, out rootDeclare); if (SharedContext.Current.IsMsFsshttpRequirementsCaptured) { MsfsshttpdCapture.VerifyObjectCount(root, SharedContext.Current.Site); } int index = 0; RootNodeObject rootNode = null; if (StreamObject.TryGetCurrent <RootNodeObject>(root.Data.Content.ToArray(), ref index, out rootNode)) { rootNode.ExGuid = rootExGuid; foreach (ExGuid extGuid in root.ObjectExGUIDArray.Content) { ObjectGroupObjectDeclare intermediateDeclare; ObjectGroupObjectData intermediateData = this.FindByExGuid(objectGroupList, extGuid, out intermediateDeclare); rootNode.IntermediateNodeObjectList.Add(new IntermediateNodeObject.IntermediateNodeObjectBuilder().Build(objectGroupList, intermediateData, extGuid)); // Capture the intermediate related requirements if (SharedContext.Current.IsMsFsshttpRequirementsCaptured) { MsfsshttpdCapture.VerifyObjectGroupObjectDataForIntermediateNode(intermediateData, intermediateDeclare, objectGroupList, SharedContext.Current.Site); MsfsshttpdCapture.VerifyIntermediateNodeObject(rootNode.IntermediateNodeObjectList.Last(), SharedContext.Current.Site); } } if (SharedContext.Current.IsMsFsshttpRequirementsCaptured) { // Capture the root node related requirements. MsfsshttpdCapture.VerifyObjectGroupObjectDataForRootNode(root, rootDeclare, objectGroupList, SharedContext.Current.Site); MsfsshttpdCapture.VerifyRootNodeObject(rootNode, SharedContext.Current.Site); } } else { // If there is only one object in the file, SharePoint Server 2010 does not return the Root Node Object, but an Intermediate Node Object at the beginning. // At this case, we will add the root node object for the further parsing. rootNode = new RootNodeObject(); rootNode.ExGuid = rootExGuid; rootNode.IntermediateNodeObjectList.Add(new IntermediateNodeObject.IntermediateNodeObjectBuilder().Build(objectGroupList, root, rootExGuid)); rootNode.DataSize = new DataSizeObject(); rootNode.DataSize.DataSize = (ulong)rootNode.IntermediateNodeObjectList.Sum(o => (float)o.DataSize.DataSize); } // Capture all the signature related requirements. if (SharedContext.Current.IsMsFsshttpRequirementsCaptured) { AbstractChunking chunking = ChunkingFactory.CreateChunkingInstance(rootNode); if (chunking != null) { chunking.AnalyzeChunking(rootNode, SharedContext.Current.Site); } } return(rootNode); }
/// <summary> /// This method is used to verify the root node related requirements. /// </summary> /// <param name="instance">Specify the intermediate node instance.</param> /// <param name="site">Specify the ITestSite instance.</param> public void VerifyRootNodeObject(RootNodeObject instance, ITestSite site) { // If the instance is not null and there are no parsing errors, then the RootNodeObject related adapter requirements can be directly captured. if (null == instance) { site.Assert.Fail("The instance of type RootNodeObject is null due to parsing error or type casting error."); } // Verify the stream object header related requirements. this.ExpectStreamObjectHeaderStart(instance.StreamObjectHeaderStart, instance.GetType(), site); // Capture requirement MS-FSSHTTPD_R37, if stream object start type is StreamObjectHeaderStart32bit. site.CaptureRequirement( "MS-FSSHTTPD", 37, @"[In Root Node Object Data] Root Node Start (2 bytes): A 16-bit stream object header, as specified in [MS-FSSHTTPB] section 2.2.1.5.1, with a Header Type of 0x00, Compound of 0x1, Type of 0x20, and Length of 0x00."); // Verify MS-FSSHTTPD requirement: MS-FSSHTTPD_R38 site.CaptureRequirementIfAreEqual <ushort>( 0x104, LittleEndianBitConverter.ToUInt16(instance.StreamObjectHeaderStart.SerializeToByteList().ToArray(), 0), "MS-FSSHTTPD", 38, @"[In Root Node Object Data] Root Node Start (2 bytes): The value of this field[Root Node Start] MUST be 0x0104."); // Directly capture requirement MS-FSSHTTPD_R38, if all above asserts pass. site.CaptureRequirementIfAreEqual <Type>( typeof(StreamObjectHeaderStart16bit), instance.DataSize.StreamObjectHeaderStart.GetType(), "MS-FSSHTTPD", 43, @"[In Root Node Object Data] Data Size Header (2 bytes): A 16-bit stream object header, as specified in [MS-FSSHTTPB] section 2.2.1.5.1, with a Header Type of 0x00, Compound of 0x0, Type of 0x22, and Length of 0x08 (the size, in bytes, of Data Size)."); // Verify MS-FSSHTTPD requirement: MS-FSSHTTPD_R8010 site.CaptureRequirementIfAreEqual <uint>( 0x1110, LittleEndianBitConverter.ToUInt16(instance.DataSize.StreamObjectHeaderStart.SerializeToByteList().ToArray(), 0), "MS-FSSHTTPD", 8010, @"[In Root Node Object Data] Data Size Header (2 bytes): The value of this field[Data Size Header] MUST be 0x1110."); // Verify MS-FSSHTTPD requirement: MS-FSSHTTPD_R39 site.CaptureRequirementIfAreEqual <Type>( typeof(StreamObjectHeaderStart16bit), instance.Signature.StreamObjectHeaderStart.GetType(), "MS-FSSHTTPD", 39, @"[In Root Node Object Data] Signature Header (2 bytes): A 16-bit stream object header, as specified in [MS-FSSHTTPB] section 2.2.1.5.1, with a Header Type of 0x00, Compound of 0x0, Type of 0x21, and Length equal to the size of Signature Data."); // Verify the stream object header end related requirements. this.ExpectStreamObjectHeaderEnd(instance.StreamObjectHeaderEnd, instance.GetType(), site); this.ExpectCompoundObject(instance.StreamObjectHeaderStart, site); // Verify MS-FSSHTTPD requirement: MS-FSSHTTPD_R45 site.CaptureRequirementIfAreEqual <Type>( typeof(StreamObjectHeaderEnd8bit), instance.StreamObjectHeaderEnd.GetType(), "MS-FSSHTTPD", 45, @"[In Root Node Object Data] Root Node End (1 byte): An 8-bit stream object header end, as specified in [MS-FSSHTTPB] section 2.2.1.5.3, that specifies a stream object of type 0x20."); // Verify MS-FSSHTTPD requirement: MS-FSSHTTPD_R46 site.CaptureRequirementIfAreEqual <byte>( 0x81, instance.StreamObjectHeaderEnd.SerializeToByteList()[0], "MS-FSSHTTPD", 46, @"[In Root Node Object Data] Root Node End (1 byte): The value of this field[Root Node End] MUST be 0x81."); }
/// <summary> /// This method is used to analyze the chunk. /// </summary> /// <param name="rootNode">Specify the root node object which will be analyzed.</param> /// <param name="site">Specify the ITestSite instance.</param> public override void AnalyzeChunking(RootNodeObject rootNode, ITestSite site) { List<IntermediateNodeObject> cloneList = new List<IntermediateNodeObject>(rootNode.IntermediateNodeObjectList); while (cloneList.Count != 0) { IntermediateNodeObject nodeObject = cloneList.First(); byte[] content = nodeObject.DataNodeObjectData.ObjectData; if (cloneList.Count == 1) { if (content.Length > 1048576) { throw new NotImplementedException("If the final chunk is larger than 1MB, the signature method is not implemented."); } // Only final chunk left SignatureObject expect = this.GetSHA1Signature(content); if (!expect.Equals(nodeObject.Signature)) { site.Assert.Fail("For the Zip file, final part chunk expect the signature {0}, actual signature {1}", expect.ToString(), nodeObject.Signature.ToString()); } // Verify the less than 1MB final part related requirements if (SharedContext.Current.IsMsFsshttpRequirementsCaptured) { MsfsshttpdCapture.VerifySmallFinalChunk(SharedContext.Current.Site); } } else { if (ZipHeader.IsFileHeader(content, 0)) { byte[] dataFileSignatureBytes; byte[] header = this.AnalyzeFileHeader(content, 0, out dataFileSignatureBytes); int headerLength = header.Length; int compressedSize = (int)this.GetCompressedSize(dataFileSignatureBytes); if (headerLength + compressedSize <= 4096) { IntermediateNodeObject expectNode = new IntermediateNodeObject.IntermediateNodeObjectBuilder().Build(content, this.GetSingleChunkSignature(header, dataFileSignatureBytes)); if (!expectNode.Signature.Equals(nodeObject.Signature)) { site.Assert.Fail("For the Zip file, when zip file is less than 4096, expect the signature {0}, actual signature {1}", expectNode.Signature.ToString(), nodeObject.Signature.ToString()); } // Verify the zip file less than 4096 bytes MsfsshttpdCapture.VerifyZipFileLessThan4096Bytes(SharedContext.Current.Site); } else { SignatureObject expectHeader = this.GetSHA1Signature(header); if (!expectHeader.Equals(nodeObject.Signature)) { site.Assert.Fail("For the Zip file header, expect the signature {0}, actual signature {1}", expectHeader.ToString(), nodeObject.Signature.ToString()); } // Remove the header node cloneList.RemoveAt(0); // Then expect the next is file content node nodeObject = cloneList.First(); // Here having something need to be distinguished between the MOSS2010 and MOSS2013 if (nodeObject.DataNodeObjectData == null && nodeObject.IntermediateNodeObjectList != null) { // This situation could most happens for MOSS2010, we fake intermediate node instead of the root node when the zip file size is larger than 1M. // In the current stage, this kind of signature algorithm is not mentioned in the open specification, so leave this verify blank. } else if (nodeObject.DataNodeObjectData != null) { site.Assert.AreEqual<ulong>( (ulong)compressedSize, nodeObject.DataSize.DataSize, "The Data Size of the Intermediate Node Object MUST be the total number of bytes represented by the chunk."); SignatureObject contentSignature = new SignatureObject(); contentSignature.SignatureData = new BinaryItem(dataFileSignatureBytes); if (!contentSignature.Equals(nodeObject.Signature)) { site.Assert.Fail("For the Zip file content, expect the signature {0}, actual signature {1}", contentSignature.ToString(), nodeObject.Signature.ToString()); } // Verify the zip file larger than 4096 bytes and less than 1MB. if (SharedContext.Current.IsMsFsshttpRequirementsCaptured) { MsfsshttpdCapture.VerifyZipFileHeaderAndContentSignature(SharedContext.Current.Site); MsfsshttpdCapture.VerifyIntermediateNodeForZipFileChunk(SharedContext.Current.Site); } } else { throw new InvalidOperationException("The DataNodeObjectData and IntermediateNodeObjectList cannot be null at the same time."); } } } } cloneList.RemoveAt(0); } }
/// <summary> /// This method is used to build a root node object from an object group data element list with the specified root extended GUID. /// </summary> /// <param name="objectGroupList">Specify the object group data element list.</param> /// <param name="rootExGuid">Specify the root extended GUID.</param> /// <returns>Return a root node object build from the object group data element list.</returns> private RootNodeObject Build(List<ObjectGroupDataElementData> objectGroupList, ExGuid rootExGuid) { ObjectGroupObjectDeclare rootDeclare; ObjectGroupObjectData root = this.FindByExGuid(objectGroupList, rootExGuid, out rootDeclare); if (SharedContext.Current.IsMsFsshttpRequirementsCaptured) { MsfsshttpdCapture.VerifyObjectCount(root, SharedContext.Current.Site); } int index = 0; RootNodeObject rootNode = null; if (StreamObject.TryGetCurrent<RootNodeObject>(root.Data.Content.ToArray(), ref index, out rootNode)) { rootNode.ExGuid = rootExGuid; foreach (ExGuid extGuid in root.ObjectExGUIDArray.Content) { ObjectGroupObjectDeclare intermediateDeclare; ObjectGroupObjectData intermediateData = this.FindByExGuid(objectGroupList, extGuid, out intermediateDeclare); rootNode.IntermediateNodeObjectList.Add(new IntermediateNodeObject.IntermediateNodeObjectBuilder().Build(objectGroupList, intermediateData, extGuid)); // Capture the intermediate related requirements if (SharedContext.Current.IsMsFsshttpRequirementsCaptured) { MsfsshttpdCapture.VerifyObjectGroupObjectDataForIntermediateNode(intermediateData, intermediateDeclare, objectGroupList, SharedContext.Current.Site); MsfsshttpdCapture.VerifyIntermediateNodeObject(rootNode.IntermediateNodeObjectList.Last(), SharedContext.Current.Site); } } if (SharedContext.Current.IsMsFsshttpRequirementsCaptured) { // Capture the root node related requirements. MsfsshttpdCapture.VerifyObjectGroupObjectDataForRootNode(root, rootDeclare, objectGroupList, SharedContext.Current.Site); MsfsshttpdCapture.VerifyRootNodeObject(rootNode, SharedContext.Current.Site); } } else { // If there is only one object in the file, SharePoint Server 2010 does not return the Root Node Object, but an Intermediate Node Object at the beginning. // At this case, we will add the root node object for the further parsing. rootNode = new RootNodeObject(); rootNode.ExGuid = rootExGuid; rootNode.IntermediateNodeObjectList.Add(new IntermediateNodeObject.IntermediateNodeObjectBuilder().Build(objectGroupList, root, rootExGuid)); rootNode.DataSize = new DataSizeObject(); rootNode.DataSize.DataSize = (ulong)rootNode.IntermediateNodeObjectList.Sum(o => (float)o.DataSize.DataSize); } // Capture all the signature related requirements. if (SharedContext.Current.IsMsFsshttpRequirementsCaptured) { AbstractChunking chunking = ChunkingFactory.CreateChunkingInstance(rootNode); if (chunking != null) { chunking.AnalyzeChunking(rootNode, SharedContext.Current.Site); } } return rootNode; }
/// <summary> /// This method is used to build a root node object from a byte array. /// </summary> /// <param name="fileContent">Specify the byte array.</param> /// <returns>Return a root node object build from the byte array.</returns> public RootNodeObject Build(byte[] fileContent) { RootNodeObject rootNode = new RootNodeObject(); rootNode.Signature = new SignatureObject(); rootNode.DataSize = new DataSizeObject(); rootNode.DataSize.DataSize = (ulong)fileContent.Length; rootNode.ExGuid = new ExGuid(SequenceNumberGenerator.GetCurrentSerialNumber(), Guid.NewGuid()); rootNode.IntermediateNodeObjectList = ChunkingFactory.CreateChunkingInstance(fileContent).Chunking(); return rootNode; }
/// <summary> /// This method is used to analyze the chunk. /// </summary> /// <param name="rootNode">Specify the root node object which will be analyzed.</param> /// <param name="site">Specify the ITestSite instance.</param> public override void AnalyzeChunking(RootNodeObject rootNode, ITestSite site) { List <IntermediateNodeObject> cloneList = new List <IntermediateNodeObject>(rootNode.IntermediateNodeObjectList); while (cloneList.Count != 0) { IntermediateNodeObject nodeObject = cloneList.First(); byte[] content = nodeObject.DataNodeObjectData.ObjectData; if (cloneList.Count == 1) { if (content.Length > 1048576) { throw new NotImplementedException("If the final chunk is larger than 1MB, the signature method is not implemented."); } // Only final chunk left SignatureObject expect = this.GetSHA1Signature(content); if (!expect.Equals(nodeObject.Signature)) { site.Assert.Fail("For the Zip file, final part chunk expect the signature {0}, actual signature {1}", expect.ToString(), nodeObject.Signature.ToString()); } // Verify the less than 1MB final part related requirements if (SharedContext.Current.IsMsFsshttpRequirementsCaptured) { MsfsshttpdCapture.VerifySmallFinalChunk(SharedContext.Current.Site); } } else { if (ZipHeader.IsFileHeader(content, 0)) { byte[] dataFileSignatureBytes; byte[] header = this.AnalyzeFileHeader(content, 0, out dataFileSignatureBytes); int headerLength = header.Length; int compressedSize = (int)this.GetCompressedSize(dataFileSignatureBytes); if (headerLength + compressedSize <= 4096) { IntermediateNodeObject expectNode = new IntermediateNodeObject.IntermediateNodeObjectBuilder().Build(content, this.GetSingleChunkSignature(header, dataFileSignatureBytes)); if (!expectNode.Signature.Equals(nodeObject.Signature)) { site.Assert.Fail("For the Zip file, when zip file is less than 4096, expect the signature {0}, actual signature {1}", expectNode.Signature.ToString(), nodeObject.Signature.ToString()); } // Verify the zip file less than 4096 bytes MsfsshttpdCapture.VerifyZipFileLessThan4096Bytes(SharedContext.Current.Site); } else { SignatureObject expectHeader = this.GetSHA1Signature(header); if (!expectHeader.Equals(nodeObject.Signature)) { site.Assert.Fail("For the Zip file header, expect the signature {0}, actual signature {1}", expectHeader.ToString(), nodeObject.Signature.ToString()); } // Remove the header node cloneList.RemoveAt(0); // Then expect the next is file content node nodeObject = cloneList.First(); // Here having something need to be distinguished between the MOSS2010 and MOSS2013 if (nodeObject.DataNodeObjectData == null && nodeObject.IntermediateNodeObjectList != null) { // This situation could most happens for MOSS2010, we fake intermediate node instead of the root node when the zip file size is larger than 1M. // In the current stage, this kind of signature algorithm is not mentioned in the open specification, so leave this verify blank. } else if (nodeObject.DataNodeObjectData != null) { site.Assert.AreEqual <ulong>( (ulong)compressedSize, nodeObject.DataSize.DataSize, "The Data Size of the Intermediate Node Object MUST be the total number of bytes represented by the chunk."); SignatureObject contentSignature = new SignatureObject(); contentSignature.SignatureData = new BinaryItem(dataFileSignatureBytes); if (!contentSignature.Equals(nodeObject.Signature)) { site.Assert.Fail("For the Zip file content, expect the signature {0}, actual signature {1}", contentSignature.ToString(), nodeObject.Signature.ToString()); } // Verify the zip file larger than 4096 bytes and less than 1MB. if (SharedContext.Current.IsMsFsshttpRequirementsCaptured) { MsfsshttpdCapture.VerifyZipFileHeaderAndContentSignature(SharedContext.Current.Site); MsfsshttpdCapture.VerifyIntermediateNodeForZipFileChunk(SharedContext.Current.Site); } } else { throw new InvalidOperationException("The DataNodeObjectData and IntermediateNodeObjectList cannot be null at the same time."); } } } } cloneList.RemoveAt(0); } }