/// <summary> /// Cleans up resources when tests are finished. /// </summary> public void Dispose() { AFFixture.Dispose(); PIFixture.Dispose(); Client.Dispose(); ServicePointManager.ServerCertificateValidationCallback = null; }
public void CheckAFServiceTest() { var service = "AFService"; using (var fixture = new AFFixture()) { Utils.CheckServiceRunning(fixture.PISystem.ConnectionInfo.Host, service, Output); } }
internal static void GetWebApiClient(ref WebClient client, ref AFElement configElement, ref bool disableWrites, ref bool anonymousAuthentication) { PISystem pisys = AFFixture.GetPISystemFromConfig(); if (client == null) { client = new WebClient { UseDefaultCredentials = true } } ; client.Headers.Add("X-Requested-With", "XMLHttpRequest"); ServicePointManager.ServerCertificateValidationCallback = null; if (Settings.SkipCertificateValidation) #pragma warning disable CA5359 // Do Not Disable Certificate Validation { ServicePointManager.ServerCertificateValidationCallback = (a, b, c, d) => true; } #pragma warning restore CA5359 // Do Not Disable Certificate Validation var configurationElement = Settings.PIWebAPI.Split('.')[0]; if (!string.IsNullOrEmpty(Settings.PIWebAPIConfigurationInstance)) { configurationElement = Settings.PIWebAPIConfigurationInstance; } var path = $"\\\\{Settings.AFServer}\\Configuration\\OSIsoft\\PI Web API\\{configurationElement}\\System Configuration"; var results = AFElement.FindElementsByPath(new string[] { path }, pisys); configElement = results.FirstOrDefault(); if (!Equals(configElement, null)) { disableWrites = (bool)configElement.Attributes["DisableWrites"].GetValue().Value; var methods = (string[])configElement.Attributes["AuthenticationMethods"].GetValue().Value; if (methods.Length > 0) { if (string.Equals(methods[0], "Basic", StringComparison.OrdinalIgnoreCase)) { client.UseDefaultCredentials = false; var credentials = Convert.ToBase64String(Encoding.ASCII.GetBytes(Settings.PIWebAPIUser + ":" + Settings.PIWebAPIPassword)); client.Headers[HttpRequestHeader.Authorization] = "Basic " + credentials; } else if (string.Equals(methods[0], "Anonymous", StringComparison.OrdinalIgnoreCase)) { anonymousAuthentication = true; } } else { throw new InvalidOperationException("PI Web API Authentication Methods are not specified in the Configuration database."); } } } }
public void CheckProductVersion() { Output.WriteLine($"AFSDK Version: {AF.AFGlobalSettings.SDKVersion}"); using (var affixture = new AFFixture()) { Assert.True(affixture.PISystem != null, $"AF Server [{affixture.PISystem}] could not be found."); Output.WriteLine($"AF Server Version: {affixture.PISystem.ServerVersion}"); } using (var pifixture = new PIFixture()) { Assert.True(pifixture.PIServer != null, $"PI Server [{pifixture.PIServer}] could not be found."); Output.WriteLine($"PI Data Archive Version: {pifixture.PIServer.ServerVersion}"); } }
public void CheckRtqpEngineServiceTest() { var service = "PISqlDas.Rtqp"; using (var fixture = new AFFixture()) { if (Settings.PISqlClientTests) { Utils.CheckServiceRunning(fixture.PISystem.ConnectionInfo.Host, service, Output); } else { Output.WriteLine($"'PISQLClientTests' setting value is set to 'false' or not set at all. Check if [{service}] (required by PI SQL Client) is running was skipped."); } } }
internal void InitializeWebService(AFFixture afFixture, ITestOutputHelper output) { if (AFFixture != null) { return; } // Initialize a web service notification contact template AFFixture = afFixture; Service = new TestWebService(); SoapWebServiceHost = new BasicWebServiceHost(Service, typeof(IWebService)); try { SoapWebServiceHost.Start(ServiceName, ServiceUri); } catch (AddressAccessDeniedException) { SoapWebServiceHost = null; Service = null; output.WriteLine($"Warning: The Web Service endpoint [{ServiceUri}] could not be opened."); output.WriteLine("There are two ways how to fix the problem:"); output.WriteLine("1. Use netsh add urlacl to add the current user for the service prefix http://+:9001/notificationtest"); output.WriteLine("2. Run tests as administrator."); return; } var webServiceSoap = new AFNotificationContactTemplate(afFixture.PISystem, $"{TestPrefix}_{TestInfix}_WebServiceSoap*") { DeliveryChannelPlugIn = afFixture.PISystem.DeliveryChannelPlugIns[WebServicePlugInName], ConfigString = $"Style=SOAP;WebServiceName={ServiceName};WebServiceMethod={nameof(IWebService.Test)};WebServiceUrl={ServiceUri}", }; _soapWebServiceId = webServiceSoap.ID; _notificationContactTemplateIds.Add(webServiceSoap.ID); AFFixture.PISystem.CheckIn(); output.WriteLine($"Created web service notification contact template [{webServiceSoap.Name}]."); }
internal void InitializeWebService(AFFixture afFixture, ITestOutputHelper output) { if (AFFixture != null) { return; } // Initialize a web service notification contact template AFFixture = afFixture; Service = new TestWebService(); SoapWebServiceHost = new BasicWebServiceHost(Service, typeof(IWebService)) { UseExactMatchForLocalhost = false, }; try { SoapWebServiceHost.Start(ServiceName, ServiceUri); } catch (AddressAccessDeniedException ex) { throw new Exception( $"Endpoint [{ServiceUri}] could not be opened. There are 3 possible solutions: " + "1) If notifications service and the tests are run on the same machine, set UseExactMatchForLocalhost=true; " + "2) Use netsh add urlacl to add the current user for the service prefix http://+:9001/notificationtest; " + "3) Run tests as administrator.", ex); } var webServiceSoap = new AFNotificationContactTemplate(afFixture.PISystem, $"{TestPrefix}_{TestInfix}_WebServiceSoap*") { DeliveryChannelPlugIn = afFixture.PISystem.DeliveryChannelPlugIns[WebServicePlugInName], ConfigString = $"Style=SOAP;WebServiceName={ServiceName};WebServiceMethod={nameof(IWebService.Test)};WebServiceUrl={ServiceUri}", }; _soapWebServiceId = webServiceSoap.ID; _notificationContactTemplatIds.Add(webServiceSoap.ID); AFFixture.PISystem.CheckIn(); output.WriteLine($"Created web service notification contact template [{webServiceSoap.Name}]."); }
/// <summary> /// Gets the machine name of service. /// </summary> /// <param name="settingName">Name of the setting for the service in app config settings file.</param> /// <returns>Name of machine running that service.</returns> public static string GetMachineName(string settingName) { switch (settingName) { case "PIDataArchive": using (var pifixture = new PIFixture()) return(pifixture.PIServer.ConnectionInfo.Host); case "AFServer": using (var affixture = new AFFixture()) return(affixture.PISystem.ConnectionInfo.Host); case "PIAnalysisService": return(Settings.PIAnalysisService); case "PINotificationsService": return(Settings.PINotificationsService); case "PIWebAPI": return(Settings.PIWebAPI); case "PIWebAPICrawler": return(Settings.PIWebAPICrawler); case "PIVisionServer": if (string.IsNullOrWhiteSpace(Settings.PIVisionServer)) { return(string.Empty); } return(Settings.PIVisionServer.Split('/')[2].Split(':')[0]); case "PIManualLogger": return(Settings.PIManualLogger); default: return($"Invalid setting name '{settingName}' specified."); } }
public void CheckMinimumPISQLClientSecurity() { using (var fixture = new AFFixture()) { if (Settings.PISqlClientTests) { var fullElementPath = @"OSIsoft\RTQP Engine\Custom Objects"; var element = fixture.PISystem.Databases.ConfigurationDatabase?.Elements[fullElementPath]; if (!(element is null)) { Assert.True(element.Security.CanRead && element.Security.CanWrite, $"The user does not have Read/Write permissions on the {fullElementPath} element in the Configuration database."); Assert.True(element.Security.CanReadData && element.Security.CanWriteData, $"The user does not have Read/Write Data permissions on the {fullElementPath} element in the Configuration database."); Assert.True(element.Security.CanDelete, $"The user does not have Delete permissions on the {fullElementPath} element in the Configuration database."); } else { Assert.True(false, $"Could not find element {fullElementPath} in the configuration directory."); } }
public void CheckMinimumAFSecurity() { using (var fixture = new AFFixture()) { var system = fixture.PISystem; Assert.True(system.UOMDatabase.Security.CanWrite, "The current user must have Write permission on the UOMDatabase."); foreach (var securityItem in Enum.GetValues(typeof(AFSecurityItem))) { var security = system.GetSecurity((AFSecurityItem)securityItem); switch (securityItem) { case AFSecurityItem.AnalysisTemplate: case AFSecurityItem.Category: case AFSecurityItem.Database: case AFSecurityItem.EnumerationSet: case AFSecurityItem.NotificationContactTemplate: case AFSecurityItem.NotificationRuleTemplate: case AFSecurityItem.Table: Assert.True(security.CanRead && security.CanWrite && security.CanDelete, "The current user must have Read, Write, and Delete permission to the following System collections:\n" + "\tAnalysis Templates\n" + "\tCategories\n" + "\tDatabases\n" + "\tEnumeration Sets\n" + "\tNotification Contact Templates\n" + "\tNotification Rule Templates\n" + "\tTables"); break; case AFSecurityItem.EventFrame: case AFSecurityItem.Transfer: Assert.True(security.CanReadData && security.CanWriteData && security.CanDelete && security.CanAnnotate, "The current user must have Read Data, Write Data, Annotate, and Delete permission to the following System collections:\n" + "\tEvent Frames\n" + "\tTransfers"); break; case AFSecurityItem.Analysis: Assert.True(security.CanRead && security.CanWrite && security.CanDelete && security.CanExecute, "The current user must have Read, Write, Execute, and Delete permission to the Analyses System collection."); break; case AFSecurityItem.Element: case AFSecurityItem.ElementTemplate: Assert.True(security.CanRead && security.CanReadData && security.CanWrite && security.CanWriteData && security.CanDelete, "The current user must have Read, Write, Read Data, Write Data, and Delete permission to the following System collections:\n" + "\tElements\n" + "\tElement Templates"); var identities = system.CurrentUserIdentities; var instancedSystem = fixture.GetInstancedSystem(); if ((AFSecurityItem)securityItem == AFSecurityItem.Element) { Assert.True(security.CanAnnotate, "The current user must have Annotate permission to the Elements System collection."); } else { var elementTemplateToken = instancedSystem.GetSecurity(AFSecurityItem.ElementTemplate).Token; elementTemplateToken.SecurityItem = AFSecurityItem.EventFrame; var tokens = new List <AFSecurityRightsToken>() { elementTemplateToken }; var dict = AFSecurity.CheckSecurity(instancedSystem, identities, tokens); Assert.True(dict[elementTemplateToken.ObjectId].CanAnnotate(), "The current user must have Annotate permission to the Element Templates System collection."); } instancedSystem.Disconnect(); break; case AFSecurityItem.NotificationRule: Assert.True(security.CanRead && security.CanWrite && security.CanDelete && security.CanSubscribe, "The current user must have Read, Write, Subscribe, and Delete permission to the Notification Rules System collection."); break; } } } }
/// <summary> /// Skips a test based on the passed condition. /// </summary> public GenericFactAttribute(TestCondition feature, bool error) : base(AFTests.KeySetting, AFTests.KeySettingTypeCode) { string afVersion = AFGlobalSettings.SDKVersion; string piHomeDir = string.Empty; // Return if the Skip property has been changed in the base constructor if (!string.IsNullOrEmpty(Skip)) { return; } string piHome64 = null; string piHome32 = null; DataLinkUtils.GetPIHOME(ref piHome64, 1); DataLinkUtils.GetPIHOME(ref piHome32, 0); switch (feature) { case TestCondition.AFCLIENTCURRENTPATCH: Version sdkVersion = new Version(afVersion); if (sdkVersion < _afClientCurrentVersion) { Skip = $@"Warning! You do not have the latest update: {_afClientCurrentVersionString}! Please consider upgrading! You are currently on {sdkVersion}"; } break; case TestCondition.AFPATCH2107: sdkVersion = new Version(afVersion); if (sdkVersion < new Version("2.10.7")) { Skip = $@"Warning! You do not have the critical patch: PI AF 2018 SP3 Patch 1 (2.10.7)! Please consider upgrading to avoid data loss! You are currently on {sdkVersion}"; } break; case TestCondition.AFSERVERCURRENTPATCH: Version serverVersion = new Version(AFFixture.GetPISystemFromConfig().ServerVersion); if (serverVersion < _afServerCurrentVersion) { Skip = $@"Warning! You do not have the latest update: {_afServerCurrentVersionString}! Please consider upgrading! You are currently on {serverVersion}"; } break; case TestCondition.ANALYSISCURRENTPATCH: Version analysisVer = new Version(AFFixture.GetPISystemFromConfig().AnalysisRulePlugIns["PerformanceEquation"].Version); if (analysisVer < _analysisCurrentVersion) { Skip = $@"Warning! You do not have the latest update: {_analysisCurrentVersionString}! Please consider upgrading! You are currently on {analysisVer}"; } break; case TestCondition.DATALINKCURRENTPATCH: string afDataDLLPath = @"Excel\OSIsoft.PIDataLink.AFData.dll"; DataLinkUtils.GetPIHOME(ref piHomeDir); Version dataLinkVersion = new Version(FileVersionInfo.GetVersionInfo(Path.Combine(piHomeDir, afDataDLLPath)).FileVersion); if (dataLinkVersion < _dataLinkCurrentVersion) { Skip = $@"Warning! You do not have the latest update: {_dataLinkCurrentVersionString}! Please consider upgrading! You are currently on {dataLinkVersion}"; } break; case TestCondition.NOTIFICATIONSCURRENTPATCH: PISystem system = AFFixture.GetPISystemFromConfig(); var configstore = new PINotificationsConfigurationStore(system); PINotificationsWCFClientManager wcfClient = new PINotificationsWCFClientManager(configstore); var serviceStatus = wcfClient.GetServiceStatus(); wcfClient.Dispose(); Version notificationsVersion = new Version(serviceStatus.Version); if (notificationsVersion < _notificationsCurrentVersion) { Skip = $@"Warning! You do not have the latest update: {_notificationsCurrentVersionString}! Please consider upgrading! You are currently on {notificationsVersion}"; } break; case TestCondition.PIDACURRENTPATCH: PIServer serv = new PIServers()[Settings.PIDataArchive]; serv.Connect(); Version pidaVersion = new Version(serv.ServerVersion); if (pidaVersion < _dataArchiveCurrentVersion) { Skip = $@"Warning! You do not have the latest update: {_dataArchiveCurrentVersionString}! Please consider upgrading! You are currently on {pidaVersion}"; } break; case TestCondition.PISQLOLEDBCURRENTPATCH: string sqlpath64OLEDB = Path.Combine(piHome64, @"SQL\SQL Client\OLEDB\PISQLOLEDB64.dll"); string sqlpath32OLEDB = Path.Combine(piHome32, @"SQL\SQL Client\OLEDB\PISQLOLEDB.dll"); if (File.Exists(sqlpath64OLEDB)) { Version piSqlVersion = new Version(FileVersionInfo.GetVersionInfo(sqlpath64OLEDB).FileVersion); if (piSqlVersion < _sqlClientOLEDBCurrentVersion) { Skip = $@"Warning! You do not have the latest update: {_sqlClientOLEDBCurrentVersionString}! Please consider upgrading! You are currently on {piSqlVersion}"; } } if (File.Exists(sqlpath32OLEDB)) { Version piSqlVersion = new Version(FileVersionInfo.GetVersionInfo(sqlpath32OLEDB).FileVersion); if (piSqlVersion < _sqlClientOLEDBCurrentVersion) { Skip = $@"Warning! You do not have the latest update: {_sqlClientOLEDBCurrentVersionString}! Please consider upgrading! You are currently on {piSqlVersion}"; } } break; case TestCondition.PISQLODBCCURRENTPATCH: string sqlpath64ODBC = Path.Combine(piHome64, @"SQL\SQL Client\ODBC\PISQLODBCB64.dll"); string sqlpath32ODBC = Path.Combine(piHome32, @"SQL\SQL Client\ODBC\PISQLODBC.dll"); if (File.Exists(sqlpath64ODBC)) { Version piSqlVersion = new Version(FileVersionInfo.GetVersionInfo(sqlpath64ODBC).FileVersion); if (piSqlVersion < _sqlClientODBCCurrentVersion) { Skip = $@"Warning! You do not have the latest update: {_sqlClientODBCCurrentVersionString}! Please consider upgrading! You are currently on {piSqlVersion}"; } } if (File.Exists(sqlpath32ODBC)) { Version piSqlVersion = new Version(FileVersionInfo.GetVersionInfo(sqlpath32ODBC).FileVersion); if (piSqlVersion < _sqlClientODBCCurrentVersion) { Skip = $@"Warning! You do not have the latest update: {_sqlClientODBCCurrentVersionString}! Please consider upgrading! You are currently on {piSqlVersion}"; } } break; case TestCondition.PIWEBAPICURRENTPATCH: var url = $"https://{Settings.PIWebAPI}:{443}/piwebapi/system"; WebClient client = new WebClient { UseDefaultCredentials = true }; AFElement elem = new AFElement(); bool disableWrites = false; bool anonymousAuth = false; JObject data = new JObject(); try { PIWebAPIFixture.GetWebApiClient(ref client, ref elem, ref disableWrites, ref anonymousAuth); data = JObject.Parse(client.DownloadString(url)); } catch { throw new InvalidOperationException($"Could not retrieve PI Web API version from server {Settings.PIWebAPI}!"); } finally { client.Dispose(); } var productVersion = (string)data["ProductVersion"]; Version piWebAPIVersion = new Version(productVersion); if (piWebAPIVersion < _webAPICurrentVersion) { Skip = $@"Warning! You do not have the latest update: {_webAPICurrentVersionString}! Please consider upgrading! You are currently on {piWebAPIVersion}"; } break; case TestCondition.RTQPCURRENTPATCH: string connectionString = $"Provider=PISQLClient.1;Data Source={Settings.AFDatabase};Location={Settings.AFServer};Integrated Security=SSPI;OLE DB Services=-2"; using (var connection = new OleDbConnection(connectionString)) { connection.Open(); try { using (var command = new OleDbCommand("SELECT Version FROM System.Diagnostics.Version WHERE Item='Query Processor'", connection)) { string tempVersion = (string)command.ExecuteScalar(); Version rtqpVersion = new Version(tempVersion); if (rtqpVersion < _rtqpCurrentVersion) { Skip = $@"Warning! You do not have the latest update: {_rtqpCurrentVersionString}! Please consider upgrading! You are currently on {rtqpVersion}"; } } } catch (Exception) { Skip = $@"Warning! You do not have the latest update: {_rtqpCurrentVersionString}! Please consider upgrading!"; } } break; case TestCondition.PIVISIONCURRENTPATCH: string path = Settings.PIVisionServer; if (path.EndsWith("/#/", StringComparison.OrdinalIgnoreCase)) { path = path.Substring(0, path.Length - 3); } string visionUrl = $"{path}/Utility/permissions/read"; var visionProductVersion = string.Empty; using (var visionClient = new WebClient { UseDefaultCredentials = true }) { visionClient.Headers.Add("X-Requested-With", "XMLHttpRequest"); visionProductVersion = visionClient.DownloadString(visionUrl); } Version piVisionVersion = new Version(); if (!string.IsNullOrWhiteSpace(visionProductVersion)) { piVisionVersion = new Version(visionProductVersion); } else { throw new InvalidOperationException($"Could not retrieve PI Vision version from server {Settings.PIVisionServer}!"); } if (piVisionVersion < _visionCurrentVersion) { Skip = $@"Warning! You do not have the latest update: {_visionCurrentVersionString}! Please consider upgrading! You are currently on {piVisionVersion}"; } break; } if (error && !string.IsNullOrEmpty(Skip)) { throw new Exception(Skip); } }
public void CreatePointSendEventsAndVerify() { string pointName = $"CreatePointSendEventsAndVerify{AFTime.Now}"; IDictionary<string, object> attributes = new Dictionary<string, object>() { { PICommonPointAttributes.Tag, pointName }, { PICommonPointAttributes.PointType, PIPointType.Int32 }, { PICommonPointAttributes.Compressing, 0 }, }; // Create a PI Point Output.WriteLine($"Create PI Point [{pointName}]."); PIPoint point = Fixture.PIServer.CreatePIPoint(pointName, attributes); // Assert that the PI Point creation was successful Assert.True(PIPoint.FindPIPoint(Fixture.PIServer, pointName) != null, $"Could not find PI Point [{pointName}] on Data Archive [{Fixture.PIServer.Name}]."); try { // Prepare the events to be written var eventsToWrite = new AFValues(); var start = AFTime.Now.ToPIPrecision(); int eventsCount = 10; var randomData = new byte[eventsCount]; using (var random = RandomNumberGenerator.Create()) { random.GetBytes(randomData); } for (int i = 0; i < eventsCount; i++) { var evnt = new AFValue(Convert.ToInt32(randomData[i]), start + TimeSpan.FromSeconds(i)); eventsToWrite.Add(evnt); } // Send the events to be written Output.WriteLine($"Write events to PI Point [{pointName}]."); point.UpdateValues(eventsToWrite, AFUpdateOption.InsertNoCompression); // Read the events to verify that it was written successfully var eventsRead = new AFValues(); Output.WriteLine($"Read events from PI Point [{pointName}]."); AssertEventually.Equal( eventsToWrite.Count, () => point.RecordedValuesByCount(start, eventsCount, true, AFBoundaryType.Inside, null, false).Count, TimeSpan.FromSeconds(2), TimeSpan.FromSeconds(0.2)); eventsRead = point.RecordedValuesByCount(start, eventsCount, true, AFBoundaryType.Inside, null, false); for (int j = 0; j < eventsCount; j++) { Assert.True(eventsToWrite[j].Value.Equals(eventsRead[j].Value), $"Expected the value of the written event {AFFixture.DisplayAFValue(eventsToWrite[j])} " + $"and the read event {AFFixture.DisplayAFValue(eventsRead[j])} to be equal."); } } finally { // Delete the PI Point to cleanup Fixture.DeletePIPoints(pointName, Output); } }
public void UpdateEventValuesTest() { string pointName = $"UpdateEventValuesTest{AFTime.Now}"; IDictionary<string, object> attributes = new Dictionary<string, object>() { { PICommonPointAttributes.Tag, pointName }, { PICommonPointAttributes.PointType, PIPointType.Int32 }, { PICommonPointAttributes.Compressing, 0 }, }; // Create a PI Point Output.WriteLine($"Create PI Point [{pointName}]."); PIPoint point = Fixture.PIServer.CreatePIPoint(pointName, attributes); // Assert that the PI Point creation was successful Assert.True(PIPoint.FindPIPoint(Fixture.PIServer, pointName) != null, $"Could not find PI Point [{pointName}] on Data Archive [{Fixture.PIServer.Name}]."); try { // Prepare the events to be written var eventsToWrite = new AFValues(); var start = AFTime.Now.ToPIPrecision(); int eventsCount = 10; var randomData = new byte[eventsCount]; var valuesToWrite = new List<int>(); var timeStamps = new List<AFTime>(); using (var random = RandomNumberGenerator.Create()) { random.GetBytes(randomData); for (int i = 0; i < eventsCount; i++) { int value = Convert.ToInt32(randomData[i]); var timestamp = start + TimeSpan.FromMinutes(i); var evnt = new AFValue(value, timestamp); eventsToWrite.Add(evnt); valuesToWrite.Add(value); timeStamps.Add(timestamp); } } // Send the events to be written Output.WriteLine($"Write {eventsCount} events to PI Point [{pointName}]."); point.UpdateValues(eventsToWrite, AFUpdateOption.InsertNoCompression); Thread.Sleep(TimeSpan.FromSeconds(1)); // Read the events to verify that it was written successfully var eventsRead = new AFValues(); Output.WriteLine($"Read events from point [{pointName}]."); AssertEventually.True(() => { eventsRead = point.RecordedValuesByCount(start, eventsCount, true, AFBoundaryType.Inside, null, false); if (eventsToWrite.Count != eventsRead.Count) { Output.WriteLine($"The read event count {eventsRead.Count} does not match the written event count {eventsToWrite.Count}."); return false; } for (int j = 0; j < eventsCount; j++) { if (!eventsToWrite[j].Value.Equals(eventsRead[j].Value)) { Output.WriteLine($"Written event value {AFFixture.DisplayAFValue(eventsToWrite[j])} " + $"did not match read event value {AFFixture.DisplayAFValue(eventsRead[j])}."); return false; } } return true; }, TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(5), $"The events read back do not match the events written on the PI Data Archive [{Fixture.PIServer.Name}]."); // Update/edit the values and send again var updatedNewValues = new List<int>(); var eventsUpdated = new AFValues(); randomData = new byte[eventsCount]; using (var random = RandomNumberGenerator.Create()) { random.GetBytes(randomData); for (int i = 0; i < eventsCount; i++) { // Ensure that the updated values are different than the written values. int value = Convert.ToInt32(randomData[i]) + 256; var evnt = new AFValue(value, timeStamps[i]); eventsUpdated.Add(evnt); updatedNewValues.Add(value); } } // Send the updated events to be written Output.WriteLine($"Write updated events to PI Point [{pointName}]."); point.UpdateValues(eventsUpdated, AFUpdateOption.Replace); // Read the events to verify that it was updated successfully eventsRead = new AFValues(); Output.WriteLine($"Read events from PI Point [{pointName}]."); AssertEventually.True(() => { eventsRead = point.RecordedValuesByCount(start, eventsCount, true, AFBoundaryType.Inside, null, false); if (eventsUpdated.Count != eventsRead.Count) { Output.WriteLine($"The read event count {eventsRead.Count} does not match the updated event count {eventsUpdated.Count}."); return false; } for (int j = 0; j < eventsCount; j++) { if (!eventsUpdated[j].Value.Equals(eventsRead[j].Value)) { Output.WriteLine($"Updated event value {AFFixture.DisplayAFValue(eventsUpdated[j])} " + $"did not match read event value {AFFixture.DisplayAFValue(eventsRead[j])}."); return false; } if (eventsToWrite[j].Value.Equals(eventsRead[j].Value)) { Output.WriteLine($"Written event value {AFFixture.DisplayAFValue(eventsToWrite[j])} " + $"did match read event value {AFFixture.DisplayAFValue(eventsRead[j])}. The values should not be equal."); return false; } } return true; }, $"The events read back do not match the events written or updated on the PI Data Archive [{Fixture.PIServer.Name}]."); } finally { // Delete the PI Point to cleanup Fixture.DeletePIPoints(pointName, Output); } }
public void DeleteValuesTest() { string pointName = $"DeleteValuesTest{AFTime.Now}"; IDictionary<string, object> attributes = new Dictionary<string, object>() { { PICommonPointAttributes.Tag, pointName }, { PICommonPointAttributes.PointType, PIPointType.Int32 }, { PICommonPointAttributes.Compressing, 0 }, }; // Create a PI Point Output.WriteLine($"Create PI Point [{pointName}]."); PIPoint point = Fixture.PIServer.CreatePIPoint(pointName, attributes); // Assert that the PI Point creation was successful Assert.True(PIPoint.FindPIPoint(Fixture.PIServer, pointName) != null, $"Could not find PI Point [{pointName}] on Data Archive [{Fixture.PIServer.Name}]."); try { // Prepare the events to be written var eventsToWrite = new AFValues(); var start = AFTime.Now.ToPIPrecision(); int eventsCount = 10; var randomData = new byte[eventsCount]; using (var random = RandomNumberGenerator.Create()) { random.GetBytes(randomData); for (int i = 0; i < eventsCount; i++) { var evnt = new AFValue(Convert.ToInt32(randomData[i]), start + TimeSpan.FromSeconds(i)); eventsToWrite.Add(evnt); } } // Send the events to be written Output.WriteLine($"Write events to PI Point [{pointName}]."); point.UpdateValues(eventsToWrite, AFUpdateOption.InsertNoCompression); // Read the events to verify that the events write was successful var eventsRead = new AFValues(); Output.WriteLine($"Read events from PI Point [{pointName}]."); AssertEventually.True(() => { eventsRead = point.RecordedValuesByCount(start, eventsCount, true, AFBoundaryType.Inside, null, false); if (eventsToWrite.Count != eventsRead.Count) { Output.WriteLine($"The read event count {eventsRead.Count} does not match the written event count {eventsToWrite.Count}."); return false; } else { for (int j = 0; j < eventsCount; j++) { if (!eventsToWrite[j].Value.Equals(eventsRead[j].Value)) { Output.WriteLine($"Written event value {AFFixture.DisplayAFValue(eventsToWrite[j])} " + $"did not match read event value {AFFixture.DisplayAFValue(eventsRead[j])}."); return false; } } } return true; }, $"The events read back do not match the events written to PI Data Archive [{Fixture.PIServer.Name}]."); // Delete the events Output.WriteLine($"Delete events from PI Point [{pointName}]."); eventsRead.Clear(); point.UpdateValues(eventsToWrite, AFUpdateOption.Remove); AssertEventually.True(() => { eventsRead = point.RecordedValuesByCount(start, eventsCount, true, AFBoundaryType.Inside, null, false); return eventsRead.Count == 0; }, $"The return event count should be 0 after deleting the events, but it was actually {eventsRead.Count}."); } finally { // Delete the PI Point to cleanup Fixture.DeletePIPoints(pointName, Output); } }