public override void CalculateExpectedTestingTime(ICollection otherSubTests, ISubTestArgument arg) { // get the results from the prerequisite tests CdsResult_BrowseFilter FILTER_RESULTS = null; CdsResult_BrowseRange RANGE_RESULTS = null; CdsResult_BrowseSortCriteria SORT_RESULTS = null; foreach (ISubTest preTest in otherSubTests) { if (preTest.Name == this.PRE_FILTER.Name) { FILTER_RESULTS = preTest.Details as CdsResult_BrowseFilter; } else if (preTest.Name == this.PRE_RANGE.Name) { RANGE_RESULTS = preTest.Details as CdsResult_BrowseRange; } else if (preTest.Name == this.PRE_SORT.Name) { SORT_RESULTS = preTest.Details as CdsResult_BrowseSortCriteria; } } if (FILTER_RESULTS == null) { return; } if (RANGE_RESULTS == null) { return; } if (SORT_RESULTS == null) { return; } CdsResult_BrowseAll BROWSE_ALL = FILTER_RESULTS.BrowseAllResults; if (BROWSE_ALL.LargestContainer == null) { return; } if (BROWSE_ALL.MostMetadata == null) { return; } if (SORT_RESULTS.SortFields == null) { return; } int max = Math.Max(FILTER_RESULTS.Filters.Count, BROWSE_ALL.LargestContainer.ChildCount); max = Math.Max(max, SORT_RESULTS.SortFields.Count); this._ExpectedTestingTime = max * 900; }
public override void CalculateExpectedTestingTime(ICollection otherSubTests, ISubTestArgument arg) { // get the results from the BrowseAll test CdsResult_BrowseAll PRE = null; foreach (ISubTest preTest in otherSubTests) { if (preTest.Name == this.PRE_BROWSEALL.Name) { if (preTest.TestState >= UPnPTestStates.Pass) { PRE = preTest.Details as CdsResult_BrowseAll; break; } } } if (PRE == null) { return; } if (PRE.LargestContainer == null) { return; } if (PRE.Root == null) { return; } int totalBrowses = CalculateExpectedBrowseRequests(PRE.LargestContainer) + CalculateExpectedBrowseRequests(PRE.Root); int maxTime = 300 * totalBrowses; this._ExpectedTestingTime = maxTime; }
public override void CalculateExpectedTestingTime(ICollection otherSubTests, ISubTestArgument arg) { // get the results from the BrowseAll test CdsResult_BrowseAll PRE = null; foreach (ISubTest preTest in otherSubTests) { if (preTest.Name == this.PRE_BROWSEALL.Name) { if (preTest.TestState >= UPnPTestStates.Pass) { PRE = preTest.Details as CdsResult_BrowseAll; break; } } } if (PRE == null) { return; } if (PRE.MostMetadata == null) { return; } if (PRE.MostMetadata.Properties.Count != PRE.MostMetadata.Properties.PropertyNames.Count) { return; } IUPnPMedia MM = PRE.MostMetadata; if (MM == null) { return; } IMediaContainer MC = PRE.MostMetadata.Parent; if (MC == null) { return; } int numProps = MM.Properties.Count; int numChildren = MC.ChildCount; // we browse for "res" and each possible res@attribute numProps += (2 * MediaResource.GetPossibleAttributes().Count) + 2; int expectedBrowses = 0; int inc = numProps / 4; if (inc == 0) { inc = 1; } for (int nProps = 0; nProps < numProps; nProps++) { for (int iProp = 0; iProp < numProps; iProp += inc) { expectedBrowses++; } } expectedBrowses *= 2; int maxTime = 90 * expectedBrowses; this._ExpectedTestingTime = maxTime; }
public override UPnPTestStates Run(ICollection otherSubTests, CdsSubTestArgument arg) { CpContentDirectory CDS = this.GetCDS(arg._Device); _Details = new CdsResult_BrowseFilter(); this._TestState = UPnPTestStates.Running; arg._TestGroup.AddEvent(LogImportance.Remark, this.Name, "\"" + this.Name + "\" started."); // get the results from the BrowseAll test CdsResult_BrowseAll PRE = null; try { foreach (ISubTest preTest in otherSubTests) { if (preTest.Name == this.PRE_BROWSEALL.Name) { PRE = preTest.Details as CdsResult_BrowseAll; break; } } if (PRE == null) { throw new TestException(this._Name + " requires that the \"" + this.PRE_BROWSEALL.Name + "\" test be run as a prerequisite. The results from that test cannot be obtained.", otherSubTests); } } catch (Exception e) { throw new TestException(this._Name + " requires that the \"" + this.PRE_BROWSEALL.Name + "\" test be run before. An error occurred when attempting to obtain the results of a prerequisite.", otherSubTests, e); } _Details.BrowseAllResults = PRE; if (PRE.MostMetadata == null) { throw new TestException(this.PRE_BROWSEALL.Name + " failed to find a media object with the most metadata. " + this._Name + " requires this value.", PRE); } if (PRE.MostMetadata.Properties.Count != PRE.MostMetadata.Properties.PropertyNames.Count) { throw new TestException(this.Name + " has conflicting reports for the number of metadata properties. " + PRE.MostMetadata.Properties.Count + "/" + PRE.MostMetadata.Properties.PropertyNames.Count, PRE.MostMetadata.Properties); } IUPnPMedia MM = PRE.MostMetadata; if (MM == null) { string skippedMsg = "\"" + this.Name + "\" skipped because the tested content hierarchy does not have a media object with at least one resource and has an ID!=\"0\""; arg.TestGroup.AddEvent(LogImportance.Critical, this.Name, skippedMsg); arg.TestGroup.AddResult(skippedMsg); return(UPnPTestStates.Ready); } IMediaContainer MC = PRE.MostMetadata.Parent; if (MC == null) { throw new TestException(this.Name + " has MostMetadata.Parent == null", PRE.MostMetadata); } int numProps = MM.Properties.Count; int numChildren = MC.ChildCount; // we browse for "res" and each possible res@attribute numProps += (2 * MediaResource.GetPossibleAttributes().Count) + 2; _Details.NumberOfProperties = numProps; _Details.ExpectedTotalBrowseRequests = 0; int inc = numProps / 4; if (inc == 0) { inc = 1; } for (int nProps = 0; nProps < numProps; nProps++) { for (int iProp = 0; iProp < numProps; iProp += inc) { _Details.ExpectedTotalBrowseRequests++; } } _Details.ExpectedTotalBrowseRequests *= 2; int maxTime = 90 * _Details.ExpectedTotalBrowseRequests; this._ExpectedTestingTime = maxTime; // browse metadata with various filter settings // browsedirectchildren with various filter settings UPnPTestStates state = this._TestState; CdsBrowseSearchResults test1 = TestFiltersBrowseMetadata(MM, CpContentDirectory.Enum_A_ARG_TYPE_BrowseFlag.BROWSEMETADATA, this, arg, CDS, _Details); if (test1.WorstError > state) { state = test1.WorstError; } CdsBrowseSearchResults test2 = TestFiltersBrowseMetadata(MM, CpContentDirectory.Enum_A_ARG_TYPE_BrowseFlag.BROWSEDIRECTCHILDREN, this, arg, CDS, _Details); if (test2.WorstError > state) { state = test2.WorstError; } // finish up logging this._TestState = state; StringBuilder sb = new StringBuilder(); sb.AppendFormat("\"{0}\" completed", this.Name); if (this._TestState <= UPnPTestStates.Running) { throw new TestException("\"" + this.Name + "\" must have a pass/warn/fail result.", this._TestState); } switch (this._TestState) { case UPnPTestStates.Pass: sb.Append(" successfully."); break; case UPnPTestStates.Warn: sb.Append(" with warnings."); break; case UPnPTestStates.Failed: sb.Append(" with a failed result."); break; } arg._TestGroup.AddResult(sb.ToString()); if (this._TestState <= UPnPTestStates.Warn) { if (_Details.TotalBrowseRequests != _Details.ExpectedTotalBrowseRequests) { throw new TestException("TotalBrowseRequests=" + _Details.TotalBrowseRequests.ToString() + " ExpectedTotal=" + _Details.ExpectedTotalBrowseRequests.ToString(), _Details); } } arg._TestGroup.AddEvent(LogImportance.Remark, this.Name, sb.ToString()); return(this._TestState); }
public override UPnPTestStates Run(ICollection otherSubTests, CdsSubTestArgument arg) { CpContentDirectory CDS = this.GetCDS(arg._Device); _Details = new CdsResult_BrowseFilterRangeSort(); this._TestState = UPnPTestStates.Running; arg._TestGroup.AddEvent(LogImportance.Remark, this.Name, "\"" + this.Name + "\" started."); // get the results from the prerequisite tests CdsResult_BrowseFilter FILTER_RESULTS = null; CdsResult_BrowseRange RANGE_RESULTS = null; CdsResult_BrowseSortCriteria SORT_RESULTS = null; try { foreach (ISubTest preTest in otherSubTests) { if (preTest.Name == this.PRE_FILTER.Name) { FILTER_RESULTS = preTest.Details as CdsResult_BrowseFilter; } else if (preTest.Name == this.PRE_RANGE.Name) { RANGE_RESULTS = preTest.Details as CdsResult_BrowseRange; } else if (preTest.Name == this.PRE_SORT.Name) { SORT_RESULTS = preTest.Details as CdsResult_BrowseSortCriteria; } } if (FILTER_RESULTS == null) { throw new TestException(this._Name + " requires that the \"" + this.PRE_FILTER.Name + "\" test be run as a prerequisite. The results from that test cannot be obtained.", otherSubTests); } if (RANGE_RESULTS == null) { throw new TestException(this._Name + " requires that the \"" + this.PRE_RANGE.Name + "\" test be run as a prerequisite. The results from that test cannot be obtained.", otherSubTests); } if (SORT_RESULTS == null) { throw new TestException(this._Name + " requires that the \"" + this.PRE_SORT.Name + "\" test be run as a prerequisite. The results from that test cannot be obtained.", otherSubTests); } } catch (Exception e) { throw new TestException(this._Name + " requires that the \"" + this.PRE_FILTER.Name + "\" and \"" + this.PRE_RANGE + "\" and \"" + this.PRE_SORT + "\" tests be run before. An error occurred when attempting to obtain the results of those prerequisites.", otherSubTests, e); } UPnPTestStates state = this._TestState; CdsResult_BrowseAll BROWSE_ALL = FILTER_RESULTS.BrowseAllResults; if (BROWSE_ALL.LargestContainer == null) { throw new TestException(new Cds_BrowseAll().Name + " failed to find the container with the most child objects. " + this._Name + " requires this value.", BROWSE_ALL); } if (BROWSE_ALL.MostMetadata == null) { throw new TestException(new Cds_BrowseAll().Name + " failed to find the media object with the most metadata. " + this._Name + " requires this value.", BROWSE_ALL); } if (SORT_RESULTS.SortFields == null) { throw new TestException(new Cds_BrowseAll().Name + " failed to find the sortable fields. " + this._Name + " requires this value.", SORT_RESULTS); } int max = Math.Max(FILTER_RESULTS.Filters.Count, BROWSE_ALL.LargestContainer.ChildCount); max = Math.Max(max, SORT_RESULTS.SortFields.Count); this._Details.ExpectedTotalBrowseRequests = max + 1; this._Details.TotalBrowseRequests = 0; this._ExpectedTestingTime = this._Details.ExpectedTotalBrowseRequests * 900; arg.ActiveTests.UpdateTimeAndProgress(this._Details.TotalBrowseRequests * 900); state = UPnPTestStates.Pass; for (int i = 0; i <= max; i++) { ArrayList filterList = new ArrayList(); for (int j = 0; j < i; j++) { if (j < FILTER_RESULTS.Filters.Count) { filterList.Add(FILTER_RESULTS.Filters[j]); } else { break; } } string filterSettings = Cds_BrowseTest.GetCSVString(filterList); uint range = (uint)i; if (range > BROWSE_ALL.LargestContainer.ChildCount) { range = (uint)BROWSE_ALL.LargestContainer.ChildCount; } ArrayList sortList = new ArrayList(); for (int j = 0; j < i; j++) { if (j < SORT_RESULTS.SortFields.Count) { sortList.Add(SORT_RESULTS.SortFields[j]); } else { break; } } BrowseInput input = new BrowseInput(); input.ObjectID = BROWSE_ALL.LargestContainer.ID; input.BrowseFlag = CpContentDirectory.Enum_A_ARG_TYPE_BrowseFlag.BROWSEDIRECTCHILDREN; input.Filter = filterSettings; input.RequestedCount = range; input.SortCriteria = Cds_BrowseSortCriteria.GetSortCriteriaString(sortList, i); input.StartingIndex = 0; this._ExpectedTestingTime = (max) * 900; arg.ActiveTests.UpdateTimeAndProgress(this._Details.TotalBrowseRequests * 900); CdsBrowseSearchResults br = Cds_BrowseTest.Browse(input, this, arg, CDS, _Details); MediaContainer original = (MediaContainer)BROWSE_ALL.LargestContainer; uint ignored; IList expectedResults; expectedResults = original.BrowseSorted(0, input.RequestedCount, new MediaSorter(true, input.SortCriteria), out ignored); try { if (br.WorstError <= UPnPTestStates.Warn) { if (br.MediaObjects.Count != expectedResults.Count) { throw new TerminateEarly(input.PrintBrowseParams() + " returned DIDL-Lite that declared " + br.MediaObjects.Count + " media objects but test expected " + expectedResults.Count.ToString() + " media objects as found in a prerequisite test."); } bool warnOrder = false; for (int ri = 0; ri < br.MediaObjects.Count; ri++) { IUPnPMedia resultObj = (IUPnPMedia)br.MediaObjects[ri]; IUPnPMedia originalObj = (IUPnPMedia)expectedResults[ri]; if (resultObj.ID != originalObj.ID) { warnOrder = true; } foreach (string propName in resultObj.Properties.PropertyNames) { if (filterList.Contains(propName) == false) { if ( (propName != T[_DC.title]) && (propName != T[_UPNP.Class]) ) { StringBuilder msg = new StringBuilder(); msg.AppendFormat("\"" + this.Name + "\" is terminating early because {0} returned DIDL-Lite with \"{1}\" metadata when it should not have done so.", input.PrintBrowseParams(), propName); throw new TerminateEarly(msg.ToString()); } } } } int expectedCount = i; if ((i == 0) || (i > BROWSE_ALL.LargestContainer.ChildCount)) { expectedCount = BROWSE_ALL.LargestContainer.ChildCount; } if (br.MediaObjects.Count != expectedCount) { StringBuilder msg = new StringBuilder(); msg.AppendFormat("\"{0}\" did a {1} and the DIDL-Lite result only has {2} media objects when {3} media objects were expected.", this.Name, input.PrintBrowseParams(), br.MediaObjects.Count, expectedCount); msg.AppendFormat(".\r\nDIDL-Lite ==> {0}", br.Result); throw new TerminateEarly(msg.ToString()); } if (warnOrder) { /* * ArrayList missingResults = new ArrayList(); * * foreach (IUPnPMedia em in expectedResults) * { * bool found = false; * foreach (IUPnPMedia fm in br.MediaObjects) * { * if (em.ID == fm.ID) * { * found = true; * break; * } * } * * if (found == false) * { * missingResults.Add(em); * } * } * * if (missingResults.Count > 0) * { * state = UPnPTestStates.Failed; * StringBuilder msg = new StringBuilder(); * msg.AppendFormat("\"{0}\" did a {1} and the result is missing media objects.", this.Name, input.PrintBrowseParams()); * msg.Append("\r\nExpected order of IDs: "); * int z = 0; * foreach (IUPnPMedia em in expectedResults) * { * if (z > 0) * { * msg.Append(","); * } * msg.AppendFormat("\"{0}\"", em.ID); * z++; * } * msg.Append("\r\nDIDL-Lite result's order of IDs: "); * z = 0; * foreach (IUPnPMedia em in br.MediaObjects) * { * if (z > 0) * { * msg.Append(","); * } * msg.AppendFormat("\"{0}\"", em.ID); * z++; * } * msg.AppendFormat(".\r\nDIDL-Lite ==> {0}", br.Result); * throw new TerminateEarly(msg.ToString()); * } * else */ { StringBuilder msg = new StringBuilder(); msg.AppendFormat("WARNING: \"{0}\" did a {1} and got items in a different order. Target CDS either has an error in its sorting logic, or sorting logic intentionally deviates from test.", this.Name, input.PrintBrowseParams()); msg.Append("\r\nExpected order of IDs: "); int z = 0; foreach (IUPnPMedia em in expectedResults) { if (z > 0) { msg.Append(","); } msg.AppendFormat("\"{0}\"", em.ID); z++; } msg.Append("\r\nDIDL-Lite result's order of IDs: "); z = 0; foreach (IUPnPMedia em in br.MediaObjects) { if (z > 0) { msg.Append(","); } msg.AppendFormat("\"{0}\"", em.ID); z++; } msg.AppendFormat(".\r\nDIDL-Lite ==> {0}", br.Result); arg._TestGroup.AddEvent(LogImportance.Medium, this.Name, msg.ToString()); state = UPnPTestStates.Warn; } } } else { throw new TerminateEarly("\"" + this.Name + "\" is terminating early because " + input.PrintBrowseParams() + " returned with an error or had problems with the DIDL-Lite."); } } catch (TerminateEarly te) { arg._TestGroup.AddEvent(LogImportance.Critical, this.Name, "\"" + this.Name + "\" terminating early. Reason ==> " + te.Message); state = UPnPTestStates.Failed; break; } } // finish up logging this._TestState = state; StringBuilder sb = new StringBuilder(); sb.AppendFormat("\"{0}\" completed", this.Name); if (this._TestState <= UPnPTestStates.Running) { throw new TestException("\"" + this.Name + "\" must have a pass/warn/fail result.", this._TestState); } switch (this._TestState) { case UPnPTestStates.Pass: sb.Append(" successfully."); break; case UPnPTestStates.Warn: sb.Append(" with warnings."); break; case UPnPTestStates.Failed: sb.Append(" with a failed result."); break; } arg._TestGroup.AddResult(sb.ToString()); if (this._TestState <= UPnPTestStates.Warn) { if (_Details.TotalBrowseRequests != _Details.ExpectedTotalBrowseRequests) { throw new TestException("TotalBrowseRequests=" + _Details.TotalBrowseRequests.ToString() + " ExpectedTotal=" + _Details.ExpectedTotalBrowseRequests.ToString(), _Details); } } arg._TestGroup.AddEvent(LogImportance.Remark, this.Name, this.Name + " finished."); return(this._TestState); }
public static CdsBrowseSearchResults GetContainerMetadataAndValidate(string containerID, CpContentDirectory cds, CdsSubTest test, CdsSubTestArgument arg, CdsResult_BrowseAll details, out IUPnPMedia metadata) { BrowseInput input = new BrowseInput(); input.ObjectID = containerID; input.BrowseFlag = CpContentDirectory.Enum_A_ARG_TYPE_BrowseFlag.BROWSEMETADATA; input.Filter = "*"; input.StartingIndex = 0; input.RequestedCount = 0; input.SortCriteria = ""; metadata = null; test.SetExpectedTestingTime((++details.ExpectedTotalBrowseRequests) * 30); arg.ActiveTests.UpdateTimeAndProgress(details.TotalBrowseRequests * 30); CdsBrowseSearchResults results = Browse(input, test, arg, cds, details); test.SetExpectedTestingTime((details.ExpectedTotalBrowseRequests) * 30); arg.ActiveTests.UpdateTimeAndProgress((details.TotalBrowseRequests) * 30); if (results.InvokeError == null) { if (results.NumberReturned != 1) { //results.SetError(UPnPTestStates.Warn); string msg = "\"" + test.Name + "\": " + input.PrintBrowseParams() + " returned NumberReturned=" + results.NumberReturned + " when it should logically be 1. This output parameter is not really useful for BrowseMetadata so this logic error does not prevent towards certification, but it should be fixed."; //arg._TestGroup.AddEvent(LogImportance.Low, test.Name, msg); results.ResultErrors.Add(new Exception(msg)); } if (results.TotalMatches != 1) { //results.SetError(UPnPTestStates.Warn); string msg = "\"" + test.Name + "\": " + input.PrintBrowseParams() + " returned TotalMatches=" + results.TotalMatches + " when it should logically be 1. This output parameter is not really useful BrowseMetadata so this logic error does not prevent towards certification, but it should be fixed."; //arg._TestGroup.AddEvent(LogImportance.Low, test.Name, msg); results.ResultErrors.Add(new Exception(msg)); } if (results.MediaObjects != null) { if (results.MediaObjects.Count == 1) { metadata = results.MediaObjects[0] as IUPnPMedia; if (metadata == null) { throw new TestException(test.Name + " has a TEST LOGIC ERROR. Browse returned without errors but the container's metadata is not stored in an IUPnPMedia object. The offending type is " + results.MediaObjects[0].GetType().ToString(), results.MediaObjects[0]); } IMediaContainer imc = metadata as IMediaContainer; // // check metadata // if (imc == null) { //results.SetError(UPnPTestStates.Failed); string msg = "\"" + test.Name + "\": " + input.PrintBrowseParams() + " returned a DIDL-Lite media object but it was not declared with a \"container\" element."; //arg._TestGroup.AddEvent(LogImportance.Critical, test.Name, msg); results.ResultErrors.Add(new Exception(msg)); } else { } if (metadata.ID != containerID) { //results.SetError(UPnPTestStates.Failed); string msg = "\"" + test.Name + "\": " + input.PrintBrowseParams() + " returned a DIDL-Lite media object with ID=\"" + metadata.ID + "\" when it should be \"" + containerID + "\" as indicated by the input parameter."; //arg._TestGroup.AddEvent(LogImportance.Critical, test.Name, msg); results.ResultErrors.Add(new Exception(msg)); } if (containerID == "0") { if (metadata.ParentID != "-1") { //results.SetError(UPnPTestStates.Failed); string msg = "\"" + test.Name + "\": " + input.PrintBrowseParams() + " returned a DIDL-Lite media object with parentID=\"" + metadata.ID + "\" when it must be \"-1\" because the container is the root container."; //arg._TestGroup.AddEvent(LogImportance.Critical, test.Name, msg); results.ResultErrors.Add(new Exception(msg)); } // no need to check parentID values for other containers because // they get checked when getting the children for this container. } if (results.WorstError < UPnPTestStates.Failed) { //string msg = "\"" + test.Name + "\": " + input.PrintBrowseParams() + " succeeded."; //arg._TestGroup.AddEvent(LogImportance.Remark, test.Name, msg); } } else { //results.SetError(UPnPTestStates.Failed); //string msg = "\"" + test.Name + "\": " + input.PrintBrowseParams() + " did not yield exactly one CDS-compliant media object in its result. Instantiated a total of " +results.MediaObjects.Count+ " media objects."; //arg._TestGroup.AddEvent(LogImportance.Critical, test.Name, msg); } } else { //throw new TestException(test.Name + " has a TEST LOGIC ERROR. Browse returned without errors but no media objects were instantiated.", null); } } if ((results.InvokeError != null) || (results.ResultErrors.Count > 0)) { StringBuilder msg = new StringBuilder(); results.SetError(UPnPTestStates.Failed); msg.AppendFormat("\"{0}\": {1} did not yield exactly one CDS-compliant media object in its result. Instantiated a total of {2} media objects.", test.Name, input.PrintBrowseParams(), results.MediaObjects.Count); msg.AppendFormat("\r\nAdditional Information:"); if (results.InvokeError != null) { msg.AppendFormat("\r\n{0}", results.InvokeError.Message); } foreach (Exception e in results.ResultErrors) { msg.AppendFormat("\r\n{0}", e.Message); } arg._TestGroup.AddEvent(LogImportance.Critical, test.Name, msg.ToString()); } return(results); }
public static CdsBrowseSearchResults CheckMetadata(IUPnPMedia checkAgainstThis, CpContentDirectory cds, CdsSubTest test, CdsSubTestArgument arg, CdsResult_BrowseAll details) { // // Save a reference to the media object with the most filterable properties int numProperties = 0; if (details.MostMetadata != null) { numProperties = details.MostMetadata.Properties.Count; if (details.MostMetadata.DescNodes.Count > 0) { numProperties++; } } int checkValue = 0; if (checkAgainstThis.ID != "0") { if (checkAgainstThis.Resources.Length > 0) { checkValue = checkAgainstThis.Properties.Count; if (checkAgainstThis.DescNodes.Count > 0) { checkValue++; } } } if (checkValue > numProperties) { details.MostMetadata = checkAgainstThis; } // do a browsemetadata on the media object and determine if the metadata matche. BrowseInput input = new BrowseInput(); input.ObjectID = checkAgainstThis.ID; input.BrowseFlag = CpContentDirectory.Enum_A_ARG_TYPE_BrowseFlag.BROWSEMETADATA; input.Filter = "*"; input.StartingIndex = 0; input.RequestedCount = 0; input.SortCriteria = ""; IUPnPMedia metadata = null; CdsBrowseSearchResults results = Browse(input, test, arg, cds, details); test.SetExpectedTestingTime((details.ExpectedTotalBrowseRequests) * 30); arg.ActiveTests.UpdateTimeAndProgress((details.TotalBrowseRequests) * 30); if (results.WorstError <= UPnPTestStates.Warn) { if (results.NumberReturned != 1) { results.SetError(UPnPTestStates.Warn); string msg = "\"" + test.Name + "\": " + input.PrintBrowseParams() + " returned NumberReturned=" + results.NumberReturned + " when it should logically be 1. This output parameter is not really useful for BrowseMetadata so this logic error does not prevent towards certification, but it should be fixed."; arg._TestGroup.AddEvent(LogImportance.Low, test.Name, msg); } if (results.TotalMatches != 1) { results.SetError(UPnPTestStates.Warn); string msg = "\"" + test.Name + "\": " + input.PrintBrowseParams() + " returned TotalMatches=" + results.TotalMatches + " when it should logically be 1. This output parameter is not really useful BrowseMetadata so this logic error does not prevent towards certification, but it should be fixed."; arg._TestGroup.AddEvent(LogImportance.Low, test.Name, msg); } if (results.MediaObjects != null) { if (results.MediaObjects.Count == 1) { metadata = results.MediaObjects[0] as IUPnPMedia; if (metadata == null) { throw new TestException(test.Name + " has a TEST LOGIC ERROR. Browse returned without errors but the object's metadata is not stored in an IUPnPMedia object. The offending type is " + results.MediaObjects[0].GetType().ToString(), results.MediaObjects[0]); } if (metadata.ID != input.ObjectID) { results.SetError(UPnPTestStates.Failed); string msg = "\"" + test.Name + "\": " + input.PrintBrowseParams() + " returned a DIDL-Lite media object with ID=\"" + metadata.ID + "\" when it should be \"" + input.ObjectID + "\" as indicated by the input parameter."; arg._TestGroup.AddEvent(LogImportance.Critical, test.Name, msg); } if (metadata.ParentID != checkAgainstThis.ParentID) { results.SetError(UPnPTestStates.Failed); string msg = "\"" + test.Name + "\": " + input.PrintBrowseParams() + " returned a DIDL-Lite media object with parentID=\"" + metadata.ParentID + "\" when it should be \"" + checkAgainstThis.ParentID + "\"."; arg._TestGroup.AddEvent(LogImportance.Critical, test.Name, msg); } string original; string received; try { original = checkAgainstThis.ToDidl(); received = metadata.ToDidl(); } catch { results.SetError(UPnPTestStates.Failed); string msg = "\"" + test.Name + "\": " + input.PrintBrowseParams() + " encountered errors with the DIDL-Lite."; arg._TestGroup.AddEvent(LogImportance.Critical, test.Name, msg); return(results); } if (string.Compare(original, received) == 0) { //string msg = "\"" + test.Name + "\": " + input.PrintBrowseParams() + " successfully returned a DIDL-Lite media object that succesfully matches with previously seen metadata."; //arg._TestGroup.AddEvent(LogImportance.Remark, test.Name, msg); } else { System.Xml.XmlDocument doc1 = new XmlDocument(); XmlDocument doc2 = new XmlDocument(); doc1.LoadXml(original); doc2.LoadXml(received); bool isMatch = true; foreach (XmlElement el1 in doc1.GetElementsByTagName("*")) { bool foundElement = false; foreach (XmlElement el2 in doc2.GetElementsByTagName("*")) { if ( (el1.Name != "item") && (el1.Name != "container") && (el1.OuterXml == el2.OuterXml) ) { foundElement = true; break; } else if ( ( (el1.Name == "DIDL-Lite") || (el1.Name == "item") || (el1.Name == "container") ) && (el1.Name == el2.Name) ) { foundElement = true; break; } } if (foundElement == false) { isMatch = false; break; } } if (isMatch == false) { results.SetError(UPnPTestStates.Failed); string msg = "\"" + test.Name + "\": " + input.PrintBrowseParams() + " returned a DIDL-Lite media object that failed to match with previously seen metadata."; arg._TestGroup.AddEvent(LogImportance.Critical, test.Name, msg); arg._TestGroup.AddEvent(LogImportance.Critical, test.Name, test.Name + ": Original=\"" + original + "\" Received=\"" + received + "\""); } } } else { results.SetError(UPnPTestStates.Failed); string msg = "\"" + test.Name + "\": " + input.PrintBrowseParams() + " did not yield exactly one CDS-compliant media object in its result. Instantiated a total of " + results.MediaObjects.Count + " media objects."; arg._TestGroup.AddEvent(LogImportance.Critical, test.Name, msg); } } else { throw new TestException(test.Name + " has a TEST LOGIC ERROR. Browse returned without errors but no media objects were instantiated.", null); } } return(results); }
/// <summary> /// /// </summary> /// <param name="parent"></param> /// <param name="cds"></param> /// <param name="test"></param> /// <param name="arg"></param> /// <param name="details"></param> /// <param name="C"></param> /// <returns></returns> /// <exception cref="TerminateEarly"> /// </exception> public static ArrayList GetContainerChildrenAndValidate(IMediaContainer parent, CpContentDirectory cds, CdsSubTest test, CdsSubTestArgument arg, CdsResult_BrowseAll details, Queue C) { uint totalExpected = uint.MaxValue; uint currentChild = 0; ArrayList children = new ArrayList(); while (currentChild < totalExpected) { BrowseInput input = new BrowseInput(); input.ObjectID = parent.ID; input.BrowseFlag = CpContentDirectory.Enum_A_ARG_TYPE_BrowseFlag.BROWSEDIRECTCHILDREN; input.Filter = "*"; input.StartingIndex = currentChild; input.RequestedCount = 1; input.SortCriteria = ""; string containerID = parent.ID; if (currentChild == 0) { test.SetExpectedTestingTime((++details.ExpectedTotalBrowseRequests) * 30); arg.ActiveTests.UpdateTimeAndProgress(details.TotalBrowseRequests * 30); } CdsBrowseSearchResults results = Browse(input, test, arg, cds, details); test.SetExpectedTestingTime((details.ExpectedTotalBrowseRequests) * 30); arg.ActiveTests.UpdateTimeAndProgress((details.TotalBrowseRequests) * 30); if (results.WorstError >= UPnPTestStates.Failed) { throw new TerminateEarly("\"" + test.Name + "\" is terminating early because " + input.PrintBrowseParams() + " returned with an error or had problems with the DIDL-Lite."); } else { if (results.NumberReturned != 1) { if (currentChild != 0) { results.SetError(UPnPTestStates.Failed); arg._TestGroup.AddEvent(LogImportance.Low, test.Name, "\"" + test.Name + "\": " + input.PrintBrowseParams() + " returned NumberReturned=" + results.NumberReturned + " when it should logically be 1."); } } if (results.TotalMatches != totalExpected) { if (currentChild != 0) { results.SetError(UPnPTestStates.Failed); arg._TestGroup.AddEvent(LogImportance.Critical, test.Name, "\"" + test.Name + "\": " + input.PrintBrowseParams() + " returned TotalMatches=" + results.TotalMatches + " when it should logically be " + totalExpected + " as reported in an earlier Browse request. This portion of the test requires that a MediaServer device not be in a state where its content hierarchy will change."); } else { totalExpected = results.TotalMatches; if (totalExpected > 0) { details.ExpectedTotalBrowseRequests += ((int)results.TotalMatches * 2) - 1; test.SetExpectedTestingTime((details.ExpectedTotalBrowseRequests) * 30); arg.ActiveTests.UpdateTimeAndProgress(details.TotalBrowseRequests * 30); } } } if (results.MediaObjects != null) { if (results.MediaObjects.Count == 1) { IUPnPMedia child = results.MediaObjects[0] as IUPnPMedia; if (child == null) { throw new TestException("\"" + test.Name + "\"" + " has a TEST LOGIC ERROR. Browse returned without errors but the child object's metadata is not stored in an IUPnPMedia object. The offending type is " + results.MediaObjects[0].GetType().ToString(), results.MediaObjects[0]); } // ensure no duplicates in object ID foreach (IUPnPMedia previousChild in details.AllObjects) { if (previousChild.ID == child.ID) { string msg = "\"" + test.Name + "\": " + input.PrintBrowseParams() + " returned an object with ID=\"" + child.ID + "\" which conflicts with a previously seen media object in ParentContainerID=\"" + previousChild.ParentID + "\"."; arg._TestGroup.AddEvent(LogImportance.Critical, test.Name, msg); throw new TerminateEarly(msg); } } // ensure updateID is the same between BrowseDirectChildren and earlier BrowseMetadata. try { uint previousUpdateID = (uint)parent.Tag; if (results.UpdateID != previousUpdateID) { string msg = "\"" + test.Name + "\": " + input.PrintBrowseParams() + " returned an UpdateID=" + results.UpdateID + " whilst an UpdateID=" + previousUpdateID + " was obtained in a previous call for ContainerID=\"" + parent.ID + "\" with BrowseMetadata."; arg._TestGroup.AddEvent(LogImportance.Critical, test.Name, msg); throw new TerminateEarly(msg); } } catch (TerminateEarly te) { throw te; } catch (Exception e) { throw new TestException(test.Name + " has a TEST LOGIC ERROR. Error comparing UpdateID values", parent, e); } // add the child to lists: C, parent's child list, and Allobjects try { parent.AddObject(child, false); } catch (Exception e) { AddObjectError aoe = new AddObjectError(); aoe.Parent = parent; aoe.Child = child; throw new TestException(test.Name + " has a TEST LOGIC ERROR. Browse returned without errors but the child object could not be added to its parent.", aoe, e); } details.AllObjects.Add(child); children.Add(child); if (child.IsContainer) { C.Enqueue(child); details.TotalContainers++; } else { details.TotalItems++; } // // Do a BrowseMetadata and check to see if the XML values are the same. // CdsBrowseSearchResults compareResults = CheckMetadata(child, cds, test, arg, details); if (compareResults.InvokeError != null) { arg._TestGroup.AddEvent(LogImportance.High, test.Name, test.Name + ": Browse(BrowseDirectChildren,StartingIndex=" + currentChild + ",RequestedCount=0) on ContainerID=[" + containerID + "] succeeded with warnings because a BrowseMetadata request was rejected by the CDS."); } else if (compareResults.ResultErrors.Count > 0) { string msg = "\"" + test.Name + "\": " + input.PrintBrowseParams() + " failed because a BrowseMetadata request succeeded but the DIDL-Lite could not be represented in object form. Invalid DIDL-Lite is most likely the cause."; arg._TestGroup.AddEvent(LogImportance.Critical, test.Name, msg); throw new TerminateEarly(msg); } else if (compareResults.WorstError >= UPnPTestStates.Failed) { string msg = "\"" + test.Name + "\": " + input.PrintBrowseParams() + " failed because one or more child object's failed a comparison of results between BrowseDirectChildren and BrowseMetadata or encountered some other critical error in that process."; arg._TestGroup.AddEvent(LogImportance.Critical, test.Name, msg); throw new TerminateEarly(msg); } else { //string msg = "\"" + test.Name + "\": " + input.PrintBrowseParams() + " succeeded."; //arg._TestGroup.AddEvent(LogImportance.Remark, test.Name, msg); } // // Track the metadata properties found so far // as we may use them in Browse SortCriteria // // standard top-level attributes Tags T = Tags.GetInstance(); AddTo(details.PropertyNames, "@" + T[_ATTRIB.id]); AddTo(details.PropertyNames, "@" + T[_ATTRIB.parentID]); AddTo(details.PropertyNames, "@" + T[_ATTRIB.restricted]); if (child.IsContainer) { if (child.IsSearchable) { AddTo(details.PropertyNames, "@" + T[_ATTRIB.searchable]); AddTo(details.PropertyNames, T[_DIDL.Container] + "@" + T[_ATTRIB.searchable]); } AddTo(details.PropertyNames, T[_DIDL.Container] + "@" + T[_ATTRIB.id]); AddTo(details.PropertyNames, T[_DIDL.Container] + "@" + T[_ATTRIB.parentID]); AddTo(details.PropertyNames, T[_DIDL.Container] + "@" + T[_ATTRIB.restricted]); } else if (child.IsItem) { if (child.IsReference) { AddTo(details.PropertyNames, "@" + T[_ATTRIB.refID]); AddTo(details.PropertyNames, T[_DIDL.Item] + "@" + T[_ATTRIB.refID]); } AddTo(details.PropertyNames, T[_DIDL.Item] + "@" + T[_ATTRIB.id]); AddTo(details.PropertyNames, T[_DIDL.Item] + "@" + T[_ATTRIB.parentID]); AddTo(details.PropertyNames, T[_DIDL.Item] + "@" + T[_ATTRIB.restricted]); } // standard metadata IMediaProperties properties = child.MergedProperties; IList propertyNames = properties.PropertyNames; foreach (string propertyName in propertyNames) { if (details.PropertyNames.Contains(propertyName) == false) { details.PropertyNames.Add(propertyName); // add attributes if they are not added IList propertyValues = properties[propertyName]; foreach (ICdsElement val in propertyValues) { ICollection attributes = val.ValidAttributes; foreach (string attribName in attributes) { StringBuilder sbpn = new StringBuilder(); sbpn.AppendFormat("{0}@{1}", propertyName, attribName); string fullAttribName = sbpn.ToString(); AddTo(details.PropertyNames, fullAttribName); } } } // resources IList resources = child.MergedResources; foreach (IMediaResource res in resources) { ICollection attributes = res.ValidAttributes; foreach (string attribName in attributes) { string name1 = "res@" + attribName; string name2 = "@" + attribName; AddTo(details.PropertyNames, name1); AddTo(details.PropertyNames, name2); } } if (resources.Count > 0) { AddTo(details.PropertyNames, T[_DIDL.Res]); } } } else { if (results.TotalMatches > 0) { results.SetError(UPnPTestStates.Failed); string msg = "\"" + test.Name + "\": " + input.PrintBrowseParams() + " did not yield exactly one CDS-compliant media object in its result. Instantiated a total of " + results.MediaObjects.Count + " media objects."; arg._TestGroup.AddEvent(LogImportance.Critical, test.Name, msg); throw new TerminateEarly(msg); } } } else { throw new TestException(test.Name + " has a TEST LOGIC ERROR. Browse returned without errors but no media objects were instantiated.", null); } } currentChild++; } return(children); }
public override UPnPTestStates Run(ICollection otherSubTests, CdsSubTestArgument arg) { // init basic stuff CpContentDirectory CDS = this.GetCDS(arg._Device); _Details = new CdsResult_BrowseAll(); // set up a queue of containers to browse, starting with root container Queue C = new Queue(); _Details.Root = new MediaContainer(); _Details.Root.ID = "0"; _Details.AllObjects.Add(_Details.Root); _Details.TotalContainers = 1; _Details.TotalItems = 0; C.Enqueue(_Details.Root); // if we have containers to browse, do so this._TestState = UPnPTestStates.Running; UPnPTestStates testResult = UPnPTestStates.Ready; arg._TestGroup.AddEvent(LogImportance.Remark, this.Name, "\"" + this.Name + "\" started."); while (C.Count > 0) { IMediaContainer c = (IMediaContainer)C.Dequeue(); this._ExpectedTestingTime = _Details.ExpectedTotalBrowseRequests * 30; arg.ActiveTests.UpdateTimeAndProgress(_Details.TotalBrowseRequests * 30); // // get the container's metadata // IUPnPMedia metadata; CdsBrowseSearchResults results = GetContainerMetadataAndValidate(c.ID, CDS, this, arg, _Details, out metadata); testResult = results.WorstError; if (testResult > UPnPTestStates.Warn) { arg._TestGroup.AddEvent(LogImportance.Critical, this.Name, this.Name + " terminating because container metadata could not be obtained or the metadata was not CDS-compliant."); testResult = UPnPTestStates.Failed; this._TestState = testResult; return(this._TestState); } if (metadata != null) { try { c.UpdateObject(metadata); c.Tag = results.UpdateID; } catch (Exception e) { UpdateObjectError uoe = new UpdateObjectError(); uoe.UpdateThis = c; uoe.Metadata = metadata; throw new TestException("Critical error updating metadata of a container using UpdateObject()", uoe, e); } } else { string reason = "\"" + this.Name + "\" terminating because container metadata could not be cast into object form."; arg._TestGroup.AddEvent(LogImportance.Critical, this.Name, reason); arg._TestGroup.AddResult("\"" + this.Name + "\" test failed. " + reason); testResult = UPnPTestStates.Failed; this._TestState = testResult; return(this._TestState); } // // Now get the container's children // ArrayList children = new ArrayList(); try { children = GetContainerChildrenAndValidate(c, CDS, this, arg, _Details, C); if ((_Details.LargestContainer == null) || (children.Count > _Details.LargestContainer.ChildCount)) { _Details.LargestContainer = c; } } catch (TerminateEarly te) { string reason = "\"" + this.Name + "\" terminating early. Reason => " + te.Message; arg._TestGroup.AddEvent(LogImportance.Critical, this.Name, reason); arg._TestGroup.AddResult("\"" + this.Name + "\" test failed. " + reason); testResult = UPnPTestStates.Failed; this._TestState = testResult; return(this._TestState); } } if (testResult >= UPnPTestStates.Failed) { throw new TestException("Execution should not reach this code if testResult is WARN or worse.", testResult); } if (testResult == UPnPTestStates.Ready) { throw new TestException("We should not return Ready state.", testResult); } StringBuilder sb = new StringBuilder(); sb.Append("\"" + this._Name + "\" test finished"); if (testResult == UPnPTestStates.Warn) { sb.Append(" with warnings"); } sb.AppendFormat(" and found {0}/{1}/{2} TotalObjects/TotalContainers/TotalItems.", _Details.AllObjects.Count, _Details.TotalContainers, _Details.TotalItems); arg.TestGroup.AddResult(sb.ToString()); arg._TestGroup.AddEvent(LogImportance.Remark, this.Name, this.Name + " completed."); this._TestState = testResult; if (this._TestState <= UPnPTestStates.Warn) { if (_Details.TotalBrowseRequests != _Details.ExpectedTotalBrowseRequests) { throw new TestException("TotalBrowseRequests=" + _Details.TotalBrowseRequests.ToString() + " ExpectedTotal=" + _Details.ExpectedTotalBrowseRequests.ToString(), _Details); } } return(this._TestState); }
public static CdsBrowseSearchResults CheckMetadata(IUPnPMedia checkAgainstThis, CpContentDirectory cds, CdsSubTest test, CdsSubTestArgument arg, CdsResult_BrowseAll details) { // // Save a reference to the media object with the most filterable properties int numProperties = 0; if (details.MostMetadata != null) { numProperties = details.MostMetadata.Properties.Count; if (details.MostMetadata.DescNodes.Count > 0) { numProperties ++; } } int checkValue = 0; if (checkAgainstThis.ID != "0") { if (checkAgainstThis.Resources.Length > 0) { checkValue = checkAgainstThis.Properties.Count; if (checkAgainstThis.DescNodes.Count > 0) { checkValue++; } } } if (checkValue > numProperties) { details.MostMetadata = checkAgainstThis; } // do a browsemetadata on the media object and determine if the metadata matche. BrowseInput input = new BrowseInput(); input.ObjectID = checkAgainstThis.ID; input.BrowseFlag = CpContentDirectory.Enum_A_ARG_TYPE_BrowseFlag.BROWSEMETADATA; input.Filter = "*"; input.StartingIndex = 0; input.RequestedCount = 0; input.SortCriteria = ""; IUPnPMedia metadata = null; CdsBrowseSearchResults results = Browse(input, test, arg, cds, details); test.SetExpectedTestingTime ((details.ExpectedTotalBrowseRequests) * 30); arg.ActiveTests.UpdateTimeAndProgress( (details.TotalBrowseRequests) * 30); if (results.WorstError <= UPnPTestStates.Warn) { if (results.NumberReturned != 1) { results.SetError(UPnPTestStates.Warn); string msg = "\"" + test.Name + "\": " + input.PrintBrowseParams() + " returned NumberReturned=" +results.NumberReturned+ " when it should logically be 1. This output parameter is not really useful for BrowseMetadata so this logic error does not prevent towards certification, but it should be fixed."; arg._TestGroup.AddEvent(LogImportance.Low, test.Name, msg); } if (results.TotalMatches != 1) { results.SetError(UPnPTestStates.Warn); string msg = "\"" + test.Name + "\": " + input.PrintBrowseParams() + " returned TotalMatches=" +results.TotalMatches+ " when it should logically be 1. This output parameter is not really useful BrowseMetadata so this logic error does not prevent towards certification, but it should be fixed."; arg._TestGroup.AddEvent(LogImportance.Low, test.Name, msg); } if (results.MediaObjects != null) { if (results.MediaObjects.Count == 1) { metadata = results.MediaObjects[0] as IUPnPMedia; if (metadata == null) { throw new TestException(test.Name + " has a TEST LOGIC ERROR. Browse returned without errors but the object's metadata is not stored in an IUPnPMedia object. The offending type is " + results.MediaObjects[0].GetType().ToString(), results.MediaObjects[0]); } if (metadata.ID != input.ObjectID) { results.SetError(UPnPTestStates.Failed); string msg = "\"" + test.Name + "\": " + input.PrintBrowseParams() + " returned a DIDL-Lite media object with ID=\"" +metadata.ID+ "\" when it should be \"" +input.ObjectID+"\" as indicated by the input parameter."; arg._TestGroup.AddEvent(LogImportance.Critical, test.Name, msg); } if (metadata.ParentID != checkAgainstThis.ParentID) { results.SetError(UPnPTestStates.Failed); string msg = "\"" + test.Name + "\": " + input.PrintBrowseParams() + " returned a DIDL-Lite media object with parentID=\"" +metadata.ParentID+ "\" when it should be \"" +checkAgainstThis.ParentID+ "\"."; arg._TestGroup.AddEvent(LogImportance.Critical, test.Name, msg); } string original; string received; try { original = checkAgainstThis.ToDidl(); received = metadata.ToDidl(); } catch { results.SetError(UPnPTestStates.Failed); string msg = "\"" + test.Name + "\": " + input.PrintBrowseParams() + " encountered errors with the DIDL-Lite."; arg._TestGroup.AddEvent(LogImportance.Critical, test.Name, msg); return results; } if (string.Compare(original, received) == 0) { //string msg = "\"" + test.Name + "\": " + input.PrintBrowseParams() + " successfully returned a DIDL-Lite media object that succesfully matches with previously seen metadata."; //arg._TestGroup.AddEvent(LogImportance.Remark, test.Name, msg); } else { System.Xml.XmlDocument doc1 = new XmlDocument(); XmlDocument doc2 = new XmlDocument(); doc1.LoadXml(original); doc2.LoadXml(received); bool isMatch = true; foreach (XmlElement el1 in doc1.GetElementsByTagName("*")) { bool foundElement = false; foreach (XmlElement el2 in doc2.GetElementsByTagName("*")) { if ( (el1.Name != "item") && (el1.Name != "container") && (el1.OuterXml == el2.OuterXml) ) { foundElement = true; break; } else if ( ( (el1.Name == "DIDL-Lite") || (el1.Name == "item") || (el1.Name == "container") ) && (el1.Name == el2.Name) ) { foundElement = true; break; } } if (foundElement == false) { isMatch = false; break; } } if (isMatch==false) { results.SetError(UPnPTestStates.Failed); string msg = "\"" + test.Name + "\": " + input.PrintBrowseParams() + " returned a DIDL-Lite media object that failed to match with previously seen metadata."; arg._TestGroup.AddEvent(LogImportance.Critical, test.Name, msg); arg._TestGroup.AddEvent(LogImportance.Critical, test.Name, test.Name + ": Original=\""+original+"\" Received=\""+received+"\""); } } } else { results.SetError(UPnPTestStates.Failed); string msg = "\"" + test.Name + "\": " + input.PrintBrowseParams() + " did not yield exactly one CDS-compliant media object in its result. Instantiated a total of " +results.MediaObjects.Count+ " media objects."; arg._TestGroup.AddEvent(LogImportance.Critical, test.Name, msg); } } else { throw new TestException(test.Name + " has a TEST LOGIC ERROR. Browse returned without errors but no media objects were instantiated.", null); } } return results; }
public override UPnPTestStates Run(ICollection otherSubTests, CdsSubTestArgument arg) { // init basic stuff CpContentDirectory CDS = this.GetCDS(arg._Device); _Details = new CdsResult_BrowseAll(); // set up a queue of containers to browse, starting with root container Queue C = new Queue(); _Details.Root = new MediaContainer(); _Details.Root.ID = "0"; _Details.AllObjects.Add(_Details.Root); _Details.TotalContainers = 1; _Details.TotalItems = 0; C.Enqueue(_Details.Root); // if we have containers to browse, do so this._TestState = UPnPTestStates.Running; UPnPTestStates testResult = UPnPTestStates.Ready; arg._TestGroup.AddEvent(LogImportance.Remark, this.Name, "\""+this.Name + "\" started."); while (C.Count > 0) { IMediaContainer c = (IMediaContainer) C.Dequeue(); this._ExpectedTestingTime = _Details.ExpectedTotalBrowseRequests * 30; arg.ActiveTests.UpdateTimeAndProgress( _Details.TotalBrowseRequests * 30); // // get the container's metadata // IUPnPMedia metadata; CdsBrowseSearchResults results = GetContainerMetadataAndValidate(c.ID, CDS, this, arg, _Details, out metadata); testResult = results.WorstError; if (testResult > UPnPTestStates.Warn) { arg._TestGroup.AddEvent(LogImportance.Critical, this.Name, this.Name + " terminating because container metadata could not be obtained or the metadata was not CDS-compliant."); testResult = UPnPTestStates.Failed; this._TestState = testResult; return this._TestState; } if (metadata != null) { try { c.UpdateObject(metadata); c.Tag = results.UpdateID; } catch (Exception e) { UpdateObjectError uoe = new UpdateObjectError(); uoe.UpdateThis = c; uoe.Metadata = metadata; throw new TestException("Critical error updating metadata of a container using UpdateObject()", uoe, e); } } else { string reason = "\"" +this.Name + "\" terminating because container metadata could not be cast into object form."; arg._TestGroup.AddEvent(LogImportance.Critical, this.Name, reason); arg._TestGroup.AddResult("\""+this.Name + "\" test failed. " + reason); testResult = UPnPTestStates.Failed; this._TestState = testResult; return this._TestState; } // // Now get the container's children // ArrayList children = new ArrayList(); try { children = GetContainerChildrenAndValidate(c, CDS, this, arg, _Details, C); if ((_Details.LargestContainer == null) || (children.Count > _Details.LargestContainer.ChildCount)) { _Details.LargestContainer = c; } } catch (TerminateEarly te) { string reason = "\"" +this.Name + "\" terminating early. Reason => " + te.Message; arg._TestGroup.AddEvent(LogImportance.Critical, this.Name, reason); arg._TestGroup.AddResult("\""+this.Name + "\" test failed. " + reason); testResult = UPnPTestStates.Failed; this._TestState = testResult; return this._TestState; } } if (testResult >= UPnPTestStates.Failed) { throw new TestException("Execution should not reach this code if testResult is WARN or worse.", testResult); } if (testResult == UPnPTestStates.Ready) { throw new TestException("We should not return Ready state.", testResult); } StringBuilder sb = new StringBuilder(); sb.Append("\""+this._Name + "\" test finished"); if (testResult == UPnPTestStates.Warn) { sb.Append(" with warnings"); } sb.AppendFormat(" and found {0}/{1}/{2} TotalObjects/TotalContainers/TotalItems.", _Details.AllObjects.Count, _Details.TotalContainers, _Details.TotalItems); arg.TestGroup.AddResult(sb.ToString()); arg._TestGroup.AddEvent(LogImportance.Remark, this.Name, this.Name + " completed."); this._TestState = testResult; if (this._TestState <= UPnPTestStates.Warn) { if (_Details.TotalBrowseRequests != _Details.ExpectedTotalBrowseRequests) { throw new TestException("TotalBrowseRequests="+_Details.TotalBrowseRequests.ToString()+" ExpectedTotal="+_Details.ExpectedTotalBrowseRequests.ToString(), _Details); } } return this._TestState; }
public static CdsBrowseSearchResults GetContainerMetadataAndValidate(string containerID, CpContentDirectory cds, CdsSubTest test, CdsSubTestArgument arg, CdsResult_BrowseAll details, out IUPnPMedia metadata) { BrowseInput input = new BrowseInput(); input.ObjectID = containerID; input.BrowseFlag = CpContentDirectory.Enum_A_ARG_TYPE_BrowseFlag.BROWSEMETADATA; input.Filter = "*"; input.StartingIndex = 0; input.RequestedCount = 0; input.SortCriteria = ""; metadata = null; test.SetExpectedTestingTime ((++details.ExpectedTotalBrowseRequests) * 30); arg.ActiveTests.UpdateTimeAndProgress( details.TotalBrowseRequests * 30); CdsBrowseSearchResults results = Browse(input, test, arg, cds, details); test.SetExpectedTestingTime ((details.ExpectedTotalBrowseRequests) * 30); arg.ActiveTests.UpdateTimeAndProgress( (details.TotalBrowseRequests) * 30); if (results.InvokeError == null) { if (results.NumberReturned != 1) { //results.SetError(UPnPTestStates.Warn); string msg = "\"" + test.Name + "\": " + input.PrintBrowseParams() + " returned NumberReturned=" +results.NumberReturned+ " when it should logically be 1. This output parameter is not really useful for BrowseMetadata so this logic error does not prevent towards certification, but it should be fixed."; //arg._TestGroup.AddEvent(LogImportance.Low, test.Name, msg); results.ResultErrors.Add( new Exception(msg) ); } if (results.TotalMatches != 1) { //results.SetError(UPnPTestStates.Warn); string msg = "\"" + test.Name + "\": " + input.PrintBrowseParams() + " returned TotalMatches=" +results.TotalMatches+ " when it should logically be 1. This output parameter is not really useful BrowseMetadata so this logic error does not prevent towards certification, but it should be fixed."; //arg._TestGroup.AddEvent(LogImportance.Low, test.Name, msg); results.ResultErrors.Add( new Exception(msg) ); } if (results.MediaObjects != null) { if (results.MediaObjects.Count == 1) { metadata = results.MediaObjects[0] as IUPnPMedia; if (metadata == null) { throw new TestException(test.Name + " has a TEST LOGIC ERROR. Browse returned without errors but the container's metadata is not stored in an IUPnPMedia object. The offending type is " + results.MediaObjects[0].GetType().ToString(), results.MediaObjects[0]); } IMediaContainer imc = metadata as IMediaContainer; // // check metadata // if (imc == null) { //results.SetError(UPnPTestStates.Failed); string msg = "\"" + test.Name + "\": " + input.PrintBrowseParams() + " returned a DIDL-Lite media object but it was not declared with a \"container\" element."; //arg._TestGroup.AddEvent(LogImportance.Critical, test.Name, msg); results.ResultErrors.Add( new Exception(msg) ); } else { } if (metadata.ID != containerID) { //results.SetError(UPnPTestStates.Failed); string msg = "\"" + test.Name + "\": " + input.PrintBrowseParams() + " returned a DIDL-Lite media object with ID=\"" +metadata.ID+ "\" when it should be \"" +containerID+"\" as indicated by the input parameter."; //arg._TestGroup.AddEvent(LogImportance.Critical, test.Name, msg); results.ResultErrors.Add( new Exception(msg) ); } if (containerID == "0") { if (metadata.ParentID != "-1") { //results.SetError(UPnPTestStates.Failed); string msg = "\"" + test.Name + "\": " + input.PrintBrowseParams() + " returned a DIDL-Lite media object with parentID=\"" +metadata.ID+ "\" when it must be \"-1\" because the container is the root container."; //arg._TestGroup.AddEvent(LogImportance.Critical, test.Name, msg); results.ResultErrors.Add( new Exception(msg) ); } // no need to check parentID values for other containers because // they get checked when getting the children for this container. } if (results.WorstError < UPnPTestStates.Failed) { //string msg = "\"" + test.Name + "\": " + input.PrintBrowseParams() + " succeeded."; //arg._TestGroup.AddEvent(LogImportance.Remark, test.Name, msg); } } else { //results.SetError(UPnPTestStates.Failed); //string msg = "\"" + test.Name + "\": " + input.PrintBrowseParams() + " did not yield exactly one CDS-compliant media object in its result. Instantiated a total of " +results.MediaObjects.Count+ " media objects."; //arg._TestGroup.AddEvent(LogImportance.Critical, test.Name, msg); } } else { //throw new TestException(test.Name + " has a TEST LOGIC ERROR. Browse returned without errors but no media objects were instantiated.", null); } } if ((results.InvokeError != null) || (results.ResultErrors.Count > 0)) { StringBuilder msg = new StringBuilder(); results.SetError(UPnPTestStates.Failed); msg.AppendFormat("\"{0}\": {1} did not yield exactly one CDS-compliant media object in its result. Instantiated a total of {2} media objects.", test.Name, input.PrintBrowseParams(), results.MediaObjects.Count); msg.AppendFormat("\r\nAdditional Information:"); if (results.InvokeError != null) { msg.AppendFormat("\r\n{0}", results.InvokeError.Message); } foreach (Exception e in results.ResultErrors) { msg.AppendFormat("\r\n{0}", e.Message); } arg._TestGroup.AddEvent(LogImportance.Critical, test.Name, msg.ToString()); } return results; }
/// <summary> /// /// </summary> /// <param name="parent"></param> /// <param name="cds"></param> /// <param name="test"></param> /// <param name="arg"></param> /// <param name="details"></param> /// <param name="C"></param> /// <returns></returns> /// <exception cref="TerminateEarly"> /// </exception> public static ArrayList GetContainerChildrenAndValidate(IMediaContainer parent, CpContentDirectory cds, CdsSubTest test, CdsSubTestArgument arg, CdsResult_BrowseAll details, Queue C) { uint totalExpected = uint.MaxValue; uint currentChild = 0; ArrayList children = new ArrayList(); while (currentChild < totalExpected) { BrowseInput input = new BrowseInput(); input.ObjectID = parent.ID; input.BrowseFlag = CpContentDirectory.Enum_A_ARG_TYPE_BrowseFlag.BROWSEDIRECTCHILDREN; input.Filter = "*"; input.StartingIndex = currentChild; input.RequestedCount = 1; input.SortCriteria = ""; string containerID = parent.ID; if (currentChild == 0) { test.SetExpectedTestingTime ((++details.ExpectedTotalBrowseRequests) * 30); arg.ActiveTests.UpdateTimeAndProgress( details.TotalBrowseRequests * 30); } CdsBrowseSearchResults results = Browse(input, test, arg, cds, details); test.SetExpectedTestingTime ((details.ExpectedTotalBrowseRequests) * 30); arg.ActiveTests.UpdateTimeAndProgress( (details.TotalBrowseRequests) * 30); if (results.WorstError >= UPnPTestStates.Failed) { throw new TerminateEarly("\"" + test.Name + "\" is terminating early because " +input.PrintBrowseParams()+ " returned with an error or had problems with the DIDL-Lite."); } else { if (results.NumberReturned != 1) { if (currentChild != 0) { results.SetError(UPnPTestStates.Failed); arg._TestGroup.AddEvent(LogImportance.Low, test.Name, "\"" + test.Name + "\": " + input.PrintBrowseParams() + " returned NumberReturned=" +results.NumberReturned+ " when it should logically be 1."); } } if (results.TotalMatches != totalExpected) { if (currentChild != 0) { results.SetError(UPnPTestStates.Failed); arg._TestGroup.AddEvent(LogImportance.Critical, test.Name, "\"" + test.Name + "\": " + input.PrintBrowseParams() + " returned TotalMatches=" +results.TotalMatches+ " when it should logically be " +totalExpected+ " as reported in an earlier Browse request. This portion of the test requires that a MediaServer device not be in a state where its content hierarchy will change."); } else { totalExpected = results.TotalMatches; if (totalExpected > 0) { details.ExpectedTotalBrowseRequests += ((int)results.TotalMatches * 2) - 1; test.SetExpectedTestingTime ((details.ExpectedTotalBrowseRequests) * 30); arg.ActiveTests.UpdateTimeAndProgress( details.TotalBrowseRequests * 30); } } } if (results.MediaObjects != null) { if (results.MediaObjects.Count == 1) { IUPnPMedia child = results.MediaObjects[0] as IUPnPMedia; if (child == null) { throw new TestException("\"" + test.Name + "\"" + " has a TEST LOGIC ERROR. Browse returned without errors but the child object's metadata is not stored in an IUPnPMedia object. The offending type is " + results.MediaObjects[0].GetType().ToString(), results.MediaObjects[0]); } // ensure no duplicates in object ID foreach (IUPnPMedia previousChild in details.AllObjects) { if (previousChild.ID == child.ID) { string msg = "\"" + test.Name + "\": " + input.PrintBrowseParams() + " returned an object with ID=\"" +child.ID+ "\" which conflicts with a previously seen media object in ParentContainerID=\"" +previousChild.ParentID+ "\"."; arg._TestGroup.AddEvent(LogImportance.Critical, test.Name, msg); throw new TerminateEarly(msg); } } // ensure updateID is the same between BrowseDirectChildren and earlier BrowseMetadata. try { uint previousUpdateID = (uint) parent.Tag; if (results.UpdateID != previousUpdateID) { string msg = "\"" + test.Name + "\": " + input.PrintBrowseParams() + " returned an UpdateID=" +results.UpdateID+ " whilst an UpdateID=" +previousUpdateID+ " was obtained in a previous call for ContainerID=\"" +parent.ID+ "\" with BrowseMetadata."; arg._TestGroup.AddEvent(LogImportance.Critical, test.Name, msg); throw new TerminateEarly(msg); } } catch (TerminateEarly te) { throw te; } catch (Exception e) { throw new TestException(test.Name + " has a TEST LOGIC ERROR. Error comparing UpdateID values", parent, e); } // add the child to lists: C, parent's child list, and Allobjects try { parent.AddObject(child, false); } catch (Exception e) { AddObjectError aoe = new AddObjectError(); aoe.Parent = parent; aoe.Child = child; throw new TestException(test.Name + " has a TEST LOGIC ERROR. Browse returned without errors but the child object could not be added to its parent.", aoe, e); } details.AllObjects.Add(child); children.Add(child); if (child.IsContainer) { C.Enqueue(child); details.TotalContainers++; } else { details.TotalItems++; } // // Do a BrowseMetadata and check to see if the XML values are the same. // CdsBrowseSearchResults compareResults = CheckMetadata(child, cds, test, arg, details); if (compareResults.InvokeError != null) { arg._TestGroup.AddEvent(LogImportance.High, test.Name, test.Name + ": Browse(BrowseDirectChildren,StartingIndex="+currentChild+",RequestedCount=0) on ContainerID=["+containerID+"] succeeded with warnings because a BrowseMetadata request was rejected by the CDS."); } else if (compareResults.ResultErrors.Count > 0) { string msg = "\"" + test.Name + "\": " + input.PrintBrowseParams() + " failed because a BrowseMetadata request succeeded but the DIDL-Lite could not be represented in object form. Invalid DIDL-Lite is most likely the cause."; arg._TestGroup.AddEvent(LogImportance.Critical, test.Name, msg); throw new TerminateEarly(msg); } else if (compareResults.WorstError >= UPnPTestStates.Failed) { string msg = "\"" + test.Name + "\": " + input.PrintBrowseParams() + " failed because one or more child object's failed a comparison of results between BrowseDirectChildren and BrowseMetadata or encountered some other critical error in that process."; arg._TestGroup.AddEvent(LogImportance.Critical, test.Name, msg); throw new TerminateEarly(msg); } else { //string msg = "\"" + test.Name + "\": " + input.PrintBrowseParams() + " succeeded."; //arg._TestGroup.AddEvent(LogImportance.Remark, test.Name, msg); } // // Track the metadata properties found so far // as we may use them in Browse SortCriteria // // standard top-level attributes Tags T = Tags.GetInstance(); AddTo(details.PropertyNames, "@"+T[_ATTRIB.id]); AddTo(details.PropertyNames, "@"+T[_ATTRIB.parentID]); AddTo(details.PropertyNames, "@"+T[_ATTRIB.restricted]); if (child.IsContainer) { if (child.IsSearchable) { AddTo(details.PropertyNames, "@"+T[_ATTRIB.searchable]); AddTo(details.PropertyNames, T[_DIDL.Container]+"@"+T[_ATTRIB.searchable]); } AddTo(details.PropertyNames, T[_DIDL.Container]+"@"+T[_ATTRIB.id]); AddTo(details.PropertyNames, T[_DIDL.Container]+"@"+T[_ATTRIB.parentID]); AddTo(details.PropertyNames, T[_DIDL.Container]+"@"+T[_ATTRIB.restricted]); } else if (child.IsItem) { if (child.IsReference) { AddTo(details.PropertyNames, "@"+T[_ATTRIB.refID]); AddTo(details.PropertyNames, T[_DIDL.Item]+"@"+T[_ATTRIB.refID]); } AddTo(details.PropertyNames, T[_DIDL.Item]+"@"+T[_ATTRIB.id]); AddTo(details.PropertyNames, T[_DIDL.Item]+"@"+T[_ATTRIB.parentID]); AddTo(details.PropertyNames, T[_DIDL.Item]+"@"+T[_ATTRIB.restricted]); } // standard metadata IMediaProperties properties = child.MergedProperties; IList propertyNames = properties.PropertyNames; foreach (string propertyName in propertyNames) { if (details.PropertyNames.Contains(propertyName) == false) { details.PropertyNames.Add(propertyName); // add attributes if they are not added IList propertyValues = properties[propertyName]; foreach (ICdsElement val in propertyValues) { ICollection attributes = val.ValidAttributes; foreach (string attribName in attributes) { StringBuilder sbpn = new StringBuilder(); sbpn.AppendFormat("{0}@{1}", propertyName, attribName); string fullAttribName = sbpn.ToString(); AddTo(details.PropertyNames, fullAttribName); } } } // resources IList resources = child.MergedResources; foreach (IMediaResource res in resources) { ICollection attributes = res.ValidAttributes; foreach (string attribName in attributes) { string name1 = "res@"+attribName; string name2 = "@"+attribName; AddTo(details.PropertyNames, name1); AddTo(details.PropertyNames, name2); } } if (resources.Count > 0) { AddTo(details.PropertyNames, T[_DIDL.Res]); } } } else { if (results.TotalMatches > 0) { results.SetError(UPnPTestStates.Failed); string msg = "\"" + test.Name + "\": " + input.PrintBrowseParams() + " did not yield exactly one CDS-compliant media object in its result. Instantiated a total of " +results.MediaObjects.Count+ " media objects."; arg._TestGroup.AddEvent(LogImportance.Critical, test.Name, msg); throw new TerminateEarly(msg); } } } else { throw new TestException(test.Name + " has a TEST LOGIC ERROR. Browse returned without errors but no media objects were instantiated.", null); } } currentChild++; } return children; }
public override UPnPTestStates Run(ICollection otherSubTests, CdsSubTestArgument arg) { CpContentDirectory CDS = this.GetCDS(arg._Device); _Details = new CdsResult_BrowseRange(); this._TestState = UPnPTestStates.Running; // get the results from the BrowseAll test CdsResult_BrowseAll PRE = null; try { foreach (ISubTest preTest in otherSubTests) { if (preTest.Name == this.PRE_BROWSEALL.Name) { PRE = preTest.Details as CdsResult_BrowseAll; break; } } if (PRE == null) { throw new TestException(this._Name + " requires that the \"" + this.PRE_BROWSEALL.Name + "\" test be run as a prerequisite. The results from that test cannot be obtained.", otherSubTests); } } catch (Exception e) { throw new TestException(this._Name + " requires that the \"" + this.PRE_BROWSEALL.Name + "\" test be run before. An error occurred when attempting to obtain the results of a prerequisite.", otherSubTests, e); } _Details.BrowseAllResults = PRE; if (PRE.LargestContainer == null) { throw new TestException(this.PRE_BROWSEALL.Name + " failed to find the container with the most child objects. " + this._Name + " requires this value.", PRE); } if (PRE.Root == null) { throw new TestException(this.PRE_BROWSEALL.Name + " failed to find the root container. " + this._Name + " requires this value.", PRE); } //calculate expected test time //int maxC = PRE.LargestContainer.ChildCount + 1; //int rootC = PRE.Root.ChildCount + 1; //_Details.ExpectedTotalBrowseRequests = (maxC * maxC) + (rootC * rootC); _Details.ExpectedTotalBrowseRequests = CalculateExpectedBrowseRequests(PRE.LargestContainer) + CalculateExpectedBrowseRequests(PRE.Root); int maxTime = 300 * _Details.ExpectedTotalBrowseRequests; this._ExpectedTestingTime = maxTime; arg.ActiveTests.UpdateTimeAndProgress(0); // test the root container arg.TestGroup.AddEvent(LogImportance.Remark, this.Name, "\"" + this.Name + "\" started testing root container."); CdsBrowseSearchResults rootResults = TestContainerRanges(PRE.Root, this, arg, CDS, _Details); arg.TestGroup.AddEvent(LogImportance.Remark, this.Name, "\"" + this.Name + "\" finished testing root container."); UPnPTestStates state = this._TestState; if (state < rootResults.WorstError) { state = rootResults.WorstError; } //test largest container arg.TestGroup.AddEvent(LogImportance.Remark, this.Name, "\"" + this.Name + "\" started testing containerID=\"" + PRE.LargestContainer.ID + "\"."); CdsBrowseSearchResults cResults = TestContainerRanges(PRE.LargestContainer, this, arg, CDS, _Details); arg.TestGroup.AddEvent(LogImportance.Remark, this.Name, "\"" + this.Name + "\" finished testing containerID=\"" + PRE.LargestContainer.ID + "\"."); if (state < cResults.WorstError) { state = cResults.WorstError; } // finish up logging this._TestState = state; if (this._TestState >= UPnPTestStates.Warn) { arg._TestGroup.AddEvent(LogImportance.High, this.Name, "\"" + this.Name + "\" expects all Browse requests to succeed. A CDS should not return errors caused by [(StartingIndex + RequestedCount) >= container.ChildCount] because control points cannot assume a particular range. For leniency, the test will pass with warnings for CDS implementations that return an error when (StartingIndex >= container.ChildCount)."); } StringBuilder sb = new StringBuilder(); sb.AppendFormat("\"{0}\" completed", this.Name); if (this._TestState <= UPnPTestStates.Running) { throw new TestException("\"" + this.Name + "\" must have a pass/warn/fail result.", this._TestState); } switch (this._TestState) { case UPnPTestStates.Pass: sb.Append(" successfully."); break; case UPnPTestStates.Warn: sb.Append(" with warnings."); break; case UPnPTestStates.Failed: sb.Append(" with a failed result."); break; } arg._TestGroup.AddResult(sb.ToString()); if (this._TestState <= UPnPTestStates.Warn) { if (_Details.TotalBrowseRequests != _Details.ExpectedTotalBrowseRequests) { throw new TestException("TotalBrowseRequests=" + _Details.TotalBrowseRequests.ToString() + " ExpectedTotal=" + _Details.ExpectedTotalBrowseRequests.ToString(), _Details); } } return(this._TestState); }
public override void CalculateExpectedTestingTime(ICollection otherSubTests, ISubTestArgument arg) { // get the results from the prerequisite tests CdsResult_BrowseAll BROWSE_RESULTS = null; CdsResult_GetSortCapabilities SORTCAPS = null; foreach (ISubTest preTest in otherSubTests) { if (preTest.Name == this.PRE_BROWSEALL.Name) { BROWSE_RESULTS = preTest.Details as CdsResult_BrowseAll; } else if (preTest.Name == this.PRE_SORTCAPS.Name) { SORTCAPS = preTest.Details as CdsResult_GetSortCapabilities; } } if (BROWSE_RESULTS == null) { return; } if (SORTCAPS == null) { return; } if (BROWSE_RESULTS.LargestContainer == null) { return; } MediaContainer MC = BROWSE_RESULTS.LargestContainer as MediaContainer; if (MC == null) { return; } ArrayList sortFields = new ArrayList(); if (SORTCAPS.SortCapabilities == "") { } else if (SORTCAPS.SortCapabilities == "*") { sortFields = (ArrayList)BROWSE_RESULTS.PropertyNames.Clone(); } else { sortFields.AddRange(GetSortFields(SORTCAPS.SortCapabilities)); } int fieldCount = sortFields.Count; IList childList = BROWSE_RESULTS.LargestContainer.CompleteList; uint inc = (uint)(childList.Count / 3); int firstInc = (fieldCount / 3); if (firstInc == 0) { firstInc = 1; } int totalBrowses = 0; for (int numFields = 0; numFields < fieldCount; numFields++) { for (int first = 0; first < fieldCount; first += firstInc) { //for (uint i=0; i < childList.Count; i+=inc) { totalBrowses++; } } } //add one for an unsorted browse totalBrowses++; //multiply by 2 because we have 2 rounds to check for consistency in ordered results totalBrowses *= 2; //calculate expected time this._ExpectedTestingTime = totalBrowses * 900; }
public override UPnPTestStates Run(ICollection otherSubTests, CdsSubTestArgument arg) { CpContentDirectory CDS = this.GetCDS(arg._Device); _Details = new CdsResult_BrowseSortCriteria(); this._TestState = UPnPTestStates.Running; arg._TestGroup.AddEvent(LogImportance.Remark, this.Name, "\"" + this.Name + "\" started."); // get the results from the prerequisite tests CdsResult_BrowseAll BROWSE_RESULTS = null; CdsResult_GetSortCapabilities SORTCAPS = null; try { foreach (ISubTest preTest in otherSubTests) { if (preTest.Name == this.PRE_BROWSEALL.Name) { BROWSE_RESULTS = preTest.Details as CdsResult_BrowseAll; } else if (preTest.Name == this.PRE_SORTCAPS.Name) { SORTCAPS = preTest.Details as CdsResult_GetSortCapabilities; } } if (BROWSE_RESULTS == null) { throw new TestException(this._Name + " requires that the \"" + this.PRE_BROWSEALL.Name + "\" test be run as a prerequisite. The results from that test cannot be obtained.", otherSubTests); } if (SORTCAPS == null) { throw new TestException(this._Name + " requires that the \"" + this.PRE_SORTCAPS.Name + "\" test be run as a prerequisite. The results from that test cannot be obtained.", otherSubTests); } } catch (Exception e) { throw new TestException(this._Name + " requires that the \"" + this.PRE_BROWSEALL.Name + "\" and \"" + this.PRE_SORTCAPS + "\" tests be run before. An error occurred when attempting to obtain the results of those prerequisites.", otherSubTests, e); } _Details.BrowseAllResults = BROWSE_RESULTS; _Details.SortCapsResults = SORTCAPS; UPnPTestStates state = this._TestState; if (BROWSE_RESULTS.LargestContainer == null) { throw new TestException(this.PRE_BROWSEALL.Name + " failed to find the container with the most child objects. " + this._Name + " requires this value.", BROWSE_RESULTS); } MediaContainer MC = BROWSE_RESULTS.LargestContainer as MediaContainer; if (MC == null) { throw new TestException(this.PRE_BROWSEALL.Name + " has the largest container as type \"" + BROWSE_RESULTS.LargestContainer.GetType().ToString() + "\" when \"" + this.Name + "\" requires \"" + typeof(MediaContainer).ToString() + "\".", BROWSE_RESULTS); } ArrayList sortFields = new ArrayList(); if (SORTCAPS.SortCapabilities == "") { //arg.TestGroup.AddEvent(LogImportance.Remark, this.Name, "\""+this.Name+"\" has no sorting capabilities."); } else if (SORTCAPS.SortCapabilities == "*") { sortFields = (ArrayList)BROWSE_RESULTS.PropertyNames.Clone(); } else { sortFields.AddRange(GetSortFields(SORTCAPS.SortCapabilities)); } _Details.ExpectedTotalBrowseRequests = 0; _Details.SortFields = sortFields; int fieldCount = sortFields.Count; IList childList = BROWSE_RESULTS.LargestContainer.CompleteList; _Details.ExpectedTotalBrowseRequests = 0; //fieldCount * fieldCount * fieldCount; uint inc = (uint)(childList.Count / 3); int firstInc = (fieldCount / 3); if (firstInc == 0) { firstInc = 1; } for (int numFields = 0; numFields < fieldCount; numFields++) { for (int first = 0; first < fieldCount; first += firstInc) { //for (uint i=0; i < childList.Count; i+=inc) { _Details.ExpectedTotalBrowseRequests++; } } } // add 1 for an unsorted browse _Details.ExpectedTotalBrowseRequests++; //multiply by 2 because we have 2 rounds to check for consistency in ordered results _Details.ExpectedTotalBrowseRequests *= 2; //calculate time this._ExpectedTestingTime = _Details.ExpectedTotalBrowseRequests * 900; arg.ActiveTests.UpdateTimeAndProgress(0); if (state <= UPnPTestStates.Running) { state = UPnPTestStates.Pass; try { ArrayList round2 = new ArrayList(); //perform the standard unsorted browse BrowseInput input = new BrowseInput(); input.BrowseFlag = CpContentDirectory.Enum_A_ARG_TYPE_BrowseFlag.BROWSEDIRECTCHILDREN; input.StartingIndex = 0; input.ObjectID = MC.ID; input.RequestedCount = 0; input.Filter = "*"; input.SortCriteria = ""; CdsBrowseSearchResults br = Browse(input, this, arg, CDS, _Details); Round2 r2 = new Round2(); r2.Input = (BrowseInput)input.Clone(); r2.PreviousResult = br; round2.Add(r2); for (int numFields = 0; numFields < fieldCount; numFields++) { for (int first = 0; first < fieldCount; first += firstInc) { ArrayList sortSettings = GetSortSettings(sortFields, first, first); input.SortCriteria = GetSortCriteriaString(sortSettings, numFields + first); arg.ActiveTests.UpdateTimeAndProgress(_Details.TotalBrowseRequests * 900); uint ignored; //use this sorter for to determine the expected order of the media objects IMediaSorter sorter = new MediaSorter(true, input.SortCriteria); IList expectedSorted = MC.BrowseSorted(0, 0, sorter, out ignored); br = Browse(input, this, arg, CDS, _Details); arg.ActiveTests.UpdateTimeAndProgress(_Details.TotalBrowseRequests * 900); this.CompareResultsAgainstExpected(br, expectedSorted, ref state, arg, input, false); r2 = new Round2(); r2.Input = (BrowseInput)input.Clone(); r2.PreviousResult = br; round2.Add(r2); } } //do round2 - check for consistency in results foreach (Round2 r in round2) { br = Browse(r.Input, this, arg, CDS, _Details); arg.ActiveTests.UpdateTimeAndProgress(_Details.TotalBrowseRequests * 900); this.CompareResultsAgainstExpected(br, r.PreviousResult.MediaObjects, ref state, arg, r.Input, true); } } catch (TerminateEarly te) { string reason = "\"" + this.Name + "\" terminating early. Reason => " + te.Message; arg._TestGroup.AddEvent(LogImportance.Critical, this.Name, reason); state = UPnPTestStates.Failed; } } // finish up logging this._TestState = state; StringBuilder sb = new StringBuilder(); sb.AppendFormat("\"{0}\" completed", this.Name); if (this._TestState <= UPnPTestStates.Running) { throw new TestException("\"" + this.Name + "\" must have a pass/warn/fail result.", this._TestState); } switch (this._TestState) { case UPnPTestStates.Pass: sb.Append(" successfully."); break; case UPnPTestStates.Warn: sb.Append(" with warnings."); break; case UPnPTestStates.Failed: sb.Append(" with a failed result."); break; } arg._TestGroup.AddResult(sb.ToString()); if (this._TestState <= UPnPTestStates.Warn) { if (_Details.TotalBrowseRequests != _Details.ExpectedTotalBrowseRequests) { throw new TestException("TotalBrowseRequests=" + _Details.TotalBrowseRequests.ToString() + " ExpectedTotal=" + _Details.ExpectedTotalBrowseRequests.ToString(), _Details); } } arg._TestGroup.AddEvent(LogImportance.Remark, this.Name, sb.ToString()); return(this._TestState); }