diff --git a/.pubnub.yml b/.pubnub.yml index ea628202c..3aaeaca95 100644 --- a/.pubnub.yml +++ b/.pubnub.yml @@ -1,15 +1,22 @@ name: c-sharp -version: "7.0.0" +version: "7.1.0" schema: 1 scm: github.com/pubnub/c-sharp changelog: + - date: 2024-12-04 + version: v7.1.0 + changes: + - type: feature + text: "Added support for CustomMessageType in publish, signal, files features." + - type: feature + text: "Added support for Type field in membership APIs." - date: 2024-10-30 version: v7.0.0 changes: - type: feature text: "Added support for `Channel`, `ChannelGroup`, `Subscription` and `SubscriptionSet`, `ChannelMetadata`, `UserMetadata` entities for Subscribe related operation." - type: feature - text: "BREAKING CHANGES: Added new event listeners support." + text: "BREAKING CHANGES: Default Reconnection policy is set to Exponential." - type: feature text: "BREAKING CHANGES: All apis calls will be made through `HttpClient` by default." - type: feature @@ -806,7 +813,7 @@ features: - QUERY-PARAM supported-platforms: - - version: Pubnub 'C#' 7.0.0 + version: Pubnub 'C#' 7.1.0 platforms: - Windows 10 and up - Windows Server 2008 and up @@ -817,7 +824,7 @@ supported-platforms: - .Net Framework 4.6.1+ - .Net Framework 6.0 - - version: PubnubPCL 'C#' 7.0.0 + version: PubnubPCL 'C#' 7.1.0 platforms: - Xamarin.Android - Xamarin.iOS @@ -837,7 +844,7 @@ supported-platforms: - .Net Core - .Net 6.0 - - version: PubnubUWP 'C#' 7.0.0 + version: PubnubUWP 'C#' 7.1.0 platforms: - Windows Phone 10 - Universal Windows Apps @@ -861,7 +868,7 @@ sdks: distribution-type: source distribution-repository: GitHub package-name: Pubnub - location: https://github.com/pubnub/c-sharp/releases/tag/v7.0.0.0 + location: https://github.com/pubnub/c-sharp/releases/tag/v7.1.0.0 requires: - name: ".Net" @@ -1144,7 +1151,7 @@ sdks: distribution-type: source distribution-repository: GitHub package-name: PubNubPCL - location: https://github.com/pubnub/c-sharp/releases/tag/v7.0.0.0 + location: https://github.com/pubnub/c-sharp/releases/tag/v7.1.0.0 requires: - name: ".Net Core" @@ -1503,7 +1510,7 @@ sdks: distribution-type: source distribution-repository: GitHub package-name: PubnubUWP - location: https://github.com/pubnub/c-sharp/releases/tag/v7.0.0.0 + location: https://github.com/pubnub/c-sharp/releases/tag/v7.1.0.0 requires: - name: "Universal Windows Platform Development" diff --git a/CHANGELOG b/CHANGELOG index b679a9ef5..e03bbb5b8 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,8 @@ +v7.1.0 - December 04 2024 +----------------------------- +- Added: added support for CustomMessageType in publish, signal, files features. +- Added: added support for Type field in membership APIs. + v7.0.0 - October 30 2024 ----------------------------- - Added: added support for `Channel`, `ChannelGroup`, `Subscription` and `SubscriptionSet`, `ChannelMetadata`, `UserMetadata` entities for Subscribe related operation. diff --git a/src/Api/PubnubApi/Builder/StatusBuilder.cs b/src/Api/PubnubApi/Builder/StatusBuilder.cs index 196ff5b64..bf4be1e13 100644 --- a/src/Api/PubnubApi/Builder/StatusBuilder.cs +++ b/src/Api/PubnubApi/Builder/StatusBuilder.cs @@ -154,7 +154,7 @@ public PNStatus CreateStatusResponse(PNOperationType type, PNStatusCategory c status.Category = PNStatusCategory.PNAccessDeniedCategory; } - + status.Uuid = config.UserId; status.Origin = config.Origin; status.TlsEnabled = config.Secure; diff --git a/src/Api/PubnubApi/Builder/UrlParameterConverter.cs b/src/Api/PubnubApi/Builder/UrlParameterConverter.cs index 6b8dc1562..e006be989 100644 --- a/src/Api/PubnubApi/Builder/UrlParameterConverter.cs +++ b/src/Api/PubnubApi/Builder/UrlParameterConverter.cs @@ -28,6 +28,14 @@ public static string MapEnumValueToEndpoint(string enumValue) { endpointParameterName = "uuid.custom"; } + else if (enumValue.ToLowerInvariant() == "status") + { + endpointParameterName = "status"; + } + else if (enumValue.ToLowerInvariant() == "type") + { + endpointParameterName = "type"; + } return endpointParameterName; } diff --git a/src/Api/PubnubApi/EndPoint/Files/DeleteFileOperation.cs b/src/Api/PubnubApi/EndPoint/Files/DeleteFileOperation.cs index e0e59d88d..121270439 100644 --- a/src/Api/PubnubApi/EndPoint/Files/DeleteFileOperation.cs +++ b/src/Api/PubnubApi/EndPoint/Files/DeleteFileOperation.cs @@ -93,6 +93,7 @@ private void ProcessDeleteFileRequest(Dictionary externalQueryPa PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ContinueWith(t => { var transportResponse = t.Result; if (transportResponse.Error == null) { + requestState.GotJsonResponse = true; var responseString = Encoding.UTF8.GetString(transportResponse.Content); if (!string.IsNullOrEmpty(responseString)) { List result = ProcessJsonResponse(requestState, responseString); @@ -140,6 +141,7 @@ private async Task> ProcessDeleteFileRequest(Dictio var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNDeleteFileOperation); var transportResponse = await PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ConfigureAwait(false); if (transportResponse.Error == null) { + requestState.GotJsonResponse = true; var responseString = Encoding.UTF8.GetString(transportResponse.Content); PNStatus errorStatus = GetStatusIfError(requestState, responseString); if (errorStatus == null) { diff --git a/src/Api/PubnubApi/EndPoint/Files/PublishFileMessage.cs b/src/Api/PubnubApi/EndPoint/Files/PublishFileMessage.cs index 5f7c5083d..e8ac69b68 100644 --- a/src/Api/PubnubApi/EndPoint/Files/PublishFileMessage.cs +++ b/src/Api/PubnubApi/EndPoint/Files/PublishFileMessage.cs @@ -25,6 +25,7 @@ public class PublishFileMessageOperation : PubnubCoreBase private object publishMessageContent; private bool storeInHistory = true; private Dictionary userMetadata; + private string customMessageType; private int ttl = -1; public PublishFileMessageOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, tokenManager, instance) @@ -76,6 +77,11 @@ public PublishFileMessageOperation FileName(string name) this.currentFileName = name; return this; } + public PublishFileMessageOperation CustomMessageType(string customMessageType) + { + this.customMessageType = customMessageType; + return this; + } public PublishFileMessageOperation QueryParam(Dictionary customQueryParam) { @@ -250,6 +256,10 @@ private RequestParameter CreateRequestParameter() if (!storeInHistory) { requestQueryStringParams.Add("store", "0"); } + + if (!string.IsNullOrEmpty(customMessageType)) { + requestQueryStringParams.Add("custom_message_type", customMessageType); + } if (queryParam != null && queryParam.Count > 0) { foreach (KeyValuePair kvp in queryParam) { diff --git a/src/Api/PubnubApi/EndPoint/Files/SendFileOperation.cs b/src/Api/PubnubApi/EndPoint/Files/SendFileOperation.cs index 78c22c900..60a3b2f5c 100644 --- a/src/Api/PubnubApi/EndPoint/Files/SendFileOperation.cs +++ b/src/Api/PubnubApi/EndPoint/Files/SendFileOperation.cs @@ -29,6 +29,7 @@ public class SendFileOperation : PubnubCoreBase private bool storeInHistory = true; private Dictionary userMetadata; private int ttl = -1; + private string customMessageType; public SendFileOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, tokenManager, instance) { @@ -67,6 +68,12 @@ public SendFileOperation Ttl(int ttl) this.ttl = ttl; return this; } + + public SendFileOperation CustomMessageType(string customMessageType) + { + this.customMessageType = customMessageType; + return this; + } public SendFileOperation File(string fileNameWithFullPath) { @@ -180,11 +187,12 @@ private void ProcessFileUpload(PNCallback callback) int publishFileRetryLimit = config.FileMessagePublishRetryLimit; int currentFileRetryCount = 0; bool publishFailed; + PNStatus publishFileMessageStatus; do { currentFileRetryCount += 1; PNResult publishFileMessageResponse = PublishFileMessage(publishPayload, queryParam).Result; PNPublishFileMessageResult publishFileMessage = publishFileMessageResponse.Result; - PNStatus publishFileMessageStatus = publishFileMessageResponse.Status; + publishFileMessageStatus = publishFileMessageResponse.Status; if (publishFileMessageStatus != null && !publishFileMessageStatus.Error && publishFileMessage != null) { publishFailed = false; PNFileUploadResult result = new PNFileUploadResult(); @@ -202,11 +210,11 @@ private void ProcessFileUpload(PNCallback callback) LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} PublishFileMessage Failed. currentFileRetryCount={1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), currentFileRetryCount), config.LogVerbosity); } } - while (publishFailed && currentFileRetryCount <= publishFileRetryLimit); + while (publishFailed && currentFileRetryCount <= publishFileRetryLimit && !(publishFileMessageStatus?.StatusCode != 400 || publishFileMessageStatus.StatusCode != 403)); } else { - int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); - PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); - PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNFileUploadOperation, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse?.Error?.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse?.Error?.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNFileUploadOperation, category, requestState, statusCode, new PNException(transportResponse?.Error?.Message, transportResponse?.Error)); requestState.PubnubCallback.OnResponse(default, status); } } @@ -229,11 +237,13 @@ private async Task> ProcessFileUpload() return returnValue; } LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} GenerateFileUploadUrl executed.", DateTime.Now.ToString(CultureInfo.InvariantCulture)), config.LogVerbosity); - RequestState requestState = new RequestState(); - requestState.ResponseType = PNOperationType.PNFileUploadOperation; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - requestState.UsePostMethod = true; + RequestState requestState = new RequestState + { + ResponseType = PNOperationType.PNFileUploadOperation, + Reconnect = false, + EndPointOperation = this, + UsePostMethod = true + }; byte[] sendFileByteArray = sendFileBytes ?? GetByteArrayFromFilePath(sendFileFullPath); string dataBoundary = string.Format(CultureInfo.InvariantCulture, "----------{0:N}", Guid.NewGuid()); string contentType = "multipart/form-data; boundary=" + dataBoundary; @@ -303,11 +313,12 @@ private async Task> ProcessFileUpload() int publishFileRetryLimit = config.FileMessagePublishRetryLimit; int currentFileRetryCount = 0; bool publishFailed; + PNStatus publishFileMessageStatus; do { currentFileRetryCount += 1; PNResult publishFileMessageResponse = await PublishFileMessage(publishPayload, queryParam).ConfigureAwait(false); PNPublishFileMessageResult publishFileMessage = publishFileMessageResponse.Result; - PNStatus publishFileMessageStatus = publishFileMessageResponse.Status; + publishFileMessageStatus = publishFileMessageResponse.Status; if (publishFileMessageStatus != null && !publishFileMessageStatus.Error && publishFileMessage != null) { publishFailed = false; PNFileUploadResult result = new PNFileUploadResult @@ -326,7 +337,7 @@ private async Task> ProcessFileUpload() await Task.Delay(1000); } } - while (publishFailed && currentFileRetryCount <= publishFileRetryLimit); + while (publishFailed && currentFileRetryCount <= publishFileRetryLimit && !(publishFileMessageStatus?.StatusCode != 400 || publishFileMessageStatus.StatusCode != 403)); } return returnValue; @@ -403,7 +414,7 @@ private async Task> PublishFileMessage(obje ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); PNPublishFileMessageResult publishResult = responseBuilder.JsonToObject(result, true); StatusBuilder statusBuilder = new StatusBuilder(config, jsonLibrary); - if (publishResult != null) { + if (publishResult != null && transportResponse.StatusCode == Constants.HttpRequestSuccessStatusCode) { returnValue.Result = publishResult; PNStatus status = statusBuilder.CreateStatusResponse(requestState.ResponseType, PNStatusCategory.PNAcknowledgmentCategory, requestState, transportResponse.StatusCode, null); returnValue.Status = status; @@ -564,6 +575,10 @@ private RequestParameter CreatePublishFileMessageRequestParameter() if (storeInHistory && ttl >= 0) { requestQueryStringParams.Add("ttl", ttl.ToString(CultureInfo.InvariantCulture)); } + + if (!string.IsNullOrEmpty(customMessageType)) { + requestQueryStringParams.Add("custom_message_type", customMessageType); + } if (!storeInHistory) { requestQueryStringParams.Add("store", "0"); @@ -587,8 +602,8 @@ private RequestParameter CreatePublishFileMessageRequestParameter() private string PrepareContent(object originalMessage) { string message = jsonLibrary.SerializeToJsonString(originalMessage); - if (config.CryptoModule != null || config.CipherKey.Length > 0) { - config.CryptoModule ??= new CryptoModule(new LegacyCryptor(config.CipherKey, config.UseRandomInitializationVector, pubnubLog), null); + if (config.CryptoModule != null || config.CipherKey.Length > 0 || currentFileCipherKey != null) { + config.CryptoModule ??= new CryptoModule(new LegacyCryptor(currentFileCipherKey ?? config.CipherKey, config.UseRandomInitializationVector, pubnubLog), null); string encryptMessage = config.CryptoModule.Encrypt(message); message = jsonLibrary.SerializeToJsonString(encryptMessage); } diff --git a/src/Api/PubnubApi/EndPoint/Objects/SetMembershipsOperation.cs b/src/Api/PubnubApi/EndPoint/Objects/SetMembershipsOperation.cs index 7d90fc67e..a47a02c56 100644 --- a/src/Api/PubnubApi/EndPoint/Objects/SetMembershipsOperation.cs +++ b/src/Api/PubnubApi/EndPoint/Objects/SetMembershipsOperation.cs @@ -204,13 +204,20 @@ private RequestParameter CreateRequestParameter() Dictionary messageEnvelope = new Dictionary(); if (addMembership != null) { List> setMembershipFormatList = new List>(); - for (int index = 0; index < addMembership.Count; index++) { + foreach (var membership in addMembership) + { Dictionary currentMembershipFormat = new Dictionary { - { "channel", new Dictionary { { "id", addMembership[index].Channel } } } + { "channel", new Dictionary { { "id", membership.Channel } } } }; - if (addMembership[index].Custom != null) { - currentMembershipFormat.Add("custom", addMembership[index].Custom); + if (membership.Custom != null) { + currentMembershipFormat.Add("custom", membership.Custom); + } + if (membership.Status != null) { + currentMembershipFormat.Add("status", membership.Status); + } + if (membership.Type != null) { + currentMembershipFormat.Add("type", membership.Type); } setMembershipFormatList.Add(currentMembershipFormat); } diff --git a/src/Api/PubnubApi/EndPoint/PubSub/PublishOperation.cs b/src/Api/PubnubApi/EndPoint/PubSub/PublishOperation.cs index 48a14aa6a..4569490db 100644 --- a/src/Api/PubnubApi/EndPoint/PubSub/PublishOperation.cs +++ b/src/Api/PubnubApi/EndPoint/PubSub/PublishOperation.cs @@ -23,6 +23,7 @@ public class PublishOperation : PubnubCoreBase private bool httpPost; private Dictionary userMetadata; private int ttl = -1; + private string customMessageType; private PNCallback savedCallback; private bool syncRequest; private Dictionary queryParam; @@ -75,6 +76,12 @@ public PublishOperation Ttl(int ttl) this.ttl = ttl; return this; } + + public PublishOperation CustomMessageType(string customMessageType) + { + this.customMessageType = customMessageType; + return this; + } public PublishOperation QueryParam(Dictionary customQueryParam) { @@ -157,12 +164,14 @@ internal void Publish(string channel, object message, bool storeInHistory, int t callback.OnResponse(null, status); return; } - RequestState requestState = new RequestState(); - requestState.Channels = new[] { channel }; - requestState.ResponseType = PNOperationType.PNPublishOperation; - requestState.PubnubCallback = callback; - requestState.Reconnect = false; - requestState.EndPointOperation = this; + RequestState requestState = new RequestState + { + Channels = [channel], + ResponseType = PNOperationType.PNPublishOperation, + PubnubCallback = callback, + Reconnect = false, + EndPointOperation = this + }; var requestParameters = CreateRequestParameter(); var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameters, operationType: PNOperationType.PNPublishOperation); @@ -220,27 +229,30 @@ internal async Task> Publish(string channel, object me returnValue.Status = errStatus; return returnValue; } - RequestState requestState = new RequestState(); - Tuple JsonAndStatusTuple; - requestState.Channels = new[] { channel }; - requestState.ResponseType = PNOperationType.PNPublishOperation; - requestState.Reconnect = false; - requestState.EndPointOperation = this; + RequestState requestState = new RequestState + { + Channels = [channel], + ResponseType = PNOperationType.PNPublishOperation, + Reconnect = false, + EndPointOperation = this + }; var requestParameter = CreateRequestParameter(); var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNPublishOperation); var transportResponse = await PubnubInstance.transportMiddleware.Send(transportRequest).ConfigureAwait(false); if (transportResponse.Error == null) { string responseString = Encoding.UTF8.GetString(transportResponse.Content); - PNStatus errorStatus = GetStatusIfError(requestState, responseString); - if (errorStatus == null) { + PNStatus errorStatus = GetStatusIfError(requestState, responseString); + Tuple jsonAndStatusTuple; + if (errorStatus == null && transportResponse.StatusCode == Constants.HttpRequestSuccessStatusCode) { requestState.GotJsonResponse = true; PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(requestState.ResponseType, PNStatusCategory.PNAcknowledgmentCategory, requestState, Constants.HttpRequestSuccessStatusCode, null); - JsonAndStatusTuple = new Tuple(responseString, status); + jsonAndStatusTuple = new Tuple(responseString, status); } else { - JsonAndStatusTuple = new Tuple("", errorStatus); + requestState.GotJsonResponse = true; + jsonAndStatusTuple = new Tuple(responseString??"", errorStatus); } - returnValue.Status = JsonAndStatusTuple.Item2; - string json = JsonAndStatusTuple.Item1; + returnValue.Status = jsonAndStatusTuple.Item2; + string json = jsonAndStatusTuple.Item1; if (!string.IsNullOrEmpty(json)) { List result = ProcessJsonResponse(requestState, json); @@ -257,6 +269,16 @@ internal async Task> Publish(string channel, object me } } } + else + { + PNStatusCategory category = + PNStatusCategoryHelper.GetPNStatusCategory(400, result[1].ToString()); + PNStatus status = + new StatusBuilder(config, jsonLibrary).CreateStatusResponse( + PNOperationType.PNPublishOperation, category, requestState, 400, + new PNException(responseString)); + returnValue.Status = status; + } } } } else { @@ -296,15 +318,15 @@ private string PrepareContent(object originalMessage) private RequestParameter CreateRequestParameter() { - List urlSegments = new List - { + List urlSegments = + [ "publish", - config.PublishKey?? "", - config.SubscribeKey??"", + config.PublishKey ?? "", + config.SubscribeKey ?? "", "0", channelName, "0" - }; + ]; if (!httpPost) { urlSegments.Add(PrepareContent(this.publishContent)); } @@ -323,7 +345,11 @@ private RequestParameter CreateRequestParameter() requestQueryStringParams.Add("store", "0"); } - if (queryParam != null && queryParam.Count > 0) { + if (!string.IsNullOrEmpty(customMessageType)) { + requestQueryStringParams.Add("custom_message_type", customMessageType); + } + + if (queryParam is { Count: > 0 }) { foreach (KeyValuePair kvp in queryParam) { if (!requestQueryStringParams.ContainsKey(kvp.Key)) { requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), PNOperationType.PNPublishOperation, false, false, false)); diff --git a/src/Api/PubnubApi/EndPoint/PubSub/SignalOperation.cs b/src/Api/PubnubApi/EndPoint/PubSub/SignalOperation.cs index 31fb5f5b1..3f7223f99 100644 --- a/src/Api/PubnubApi/EndPoint/PubSub/SignalOperation.cs +++ b/src/Api/PubnubApi/EndPoint/PubSub/SignalOperation.cs @@ -14,6 +14,7 @@ public class SignalOperation : PubnubCoreBase private object signalMessage; private string channelName = string.Empty; + private string customMessageType; private PNCallback savedCallback; private Dictionary queryParam; @@ -36,6 +37,12 @@ public SignalOperation Channel(string channelName) this.channelName = channelName; return this; } + + public SignalOperation CustomMessageType(string customMessageType) + { + this.customMessageType = customMessageType; + return this; + } public SignalOperation QueryParam(Dictionary customQueryParam) { @@ -159,48 +166,53 @@ private async Task> Signal(string channel, object mess requestState.ResponseType = PNOperationType.PNSignalOperation; requestState.Reconnect = false; requestState.EndPointOperation = this; - Tuple JsonAndStatusTuple; var requestParameter = CreateRequestParameter(); - - var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNSignalOperation); - var transportResponse = await PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ConfigureAwait(false); + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNPublishOperation); + var transportResponse = await PubnubInstance.transportMiddleware.Send(transportRequest).ConfigureAwait(false); if (transportResponse.Error == null) { string responseString = Encoding.UTF8.GetString(transportResponse.Content); - PNStatus errorStatus = GetStatusIfError(requestState, responseString); - if (errorStatus == null) { + PNStatus errorStatus = GetStatusIfError(requestState, responseString); + Tuple jsonAndStatusTuple; + if (errorStatus == null && transportResponse.StatusCode == Constants.HttpRequestSuccessStatusCode) { requestState.GotJsonResponse = true; PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(requestState.ResponseType, PNStatusCategory.PNAcknowledgmentCategory, requestState, Constants.HttpRequestSuccessStatusCode, null); - JsonAndStatusTuple = new Tuple(responseString, status); + jsonAndStatusTuple = new Tuple(responseString, status); } else { - JsonAndStatusTuple = new Tuple("", errorStatus); + requestState.GotJsonResponse = true; + jsonAndStatusTuple = new Tuple(responseString??"", errorStatus); } - returnValue.Status = JsonAndStatusTuple.Item2; - string json = JsonAndStatusTuple.Item1; + returnValue.Status = jsonAndStatusTuple.Item2; + string json = jsonAndStatusTuple.Item1; + if (!string.IsNullOrEmpty(json)) { - requestState.GotJsonResponse = true; - List result = ProcessJsonResponse(requestState, responseString); - if (result != null && result.Count >= 3) - { + List result = ProcessJsonResponse(requestState, json); + + if (result is { Count: >= 3 }) { _ = int.TryParse(result[0].ToString(), out var publishStatus); if (publishStatus == 1) { - List resultList = ProcessJsonResponse(requestState, responseString); - if (resultList != null && resultList.Count > 0) { + List resultList = ProcessJsonResponse(requestState, json); + if (resultList is { Count: > 0 }) { ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); PNPublishResult responseResult = responseBuilder.JsonToObject(resultList, true); if (responseResult != null) { returnValue.Result = responseResult; } - } else { - PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(transportResponse.StatusCode, result[1].ToString()); - PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNSignalOperation, category, requestState, transportResponse.StatusCode, new PNException(responseString)); - returnValue.Status = status; - returnValue.Result = default; } } + else + { + PNStatusCategory category = + PNStatusCategoryHelper.GetPNStatusCategory(400, result[1].ToString()); + PNStatus status = + new StatusBuilder(config, jsonLibrary).CreateStatusResponse( + PNOperationType.PNPublishOperation, category, requestState, 400, + new PNException(responseString)); + returnValue.Status = status; + } } } } else { - int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + var statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNPublishOperation, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); returnValue.Status = status; @@ -210,8 +222,8 @@ private async Task> Signal(string channel, object mess private RequestParameter CreateRequestParameter() { - List urlSegments = new List() - { + List urlSegments = + [ "signal", config.PublishKey, config.SubscribeKey, @@ -219,11 +231,25 @@ private RequestParameter CreateRequestParameter() channelName, "0", jsonLibrary.SerializeToJsonString(this.signalMessage) - }; + ]; + Dictionary requestQueryStringParams = new Dictionary(); + + if (!string.IsNullOrEmpty(customMessageType)) { + requestQueryStringParams.Add("custom_message_type", customMessageType); + } + + if (queryParam is { Count: > 0 }) { + foreach (KeyValuePair kvp in queryParam) { + if (!requestQueryStringParams.ContainsKey(kvp.Key)) { + requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), PNOperationType.PNPublishOperation, false, false, false)); + } + } + } var requestParameter = new RequestParameter() { RequestType = Constants.GET, - PathSegment = urlSegments + PathSegment = urlSegments, + Query = requestQueryStringParams }; return requestParameter; diff --git a/src/Api/PubnubApi/EndPoint/PubSub/SubscribeEndpoint.cs b/src/Api/PubnubApi/EndPoint/PubSub/SubscribeEndpoint.cs index 5e13ca538..bbd37f297 100644 --- a/src/Api/PubnubApi/EndPoint/PubSub/SubscribeEndpoint.cs +++ b/src/Api/PubnubApi/EndPoint/PubSub/SubscribeEndpoint.cs @@ -87,6 +87,7 @@ public ISubscribeOperation QueryParam(Dictionary customQueryP public void Execute() { + if(string.IsNullOrEmpty(config.SubscribeKey)) throw new MissingMemberException("Invalid Subscribe key"); subscribeChannelNames ??= new List(); subscribeChannelGroupNames ??= new List(); diff --git a/src/Api/PubnubApi/EndPoint/PubSub/UnsubscribeEndpoint.cs b/src/Api/PubnubApi/EndPoint/PubSub/UnsubscribeEndpoint.cs index 22904353f..1d7a3353c 100644 --- a/src/Api/PubnubApi/EndPoint/PubSub/UnsubscribeEndpoint.cs +++ b/src/Api/PubnubApi/EndPoint/PubSub/UnsubscribeEndpoint.cs @@ -110,7 +110,7 @@ private void Unsubscribe(string[] channels, string[] channelGroups) var isSubscriptionChanged = isUniqueChannelCountChanged || isUniqueChannelGroupCountChanged; if (isSubscriptionChanged) { - subscribeEventEngine.Unsubscribe(subscribeEventEngine.Channels.ToArray(), subscribeEventEngine.Channels.ToArray()); + subscribeEventEngine.Unsubscribe(subscribeEventEngine.Channels.ToArray(), subscribeEventEngine.ChannelGroups.ToArray()); if (config.PresenceInterval > 0 && presenceEventEngineFactory.HasEventEngine(instanceId) && (uniqueChannelsToRemove.Count > 0 || uniqueChannelGroupsToRemove.Count > 0)) { PresenceEventEngine presenceEventEngine = presenceEventEngineFactory.GetEventEngine(instanceId); presenceEventEngine.EventQueue.Enqueue(new EventEngine.Presence.Events.LeftEvent() diff --git a/src/Api/PubnubApi/EndPoint/StoragePlayback/FetchHistoryOperation.cs b/src/Api/PubnubApi/EndPoint/StoragePlayback/FetchHistoryOperation.cs index 2611c19fa..13c931e21 100644 --- a/src/Api/PubnubApi/EndPoint/StoragePlayback/FetchHistoryOperation.cs +++ b/src/Api/PubnubApi/EndPoint/StoragePlayback/FetchHistoryOperation.cs @@ -25,6 +25,7 @@ public class FetchHistoryOperation : PubnubCoreBase private long startTimetoken = -1; private long endTimetoken = -1; private int perChannelCount = -1; + private bool includeCustomMessageType; private Dictionary queryParam; private string[] channelNames; @@ -74,6 +75,12 @@ public FetchHistoryOperation IncludeMessageType(bool withMessageType) includeMessageType = withMessageType; return this; } + + public FetchHistoryOperation IncludeCustomMessageType(bool withCustomMessageType) + { + includeCustomMessageType = withCustomMessageType; + return this; + } public FetchHistoryOperation IncludeUuid(bool withUuid) { @@ -269,6 +276,9 @@ private RequestParameter CreateRequestParameter() if (includeMessageType) { requestQueryStringParams.Add("include_message_type", "true"); } + + requestQueryStringParams.Add("include_custom_message_type", includeCustomMessageType?"true":"false"); + if (queryParam != null && queryParam.Count > 0) { foreach (KeyValuePair kvp in queryParam) { diff --git a/src/Api/PubnubApi/Enum/PNMembershipField.cs b/src/Api/PubnubApi/Enum/PNMembershipField.cs index 1ff35f9bf..89f984453 100644 --- a/src/Api/PubnubApi/Enum/PNMembershipField.cs +++ b/src/Api/PubnubApi/Enum/PNMembershipField.cs @@ -9,6 +9,8 @@ public enum PNMembershipField { CUSTOM, CHANNEL, - CHANNEL_CUSTOM + CHANNEL_CUSTOM, + STATUS, + TYPE } } diff --git a/src/Api/PubnubApi/EventEngine/Common/EventEmitter.cs b/src/Api/PubnubApi/EventEngine/Common/EventEmitter.cs index a6bccc71b..6ead8486c 100644 --- a/src/Api/PubnubApi/EventEngine/Common/EventEmitter.cs +++ b/src/Api/PubnubApi/EventEngine/Common/EventEmitter.cs @@ -10,310 +10,314 @@ namespace PubnubApi.EventEngine.Common { - public class EventEmitter - { - private PNConfiguration configuration; - private List listeners; - private IPubnubLog log; - private IJsonPluggableLibrary jsonLibrary; - private Pubnub instance; - private TokenManager tokenManager; - private Dictionary> channelListenersMap; - private Dictionary> channelGroupListenersMap; + public class EventEmitter + { + private PNConfiguration configuration; + private List listeners; + private IPubnubLog log; + private IJsonPluggableLibrary jsonLibrary; + private Pubnub instance; + private TokenManager tokenManager; + private Dictionary> channelListenersMap; + private Dictionary> channelGroupListenersMap; - public EventEmitter(PNConfiguration configuration, List listenerCallbacks, IJsonPluggableLibrary jsonPluggableLibrary, TokenManager tokenManager, IPubnubLog log, Pubnub instance) - { - this.configuration = configuration; - this.log = log; - this.instance = instance; - this.tokenManager = tokenManager; - jsonLibrary = jsonPluggableLibrary; - listeners = listenerCallbacks; - channelGroupListenersMap = new Dictionary>(); - channelListenersMap = new Dictionary>(); - } + public EventEmitter(PNConfiguration configuration, List listenerCallbacks, IJsonPluggableLibrary jsonPluggableLibrary, TokenManager tokenManager, IPubnubLog log, Pubnub instance) + { + this.configuration = configuration; + this.log = log; + this.instance = instance; + this.tokenManager = tokenManager; + jsonLibrary = jsonPluggableLibrary; + listeners = listenerCallbacks; + channelGroupListenersMap = new Dictionary>(); + channelListenersMap = new Dictionary>(); + } - private TimetokenMetadata GetTimetokenMetadata(object t) - { - Dictionary ttOriginMetaData = jsonLibrary.ConvertToDictionaryObject(t); - if (ttOriginMetaData != null && ttOriginMetaData.Count > 0) { - TimetokenMetadata ttMeta = new TimetokenMetadata(); + private TimetokenMetadata GetTimetokenMetadata(object t) + { + Dictionary ttOriginMetaData = jsonLibrary.ConvertToDictionaryObject(t); + if (ttOriginMetaData != null && ttOriginMetaData.Count > 0) { + TimetokenMetadata ttMeta = new TimetokenMetadata(); - foreach (string metaKey in ttOriginMetaData.Keys) { - if (metaKey.ToLowerInvariant().Equals("t", StringComparison.OrdinalIgnoreCase)) { - long timetoken; - _ = Int64.TryParse(ttOriginMetaData[metaKey].ToString(), out timetoken); - ttMeta.Timetoken = timetoken; - } else if (metaKey.ToLowerInvariant().Equals("r", StringComparison.OrdinalIgnoreCase)) { - ttMeta.Region = ttOriginMetaData[metaKey].ToString(); - } - } - return ttMeta; - } - return null; - } + foreach (string metaKey in ttOriginMetaData.Keys) { + if (metaKey.ToLowerInvariant().Equals("t", StringComparison.OrdinalIgnoreCase)) { + long timetoken; + _ = Int64.TryParse(ttOriginMetaData[metaKey].ToString(), out timetoken); + ttMeta.Timetoken = timetoken; + } else if (metaKey.ToLowerInvariant().Equals("r", StringComparison.OrdinalIgnoreCase)) { + ttMeta.Region = ttOriginMetaData[metaKey].ToString(); + } + } + return ttMeta; + } + return null; + } - public void AddListener(SubscribeCallback listener, string[] channels, string[] groups) - { - foreach (var c in channels.Where(c => !c.EndsWith("-pnpres"))) { - if (channelListenersMap.ContainsKey(c)) { - channelListenersMap[c].Add(listener); - } else { - channelListenersMap[c] = new List { listener }; - } - } + public void AddListener(SubscribeCallback listener, string[] channels, string[] groups) + { + foreach (var c in channels.Where(c => !c.EndsWith("-pnpres"))) { + if (channelListenersMap.ContainsKey(c)) { + channelListenersMap[c].Add(listener); + } else { + channelListenersMap[c] = new List { listener }; + } + } - foreach (var cg in groups.Where(cg => !cg.EndsWith("-pnpres"))) { - if (channelGroupListenersMap.ContainsKey(cg)) { - channelGroupListenersMap[cg].Add(listener); - } else { - channelGroupListenersMap[cg] = new List { listener }; - } - } - } + foreach (var cg in groups.Where(cg => !cg.EndsWith("-pnpres"))) { + if (channelGroupListenersMap.ContainsKey(cg)) { + channelGroupListenersMap[cg].Add(listener); + } else { + channelGroupListenersMap[cg] = new List { listener }; + } + } + } - public void RemoveListener(SubscribeCallback listener, string[] channels, string[] groups) - { - foreach (var c in channels.Where(c => !c.EndsWith("-pnpres"))) { - if (channelListenersMap.ContainsKey(c)) { - channelListenersMap[c].Remove(listener); - } - } - foreach (var cg in groups.Where(cg => !cg.EndsWith("-pnpres"))) { - if (channelGroupListenersMap.ContainsKey(cg)) { - channelGroupListenersMap[cg].Remove(listener); - } - } - } + public void RemoveListener(SubscribeCallback listener, string[] channels, string[] groups) + { + foreach (var c in channels.Where(c => !c.EndsWith("-pnpres"))) { + if (channelListenersMap.ContainsKey(c)) { + channelListenersMap[c].Remove(listener); + } + } + foreach (var cg in groups.Where(cg => !cg.EndsWith("-pnpres"))) { + if (channelGroupListenersMap.ContainsKey(cg)) { + channelGroupListenersMap[cg].Remove(listener); + } + } + } - public void EmitEvent(object e) - { - Message eventData = e as Message; + public void EmitEvent(object e) + { + var eventData = e as Message; + string currentMessageChannel = eventData.Channel; + string currentMessageChannelGroup = eventData.SubscriptionMatch; - string currentMessageChannel = eventData.Channel; - string currentMessageChannelGroup = eventData.SubscriptionMatch; + if (currentMessageChannel.Replace("-pnpres", "") == currentMessageChannelGroup?.Replace("-pnpres", "")) { + currentMessageChannelGroup = ""; + } + object payload; + string payloadAsString = eventData.Payload as string; + if (payloadAsString != null) { + var jsonObject = jsonLibrary.BuildJsonObject(payloadAsString.ToString()); + payload = jsonObject ?? payloadAsString; + } else { + payload = eventData.Payload; + } + List payloadContainer = new List(); //First item always message + if (currentMessageChannel.Contains("-pnpres") || currentMessageChannel.Contains(".*-pnpres")) { + payloadContainer.Add(payload); + } else if (eventData.MessageType == 2) //Objects Simplification events + { + double objectsVersion = -1; + Dictionary objectsDic = payload as Dictionary ?? (payload as JObject).ToObject>(); + if (objectsDic != null + && objectsDic.ContainsKey("source") + && objectsDic.ContainsKey("version") + && objectsDic["source"].ToString() == "objects" + && Double.TryParse(objectsDic["version"].ToString().Trim(), NumberStyles.Number, CultureInfo.InvariantCulture, out objectsVersion)) { + if (objectsVersion.CompareTo(2D) == 0) //Process only version=2 for Objects Simplification. Ignore 1. + { + payloadContainer.Add(payload); + } + } + } else { + if ((configuration.CryptoModule != null || configuration.CipherKey.Length > 0) && (eventData.MessageType == 0 || eventData.MessageType == 4)) //decrypt the subscriber message if cipherkey is available + { + string decryptMessage = ""; + configuration.CryptoModule ??= new CryptoModule(new AesCbcCryptor(configuration.CipherKey, log), new List() { new LegacyCryptor(configuration.CipherKey, configuration.UseRandomInitializationVector) }); + try { + decryptMessage = configuration.CryptoModule.Decrypt(payload.ToString()); + } catch (Exception ex) { + decryptMessage = "**DECRYPT ERROR**"; + LoggingMethod.WriteToLog( + log, + string.Format( + CultureInfo.InvariantCulture, + "Failed to decrypt message on channel {0} in ResponseToUserCallback due to exception={1}.\nMessage might be not encrypted, returning as is...", + currentMessageChannel, + ex + ), + configuration.LogVerbosity + ); + } + object decodeMessage = jsonLibrary.DeserializeToObject((decryptMessage == "**DECRYPT ERROR**") ? jsonLibrary.SerializeToJsonString(payload) : decryptMessage); + payloadContainer.Add(decodeMessage); + } else { + string payloadJson = jsonLibrary.SerializeToJsonString(payload); + object payloadJObject = jsonLibrary.BuildJsonObject(payloadJson); + if (payloadJObject == null) { + payloadContainer.Add(payload); + } else { + payloadContainer.Add(payloadJObject); + } + } + } - if (currentMessageChannel.Replace("-pnpres", "") == currentMessageChannelGroup?.Replace("-pnpres", "")) { - currentMessageChannelGroup = ""; - } - object payload; - string payloadAsString = eventData.Payload as string; - if (payloadAsString != null) { - var jsonObject = jsonLibrary.BuildJsonObject(payloadAsString.ToString()); - payload = jsonObject ?? payloadAsString; - } else { - payload = eventData.Payload; - } - List payloadContainer = new List(); //First item always message - if (currentMessageChannel.Contains("-pnpres") || currentMessageChannel.Contains(".*-pnpres")) { - payloadContainer.Add(payload); - } else if (eventData.MessageType == 2) //Objects Simplification events - { - double objectsVersion = -1; - Dictionary objectsDic = payload as Dictionary ?? (payload as JObject).ToObject>(); - if (objectsDic != null - && objectsDic.ContainsKey("source") - && objectsDic.ContainsKey("version") - && objectsDic["source"].ToString() == "objects" - && Double.TryParse(objectsDic["version"].ToString().Trim(), NumberStyles.Number, CultureInfo.InvariantCulture, out objectsVersion)) { - if (objectsVersion.CompareTo(2D) == 0) //Process only version=2 for Objects Simplification. Ignore 1. - { - payloadContainer.Add(payload); - } - } - } else { - if ((configuration.CryptoModule != null || configuration.CipherKey.Length > 0) && (eventData.MessageType == 0 || eventData.MessageType == 4)) //decrypt the subscriber message if cipherkey is available - { - string decryptMessage = ""; - configuration.CryptoModule ??= new CryptoModule(new AesCbcCryptor(configuration.CipherKey, log), new List() { new LegacyCryptor(configuration.CipherKey, configuration.UseRandomInitializationVector) }); - try { - decryptMessage = configuration.CryptoModule.Decrypt(payload.ToString()); - } catch (Exception ex) { - decryptMessage = "**DECRYPT ERROR**"; - LoggingMethod.WriteToLog( - log, - string.Format( - CultureInfo.InvariantCulture, - "Failed to decrypt message on channel {0} in ResponseToUserCallback due to exception={1}.\nMessage might be not encrypted, returning as is...", - currentMessageChannel, - ex - ), - configuration.LogVerbosity - ); - } - object decodeMessage = jsonLibrary.DeserializeToObject((decryptMessage == "**DECRYPT ERROR**") ? jsonLibrary.SerializeToJsonString(payload) : decryptMessage); - payloadContainer.Add(decodeMessage); - } else { - string payloadJson = jsonLibrary.SerializeToJsonString(payload); - object payloadJObject = jsonLibrary.BuildJsonObject(payloadJson); - if (payloadJObject == null) { - payloadContainer.Add(payload); - } else { - payloadContainer.Add(payloadJObject); - } - } - } + object userMetaData = eventData.UserMetadata; - object userMetaData = eventData.UserMetadata; + payloadContainer.Add(userMetaData); //Second one always user meta data - payloadContainer.Add(userMetaData); //Second one always user meta data + payloadContainer.Add(GetTimetokenMetadata(eventData.PublishMetadata).Timetoken); //Third one always Timetoken - payloadContainer.Add(GetTimetokenMetadata(eventData.PublishMetadata).Timetoken); //Third one always Timetoken + payloadContainer.Add(eventData.IssuingClientId); //Fourth one always Publisher + + payloadContainer.Add(currentMessageChannelGroup); + + payloadContainer.Add(currentMessageChannel); - payloadContainer.Add(eventData.IssuingClientId); //Fourth one always Publisher - - if (!string.IsNullOrEmpty(currentMessageChannelGroup)) //Add cg first before channel - { - payloadContainer.Add(currentMessageChannelGroup); - } - - if (!string.IsNullOrEmpty(currentMessageChannel)) { - payloadContainer.Add(currentMessageChannel); - } - - if (eventData.MessageType == 1) { - ResponseBuilder responseBuilder = new ResponseBuilder(configuration, jsonLibrary, log); - PNMessageResult pnMessageResult = responseBuilder.JsonToObject>(payloadContainer, true); - if (pnMessageResult != null) { - PNSignalResult signalMessage = new PNSignalResult { - Channel = pnMessageResult.Channel, - Message = pnMessageResult.Message, - Subscription = pnMessageResult.Subscription, - Timetoken = pnMessageResult.Timetoken, - UserMetadata = pnMessageResult.UserMetadata, - Publisher = pnMessageResult.Publisher - }; - foreach (var listener in listeners) { - listener?.Signal(instance, signalMessage); - } - if (!string.IsNullOrEmpty(signalMessage.Channel) && channelListenersMap.ContainsKey(signalMessage.Channel)) { - foreach (var l in channelListenersMap[signalMessage.Channel]) { - l?.Signal(instance, signalMessage); - } - } - if (!string.IsNullOrEmpty(signalMessage.Subscription) && channelGroupListenersMap.ContainsKey(signalMessage.Subscription)) { - foreach (var l in channelGroupListenersMap[signalMessage.Subscription]) { - l?.Signal(instance, signalMessage); - } - } - } - } else if (eventData.MessageType == 2) { - ResponseBuilder responseBuilder = new ResponseBuilder(configuration, jsonLibrary, log); - PNObjectEventResult objectApiEvent = responseBuilder.JsonToObject(payloadContainer, true); - if (objectApiEvent != null) { - foreach (var listener in listeners) { - listener?.ObjectEvent(instance, objectApiEvent); - } - if (!string.IsNullOrEmpty(objectApiEvent.Channel) && channelListenersMap.ContainsKey(objectApiEvent.Channel)) { - foreach (var l in channelListenersMap[objectApiEvent.Channel]) { - l?.ObjectEvent(instance, objectApiEvent); - } - } - if (!string.IsNullOrEmpty(objectApiEvent.Subscription) && channelGroupListenersMap.ContainsKey(objectApiEvent.Subscription)) { - foreach (var l in channelGroupListenersMap[objectApiEvent.Subscription]) { - l?.ObjectEvent(instance, objectApiEvent); - } - } - } - } else if (eventData.MessageType == 3) { - ResponseBuilder responseBuilder = new ResponseBuilder(configuration, jsonLibrary, log); - PNMessageActionEventResult messageActionEvent = responseBuilder.JsonToObject(payloadContainer, true); - if (messageActionEvent != null) { - foreach (var listener in listeners) { - listener?.MessageAction(instance, messageActionEvent); - } - if (!string.IsNullOrEmpty(messageActionEvent.Channel) && channelListenersMap.ContainsKey(messageActionEvent.Channel)) { - foreach (var l in channelListenersMap[messageActionEvent.Channel]) { - l?.MessageAction(instance, messageActionEvent); - } - } - if (!string.IsNullOrEmpty(messageActionEvent.Subscription) && channelGroupListenersMap.ContainsKey(messageActionEvent.Subscription)) { - foreach (var l in channelGroupListenersMap[messageActionEvent.Subscription]) { - l?.MessageAction(instance, messageActionEvent); - } - } - } - } else if (eventData.MessageType == 4) { - ResponseBuilder responseBuilder = new ResponseBuilder(configuration, jsonLibrary, log); - PNMessageResult pnFileResult = responseBuilder.JsonToObject>(payloadContainer, true); - if (pnFileResult != null) { - PNFileEventResult fileMessage = new PNFileEventResult { - Channel = pnFileResult.Channel, - Subscription = pnFileResult.Subscription, - Timetoken = pnFileResult.Timetoken, - Publisher = pnFileResult.Publisher, - }; - Dictionary pnMsgObjDic = jsonLibrary.ConvertToDictionaryObject(pnFileResult.Message); - if (pnMsgObjDic != null && pnMsgObjDic.Count > 0) { - if (pnMsgObjDic.ContainsKey("message") && pnMsgObjDic["message"] != null) { - fileMessage.Message = pnMsgObjDic["message"]; - } - if (pnMsgObjDic.ContainsKey("file")) { - Dictionary fileObjDic = jsonLibrary.ConvertToDictionaryObject(pnMsgObjDic["file"]); - if (fileObjDic != null && fileObjDic.ContainsKey("id") && fileObjDic.ContainsKey("name")) { - fileMessage.File = new PNFile { Id = fileObjDic["id"].ToString(), Name = fileObjDic["name"].ToString() }; - fileMessage.File.Url = UriUtil.GetFileUrl(fileName: fileMessage.File.Name, fileId: fileMessage.File.Id, channel:fileMessage.Channel, - pnConfiguration:configuration, pubnub:instance, tokenmanager:tokenManager); - } - } - } else { - if (pnFileResult.Message != null) { - fileMessage.Message = pnFileResult.Message; - } - } - foreach (var listener in listeners) { - listener?.File(instance, fileMessage); - } - if (!string.IsNullOrEmpty(fileMessage.Channel) && channelListenersMap.ContainsKey(fileMessage.Channel)) { - foreach (var l in channelListenersMap[fileMessage.Channel]) { - l?.File(instance, fileMessage); - } - } - if (!string.IsNullOrEmpty(fileMessage.Subscription) && channelGroupListenersMap.ContainsKey(fileMessage.Subscription)) { - foreach (var l in channelGroupListenersMap[fileMessage.Subscription]) { - l?.File(instance, fileMessage); - } - } - } - } else if (currentMessageChannel.Contains("-pnpres")) { - ResponseBuilder responseBuilder = new ResponseBuilder(configuration, jsonLibrary, log); - PNPresenceEventResult presenceEvent = responseBuilder.JsonToObject(payloadContainer, true); - if (presenceEvent != null) { - foreach (var listener in listeners) { - listener?.Presence(instance, presenceEvent); - } - if (!string.IsNullOrEmpty(presenceEvent.Channel) && channelListenersMap.ContainsKey(presenceEvent.Channel)) { - foreach (var l in channelListenersMap[presenceEvent.Channel]) { - l?.Presence(instance, presenceEvent); - } - } - if (!string.IsNullOrEmpty(presenceEvent.Subscription) && channelGroupListenersMap.ContainsKey(presenceEvent.Subscription)) { - foreach (var l in channelGroupListenersMap[presenceEvent.Subscription]) { - l?.Presence(instance, presenceEvent); - } - } - } - - } else { - ResponseBuilder responseBuilder = new ResponseBuilder(configuration, jsonLibrary, log); - PNMessageResult message = responseBuilder.JsonToObject>(payloadContainer, true); - if (message != null) { - foreach (var listener in listeners) { - listener?.Message(instance, message); - } - if (!string.IsNullOrEmpty(message.Channel) && channelListenersMap.ContainsKey(message.Channel)) { - foreach (var l in channelListenersMap[message.Channel]) { - l?.Message(instance, message); - } - } - if (!string.IsNullOrEmpty(message.Subscription) && channelGroupListenersMap.ContainsKey(message.Subscription)) { - foreach (var l in channelGroupListenersMap[message.Subscription]) { - l?.Message(instance, message); - } - } - } - } - } - } -} + if (eventData.MessageType == 1) { + payloadContainer.Add(eventData.CustomMessageType); + ResponseBuilder responseBuilder = new ResponseBuilder(configuration, jsonLibrary, log); + PNMessageResult pnMessageResult = responseBuilder.JsonToObject>(payloadContainer, true); + if (pnMessageResult != null) { + PNSignalResult signalMessage = new PNSignalResult { + Channel = pnMessageResult.Channel, + Message = pnMessageResult.Message, + Subscription = pnMessageResult.Subscription, + Timetoken = pnMessageResult.Timetoken, + UserMetadata = pnMessageResult.UserMetadata, + Publisher = pnMessageResult.Publisher + }; + foreach (var listener in listeners) { + listener?.Signal(instance, signalMessage); + } + if (!string.IsNullOrEmpty(signalMessage.Channel) && channelListenersMap.ContainsKey(signalMessage.Channel)) { + foreach (var l in channelListenersMap[signalMessage.Channel]) { + l?.Signal(instance, signalMessage); + } + } + if (!string.IsNullOrEmpty(signalMessage.Subscription) && channelGroupListenersMap.ContainsKey(signalMessage.Subscription)) { + foreach (var l in channelGroupListenersMap[signalMessage.Subscription]) { + l?.Signal(instance, signalMessage); + } + } + } + } else if (eventData.MessageType == 2) { + ResponseBuilder responseBuilder = new ResponseBuilder(configuration, jsonLibrary, log); + PNObjectEventResult objectApiEvent = responseBuilder.JsonToObject(payloadContainer, true); + if (objectApiEvent != null) { + foreach (var listener in listeners) { + listener?.ObjectEvent(instance, objectApiEvent); + } + if (!string.IsNullOrEmpty(objectApiEvent.Channel) && channelListenersMap.ContainsKey(objectApiEvent.Channel)) { + foreach (var l in channelListenersMap[objectApiEvent.Channel]) { + l?.ObjectEvent(instance, objectApiEvent); + } + } + if (!string.IsNullOrEmpty(objectApiEvent.Subscription) && channelGroupListenersMap.ContainsKey(objectApiEvent.Subscription)) { + foreach (var l in channelGroupListenersMap[objectApiEvent.Subscription]) { + l?.ObjectEvent(instance, objectApiEvent); + } + } + } + } else if (eventData.MessageType == 3) { + ResponseBuilder responseBuilder = new ResponseBuilder(configuration, jsonLibrary, log); + PNMessageActionEventResult messageActionEvent = responseBuilder.JsonToObject(payloadContainer, true); + if (messageActionEvent != null) { + foreach (var listener in listeners) { + listener?.MessageAction(instance, messageActionEvent); + } + if (!string.IsNullOrEmpty(messageActionEvent.Channel) && channelListenersMap.ContainsKey(messageActionEvent.Channel)) { + foreach (var l in channelListenersMap[messageActionEvent.Channel]) { + l?.MessageAction(instance, messageActionEvent); + } + } + if (!string.IsNullOrEmpty(messageActionEvent.Subscription) && channelGroupListenersMap.ContainsKey(messageActionEvent.Subscription)) { + foreach (var l in channelGroupListenersMap[messageActionEvent.Subscription]) { + l?.MessageAction(instance, messageActionEvent); + } + } + } + } else if (eventData.MessageType == 4) { + payloadContainer.Add(eventData.CustomMessageType); + ResponseBuilder responseBuilder = new ResponseBuilder(configuration, jsonLibrary, log); + PNMessageResult pnFileResult = responseBuilder.JsonToObject>(payloadContainer, true); + if (pnFileResult != null) { + PNFileEventResult fileMessage = new PNFileEventResult { + Channel = pnFileResult.Channel, + Subscription = pnFileResult.Subscription, + Timetoken = pnFileResult.Timetoken, + Publisher = pnFileResult.Publisher, + CustomMessageType = pnFileResult.CustomMessageType, + }; + Dictionary pnMsgObjDic = jsonLibrary.ConvertToDictionaryObject(pnFileResult.Message); + if (pnMsgObjDic != null && pnMsgObjDic.Count > 0) { + if (pnMsgObjDic.ContainsKey("message") && pnMsgObjDic["message"] != null) { + fileMessage.Message = pnMsgObjDic["message"]; + } + if (pnMsgObjDic.ContainsKey("file")) { + Dictionary fileObjDic = jsonLibrary.ConvertToDictionaryObject(pnMsgObjDic["file"]); + if (fileObjDic != null && fileObjDic.ContainsKey("id") && fileObjDic.ContainsKey("name")) { + fileMessage.File = new PNFile { Id = fileObjDic["id"].ToString(), Name = fileObjDic["name"].ToString() }; + fileMessage.File.Url = UriUtil.GetFileUrl(fileName: fileMessage.File.Name, fileId: fileMessage.File.Id, channel:fileMessage.Channel, + pnConfiguration:configuration, pubnub:instance, tokenmanager:tokenManager); + } + } + } else { + if (pnFileResult.Message != null) { + fileMessage.Message = pnFileResult.Message; + } + } + foreach (var listener in listeners) { + listener?.File(instance, fileMessage); + } + if (!string.IsNullOrEmpty(fileMessage.Channel) && channelListenersMap.ContainsKey(fileMessage.Channel)) { + foreach (var l in channelListenersMap[fileMessage.Channel]) { + l?.File(instance, fileMessage); + } + } + if (!string.IsNullOrEmpty(fileMessage.Subscription) && channelGroupListenersMap.ContainsKey(fileMessage.Subscription)) { + foreach (var l in channelGroupListenersMap[fileMessage.Subscription]) { + l?.File(instance, fileMessage); + } + } + } + } else if (currentMessageChannel.Contains("-pnpres")) { + ResponseBuilder responseBuilder = new ResponseBuilder(configuration, jsonLibrary, log); + PNPresenceEventResult presenceEvent = responseBuilder.JsonToObject(payloadContainer, true); + if (presenceEvent != null) { + foreach (var listener in listeners) { + listener?.Presence(instance, presenceEvent); + } + if (!string.IsNullOrEmpty(presenceEvent.Channel) && channelListenersMap.ContainsKey(presenceEvent.Channel)) { + foreach (var l in channelListenersMap[presenceEvent.Channel]) { + l?.Presence(instance, presenceEvent); + } + } + if (!string.IsNullOrEmpty(presenceEvent.Subscription) && channelGroupListenersMap.ContainsKey(presenceEvent.Subscription)) { + foreach (var l in channelGroupListenersMap[presenceEvent.Subscription]) { + l?.Presence(instance, presenceEvent); + } + } + } + } else { + payloadContainer.Add(eventData.CustomMessageType); + ResponseBuilder responseBuilder = new ResponseBuilder(configuration, jsonLibrary, log); + PNMessageResult message = responseBuilder.JsonToObject>(payloadContainer, true); + try + { + if (message != null) { + foreach (var listener in listeners) { + listener?.Message(instance, message); + } + if (!string.IsNullOrEmpty(message.Channel) && channelListenersMap.ContainsKey(message.Channel)) { + foreach (var l in channelListenersMap[message.Channel]) { + l?.Message(instance, message); + } + } + if (!string.IsNullOrEmpty(message.Subscription) && channelGroupListenersMap.ContainsKey(message.Subscription)) { + foreach (var l in channelGroupListenersMap[message.Subscription]) { + l?.Message(instance, message); + } + } + } + } + catch (Exception ex) + { + LoggingMethod.WriteToLog(this.log, $"Listener call back execution encounters error: {ex.Message}\n{ex?.StackTrace}", configuration.LogVerbosity); + } + } + } + } +} \ No newline at end of file diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/Common/CommonSubscribeTypes.cs b/src/Api/PubnubApi/EventEngine/Subscribe/Common/CommonSubscribeTypes.cs index 008adb92d..a2deff507 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/Common/CommonSubscribeTypes.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/Common/CommonSubscribeTypes.cs @@ -92,6 +92,9 @@ public class Message [JsonProperty("u")] public object UserMetadata { get; set; } + + [JsonProperty("cmt")] + public string CustomMessageType { get; set; } } public abstract class SubscriptionState : Core.State diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/Effects/EmitMessagesHandler.cs b/src/Api/PubnubApi/EventEngine/Subscribe/Effects/EmitMessagesHandler.cs index a5f7a23d6..13bdbd813 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/Effects/EmitMessagesHandler.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/Effects/EmitMessagesHandler.cs @@ -1,67 +1,101 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Reflection; using System.Threading.Tasks; using PubnubApi.EventEngine.Common; using PubnubApi.EventEngine.Core; +using PubnubApi.EventEngine.Subscribe.Common; using PubnubApi.EventEngine.Subscribe.Invocations; namespace PubnubApi.EventEngine.Subscribe.Effects { - public class EmitMessagesHandler : EffectHandler - { - private readonly Dictionary channelTypeMap; - private readonly Dictionary channelGroupTypeMap; - private readonly IJsonPluggableLibrary jsonPluggableLibrary; - private readonly EventEmitter eventEmitter; + public class EmitMessagesHandler : EffectHandler + { + private readonly Dictionary channelTypeMap; + private readonly Dictionary channelGroupTypeMap; + private readonly IJsonPluggableLibrary jsonPluggableLibrary; + private readonly EventEmitter eventEmitter; - public EmitMessagesHandler(EventEmitter eventEmitter, - IJsonPluggableLibrary jsonPluggableLibrary, - Dictionary channelTypeMap = null, - Dictionary channelGroupTypeMap = null) - { - this.eventEmitter = eventEmitter; - this.channelTypeMap = channelTypeMap; - this.channelGroupTypeMap = channelGroupTypeMap; - this.jsonPluggableLibrary = jsonPluggableLibrary; - } + public EmitMessagesHandler(EventEmitter eventEmitter, + IJsonPluggableLibrary jsonPluggableLibrary, + Dictionary channelTypeMap = null, + Dictionary channelGroupTypeMap = null) + { + this.eventEmitter = eventEmitter; + this.channelTypeMap = channelTypeMap; + this.channelGroupTypeMap = channelGroupTypeMap; + this.jsonPluggableLibrary = jsonPluggableLibrary; + } - public async override Task Run(EmitMessagesInvocation invocation) - { - var processedMessages = invocation.Messages?.Messages?.Select(m => { - m.Payload = DeserializePayload(m.Channel, m.Payload); - return m; - }); + public async override Task Run(EmitMessagesInvocation invocation) + { + var processedMessages = invocation.Messages?.Messages?.Select(m => { + if (CheckForNonGenericSerialization(m)) + { + return m; + } + m.Payload = DeserializePayload(m.Channel, m.Payload); + return m; + }); - if (processedMessages is null) return; + if (processedMessages is null) return; - foreach (var message in processedMessages) { - eventEmitter.EmitEvent(message); - } - } + foreach (var message in processedMessages) + { + Type type = MessageTypeValue(message.SubscriptionMatch??message.Channel); + var methodInfo = eventEmitter.GetType().GetMethod("EmitEvent"); + var genericMethod = methodInfo?.MakeGenericMethod([type]); + genericMethod?.Invoke(eventEmitter, [message]); + } + } - private object DeserializePayload(string key, object rawMessage) - { - try { - Type t; - if ((channelTypeMap is not null && channelTypeMap.TryGetValue(key, out t) || - channelGroupTypeMap is not null && channelGroupTypeMap.TryGetValue(key, out t)) && - t != typeof(string)) - { - return jsonPluggableLibrary.DeserializeToObject(rawMessage, t); - } else { - return rawMessage.ToString(); - } - } catch (Exception) { - return rawMessage; - } - } + private bool CheckForNonGenericSerialization(Message message) + { + var channel = message.Channel; + var channelGroup = message.SubscriptionMatch; + var type = message.MessageType; + if (channel.EndsWith(Constants.Pnpres)) return true; + if (!string.IsNullOrEmpty(channelGroup) && channelGroup.EndsWith(Constants.Pnpres)) return true; + if (type == 0) return false; + return true; + } - public override bool IsBackground(EmitMessagesInvocation invocation) => false; + private Type MessageTypeValue(string channel) + { + try { + Type t; + if ((channelTypeMap is not null && channelTypeMap.TryGetValue(channel, out t) || + channelGroupTypeMap is not null && channelGroupTypeMap.TryGetValue(channel, out t)) && + t != typeof(string)) + { + return t; + } + return typeof(string); + } catch (Exception) { + return typeof(object); + } + } + private object DeserializePayload(string key, object rawMessage) + { + try { + Type t; + if ((channelTypeMap is not null && channelTypeMap.TryGetValue(key, out t) || + channelGroupTypeMap is not null && channelGroupTypeMap.TryGetValue(key, out t)) && + t != typeof(string)) + { + return jsonPluggableLibrary.DeserializeToObject(rawMessage, t); + } else { + return rawMessage.ToString(); + } + } catch (Exception) { + return rawMessage; + } + } - public override Task Cancel() - { - throw new NotImplementedException(); - } - } -} \ No newline at end of file + public override bool IsBackground(EmitMessagesInvocation invocation) => false; + + public override Task Cancel() => Task.CompletedTask; + + } +} diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/States/HandshakeFailedState.cs b/src/Api/PubnubApi/EventEngine/Subscribe/States/HandshakeFailedState.cs index 0a8f6dbfa..0065977d8 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/States/HandshakeFailedState.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/States/HandshakeFailedState.cs @@ -1,6 +1,7 @@ using System.Linq; using PubnubApi.EventEngine.Core; using PubnubApi.EventEngine.Subscribe.Common; +using PubnubApi.EventEngine.Subscribe.Invocations; namespace PubnubApi.EventEngine.Subscribe.States { @@ -10,10 +11,7 @@ public override TransitionResult Transition(IEvent e) { return e switch { - Events.UnsubscribeAllEvent unsubscribeAll => new UnsubscribedState() - { - - }, + Events.UnsubscribeAllEvent unsubscribeAll => new UnsubscribedState() { }.With(new EmitStatusInvocation(PNStatusCategory.PNDisconnectedCategory)), Events.SubscriptionChangedEvent subscriptionChanged => new HandshakingState() { diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/States/HandshakeReconnectingState.cs b/src/Api/PubnubApi/EventEngine/Subscribe/States/HandshakeReconnectingState.cs index ea803c84b..49b4b6ad1 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/States/HandshakeReconnectingState.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/States/HandshakeReconnectingState.cs @@ -23,8 +23,7 @@ public class HandshakeReconnectingState : SubscriptionState public override TransitionResult Transition(IEvent e) { return e switch { - Events.UnsubscribeAllEvent unsubscribeAll => new UnsubscribedState() { - }, + Events.UnsubscribeAllEvent unsubscribeAll => new UnsubscribedState() { }.With(new EmitStatusInvocation(PNStatusCategory.PNDisconnectedCategory)), Events.SubscriptionChangedEvent subscriptionChanged => new HandshakingState() { Channels = subscriptionChanged.Channels?? Enumerable.Empty(), diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/States/HandshakeStoppedState.cs b/src/Api/PubnubApi/EventEngine/Subscribe/States/HandshakeStoppedState.cs index 588e1f5ae..d99125867 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/States/HandshakeStoppedState.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/States/HandshakeStoppedState.cs @@ -1,6 +1,7 @@ using System.Linq; using PubnubApi.EventEngine.Core; using PubnubApi.EventEngine.Subscribe.Common; +using PubnubApi.EventEngine.Subscribe.Invocations; namespace PubnubApi.EventEngine.Subscribe.States { @@ -10,10 +11,7 @@ public override TransitionResult Transition(IEvent e) { return e switch { - Events.UnsubscribeAllEvent unsubscribeAll => new UnsubscribedState() - { - - }, + Events.UnsubscribeAllEvent unsubscribeAll => new UnsubscribedState() { }.With(new EmitStatusInvocation(PNStatusCategory.PNDisconnectedCategory)), Events.SubscriptionChangedEvent subscriptionChanged => new HandshakingState() { diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/States/HandshakingState.cs b/src/Api/PubnubApi/EventEngine/Subscribe/States/HandshakingState.cs index 59e6a246d..ab47752f1 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/States/HandshakingState.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/States/HandshakingState.cs @@ -17,9 +17,7 @@ public override TransitionResult Transition(IEvent e) { return e switch { - Events.UnsubscribeAllEvent unsubscribeAll => new UnsubscribedState() - { - }, + Events.UnsubscribeAllEvent unsubscribeAll => new UnsubscribedState() { }.With(new EmitStatusInvocation(PNStatusCategory.PNDisconnectedCategory)), Events.SubscriptionChangedEvent subscriptionChanged => new States.HandshakingState() { diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceiveFailedState.cs b/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceiveFailedState.cs index d01a5da24..20a59d824 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceiveFailedState.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceiveFailedState.cs @@ -2,6 +2,7 @@ using System.Linq; using PubnubApi.EventEngine.Core; using PubnubApi.EventEngine.Subscribe.Common; +using PubnubApi.EventEngine.Subscribe.Invocations; namespace PubnubApi.EventEngine.Subscribe.States { @@ -14,10 +15,7 @@ public override TransitionResult Transition(IEvent e) { return e switch { - Events.UnsubscribeAllEvent unsubscribeAll => new UnsubscribedState() - { - - }, + Events.UnsubscribeAllEvent unsubscribeAll => new UnsubscribedState() { }.With(new EmitStatusInvocation(PNStatusCategory.PNDisconnectedCategory)), Events.SubscriptionChangedEvent subscriptionChanged => new HandshakingState() { diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceiveReconnectingState.cs b/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceiveReconnectingState.cs index 1aa67aff0..03307f0e5 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceiveReconnectingState.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceiveReconnectingState.cs @@ -27,10 +27,7 @@ public override TransitionResult Transition(IEvent e) { return e switch { - Events.UnsubscribeAllEvent unsubscribeAll => new UnsubscribedState() - { - - }, + Events.UnsubscribeAllEvent unsubscribeAll => new UnsubscribedState() { }.With(new EmitStatusInvocation(PNStatusCategory.PNDisconnectedCategory)), Events.SubscriptionChangedEvent subscriptionChanged => new ReceivingState() { @@ -72,7 +69,7 @@ public override TransitionResult Transition(IEvent e) Cursor = this.Cursor, AttemptedRetries = this.AttemptedRetries + 1, Reason = receiveReconnectFailure.Status - }, + }.With(new EmitStatusInvocation(PNStatusCategory.PNUnexpectedDisconnectCategory)), Events.ReceiveReconnectGiveUpEvent receiveReconnectGiveUp => new ReceiveFailedState() { diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceiveStoppedState.cs b/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceiveStoppedState.cs index 2ff4703a6..46b7e9783 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceiveStoppedState.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceiveStoppedState.cs @@ -1,6 +1,7 @@ using System.Linq; using PubnubApi.EventEngine.Core; using PubnubApi.EventEngine.Subscribe.Common; +using PubnubApi.EventEngine.Subscribe.Invocations; namespace PubnubApi.EventEngine.Subscribe.States { @@ -10,7 +11,7 @@ public override TransitionResult Transition(IEvent e) { return e switch { - Events.UnsubscribeAllEvent unsubscribeAll => new UnsubscribedState() { }, + Events.UnsubscribeAllEvent unsubscribeAll => new UnsubscribedState() { }.With(new EmitStatusInvocation(PNStatusCategory.PNDisconnectedCategory)), Events.SubscriptionChangedEvent subscriptionChanged => new ReceiveStoppedState() { diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceivingState.cs b/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceivingState.cs index 2d6d2b60f..b74144456 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceivingState.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceivingState.cs @@ -17,7 +17,7 @@ public override TransitionResult Transition(IEvent e) { return e switch { - Events.UnsubscribeAllEvent unsubscribeAll => new UnsubscribedState() { }, + Events.UnsubscribeAllEvent unsubscribeAll => new UnsubscribedState() { }.With(new EmitStatusInvocation(PNStatusCategory.PNDisconnectedCategory)), Events.ReceiveSuccessEvent receiveSuccess => new ReceivingState() { diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/States/UnsubscribedState.cs b/src/Api/PubnubApi/EventEngine/Subscribe/States/UnsubscribedState.cs index 61b84a6d5..142253621 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/States/UnsubscribedState.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/States/UnsubscribedState.cs @@ -1,6 +1,7 @@ using System.Linq; using PubnubApi.EventEngine.Core; using PubnubApi.EventEngine.Subscribe.Common; +using PubnubApi.EventEngine.Subscribe.Invocations; namespace PubnubApi.EventEngine.Subscribe.States { @@ -10,6 +11,7 @@ public override TransitionResult Transition(Core.IEvent e) { return e switch { + Events.UnsubscribeAllEvent unsubscribeAll => new UnsubscribedState() { }.With(new EmitStatusInvocation(PNStatusCategory.PNDisconnectedCategory)), Events.SubscriptionChangedEvent subscriptionChanged => new HandshakingState() { Channels = subscriptionChanged.Channels?? Enumerable.Empty(), diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/SubscribeEventEngine.cs b/src/Api/PubnubApi/EventEngine/Subscribe/SubscribeEventEngine.cs index 71d132548..1a137342e 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/SubscribeEventEngine.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/SubscribeEventEngine.cs @@ -89,11 +89,18 @@ public void UnsubscribeAll() public void Unsubscribe(string[] channels, string[] channelGroups) { - if(channels.Length>0 || channelGroups.Length>0) - EventQueue.Enqueue(new SubscriptionChangedEvent() { + if (channels.Length > 0 || channelGroups.Length > 0) + { + EventQueue.Enqueue(new SubscriptionChangedEvent() + { Channels = Channels.Distinct(), ChannelGroups = ChannelGroups.Distinct() }); + } + else + { + EventQueue.Enqueue(new UnsubscribeAllEvent()); + } } } } \ No newline at end of file diff --git a/src/Api/PubnubApi/JsonDataParse/DeserializeToInternalObjectUtility.cs b/src/Api/PubnubApi/JsonDataParse/DeserializeToInternalObjectUtility.cs index e88375ef2..65a4c166d 100644 --- a/src/Api/PubnubApi/JsonDataParse/DeserializeToInternalObjectUtility.cs +++ b/src/Api/PubnubApi/JsonDataParse/DeserializeToInternalObjectUtility.cs @@ -187,8 +187,8 @@ public static T DeserializeToInternalObject(IJsonPluggableLibrary jsonPlug, L if (listObject.Count == 6) { - ack.Subscription = listObject[4].ToString(); - ack.Subscription = ack.Subscription.Replace("-pnpres", ""); + ack.Subscription = listObject[5]?.ToString(); + ack.Subscription = ack.Subscription?.Replace("-pnpres", ""); } if (listObject[1] != null) diff --git a/src/Api/PubnubApi/JsonDataParse/PNFetchHistoryJsonDataParse.cs b/src/Api/PubnubApi/JsonDataParse/PNFetchHistoryJsonDataParse.cs index b17da3cfb..018a09b38 100644 --- a/src/Api/PubnubApi/JsonDataParse/PNFetchHistoryJsonDataParse.cs +++ b/src/Api/PubnubApi/JsonDataParse/PNFetchHistoryJsonDataParse.cs @@ -62,6 +62,11 @@ internal static PNFetchHistoryResult GetObject(IJsonPluggableLibrary jsonPlug, L { result.MessageType = messageType; } + + if (messagesContainer.ContainsKey("custom_message_type") && !string.IsNullOrEmpty((string)messagesContainer["custom_message_type"])) + { + result.CustomMessageType = messagesContainer["custom_message_type"].ToString(); + } } resultList.Add(result); } diff --git a/src/Api/PubnubApi/JsonDataParse/PNMembershipsJsonDataParse.cs b/src/Api/PubnubApi/JsonDataParse/PNMembershipsJsonDataParse.cs index 6ef03e78c..01a5ac2a7 100644 --- a/src/Api/PubnubApi/JsonDataParse/PNMembershipsJsonDataParse.cs +++ b/src/Api/PubnubApi/JsonDataParse/PNMembershipsJsonDataParse.cs @@ -53,6 +53,17 @@ internal static PNMembershipsResult GetObject(IJsonPluggableLibrary jsonPlug, Li mbrshipItem.ChannelMetadata = channelMetadataResult; } } + + mbrshipItem.Status = + (getMbrshipItemDataDic.ContainsKey("status") && + getMbrshipItemDataDic["status"] != null) + ? getMbrshipItemDataDic["status"]?.ToString() + : null; + mbrshipItem.Type = + (getMbrshipItemDataDic.ContainsKey("type") && + getMbrshipItemDataDic["type"] != null) + ? getMbrshipItemDataDic["type"]?.ToString() + : null; result.Memberships.Add(mbrshipItem); } } diff --git a/src/Api/PubnubApi/JsonDataParse/PNMessageActionEventJsonDataParse.cs b/src/Api/PubnubApi/JsonDataParse/PNMessageActionEventJsonDataParse.cs index e80b54538..1d2ea877c 100644 --- a/src/Api/PubnubApi/JsonDataParse/PNMessageActionEventJsonDataParse.cs +++ b/src/Api/PubnubApi/JsonDataParse/PNMessageActionEventJsonDataParse.cs @@ -44,12 +44,8 @@ internal static PNMessageActionEventResult GetObject(IJsonPluggableLibrary jsonP } } result.Uuid = listObject[3].ToString(); - if (listObject.Count == 6) { - result.Subscription = listObject[4].ToString(); - result.Channel = listObject[5].ToString(); - } else if (listObject.Count == 5) { - result.Channel = listObject[4].ToString(); - } + result.Subscription = listObject[4]?.ToString(); + result.Channel = listObject[5]?.ToString(); } diff --git a/src/Api/PubnubApi/JsonDataParse/PNObjectEventJsonDataParse.cs b/src/Api/PubnubApi/JsonDataParse/PNObjectEventJsonDataParse.cs index ea2d2824d..1cf47116a 100644 --- a/src/Api/PubnubApi/JsonDataParse/PNObjectEventJsonDataParse.cs +++ b/src/Api/PubnubApi/JsonDataParse/PNObjectEventJsonDataParse.cs @@ -88,12 +88,8 @@ internal static PNObjectEventResult GetObject(IJsonPluggableLibrary jsonPlug, Li } } } - if (listObject.Count == 6) { - result.Subscription = listObject[4].ToString(); - result.Channel = listObject[5].ToString(); - } else if (listObject.Count == 5) { - result.Channel = listObject[4].ToString(); - } + result.Subscription = listObject[4]?.ToString(); + result.Channel = listObject[5].ToString(); } return result; diff --git a/src/Api/PubnubApi/Model/Consumer/History/PNHistoryItemResult.cs b/src/Api/PubnubApi/Model/Consumer/History/PNHistoryItemResult.cs index 7e412cdde..4ba484f2d 100644 --- a/src/Api/PubnubApi/Model/Consumer/History/PNHistoryItemResult.cs +++ b/src/Api/PubnubApi/Model/Consumer/History/PNHistoryItemResult.cs @@ -13,5 +13,7 @@ public class PNHistoryItemResult public object Actions { get; internal set; } public string Uuid { get; internal set; } public int MessageType { get; internal set; } + + public string CustomMessageType { get; internal set; } } } diff --git a/src/Api/PubnubApi/Model/Consumer/Objects/PNMembership.cs b/src/Api/PubnubApi/Model/Consumer/Objects/PNMembership.cs index a4c122a0f..40fda8f6e 100644 --- a/src/Api/PubnubApi/Model/Consumer/Objects/PNMembership.cs +++ b/src/Api/PubnubApi/Model/Consumer/Objects/PNMembership.cs @@ -13,5 +13,11 @@ public class PNMembership [JsonProperty(PropertyName = "custom", DefaultValueHandling = DefaultValueHandling.Ignore)] public Dictionary Custom { get; set; } + + [JsonProperty(PropertyName = "status", DefaultValueHandling = DefaultValueHandling.Ignore)] + public string Status { get; set; } + + [JsonProperty(PropertyName = "type", DefaultValueHandling = DefaultValueHandling.Ignore)] + public string Type { get; set; } } } diff --git a/src/Api/PubnubApi/Model/Consumer/Objects/PNMembershipsItemResult.cs b/src/Api/PubnubApi/Model/Consumer/Objects/PNMembershipsItemResult.cs index 296d09c5d..a570519cc 100644 --- a/src/Api/PubnubApi/Model/Consumer/Objects/PNMembershipsItemResult.cs +++ b/src/Api/PubnubApi/Model/Consumer/Objects/PNMembershipsItemResult.cs @@ -9,6 +9,10 @@ public class PNMembershipsItemResult { public PNChannelMetadataResult ChannelMetadata { get; internal set; } public Dictionary Custom { get; internal set; } + + public string Type { get; set; } + + public string Status { get; set; } public string Updated { get; internal set; } } } diff --git a/src/Api/PubnubApi/Model/Consumer/Pubsub/PNFileEventResult.cs b/src/Api/PubnubApi/Model/Consumer/Pubsub/PNFileEventResult.cs index 45d61830e..de4a00cdb 100644 --- a/src/Api/PubnubApi/Model/Consumer/Pubsub/PNFileEventResult.cs +++ b/src/Api/PubnubApi/Model/Consumer/Pubsub/PNFileEventResult.cs @@ -11,6 +11,8 @@ public class PNFileEventResult public string Subscription { get; internal set; } public string Publisher { get; internal set; } public long Timetoken { get; internal set; } + + public string CustomMessageType { get; internal set; } public object Message { get; internal set; } public PNFile File { get; internal set; } } diff --git a/src/Api/PubnubApi/Model/Consumer/Pubsub/PNMessageResult.cs b/src/Api/PubnubApi/Model/Consumer/Pubsub/PNMessageResult.cs index ddb0e2e78..dc6b7919d 100644 --- a/src/Api/PubnubApi/Model/Consumer/Pubsub/PNMessageResult.cs +++ b/src/Api/PubnubApi/Model/Consumer/Pubsub/PNMessageResult.cs @@ -8,6 +8,8 @@ public class PNMessageResult public string Channel { get; internal set; } public string Subscription { get; internal set; } public long Timetoken { get; internal set; } + + public string CustomMessageType { get; internal set; } public object UserMetadata { get; internal set; } public string Publisher { get; internal set; } } diff --git a/src/Api/PubnubApi/Model/Derived/Pubsub/SubscribeCallbackExt.cs b/src/Api/PubnubApi/Model/Derived/Pubsub/SubscribeCallbackExt.cs index 65713cbea..0f1d91a12 100644 --- a/src/Api/PubnubApi/Model/Derived/Pubsub/SubscribeCallbackExt.cs +++ b/src/Api/PubnubApi/Model/Derived/Pubsub/SubscribeCallbackExt.cs @@ -199,6 +199,7 @@ public override void Message(Pubnub pubnub, PNMessageResult message) message1.Timetoken = message.Timetoken; message1.UserMetadata = message.UserMetadata; message1.Publisher = message.Publisher; + message1.CustomMessageType = message.CustomMessageType; subscribeAction?.Invoke(pubnub, message1); } @@ -222,6 +223,7 @@ public override void Signal(Pubnub pubnub, PNSignalResult signalMessage) message1.Timetoken = signalMessage.Timetoken; message1.UserMetadata = signalMessage.UserMetadata; message1.Publisher = signalMessage.Publisher; + message1.CustomMessageType = signalMessage.CustomMessageType; signalAction?.Invoke(pubnub, message1); } @@ -245,6 +247,7 @@ public override void File(Pubnub pubnub, PNFileEventResult fileEvent) message1.Timetoken = fileEvent.Timetoken; message1.Publisher = fileEvent.Publisher; message1.File = fileEvent.File; + message1.CustomMessageType = fileEvent.CustomMessageType; fileAction?.Invoke(pubnub, message1); } diff --git a/src/Api/PubnubApi/Model/Server/SubscribeMessage.cs b/src/Api/PubnubApi/Model/Server/SubscribeMessage.cs index f6aaf0bdc..498043b7f 100644 --- a/src/Api/PubnubApi/Model/Server/SubscribeMessage.cs +++ b/src/Api/PubnubApi/Model/Server/SubscribeMessage.cs @@ -67,6 +67,8 @@ internal class SubscribeMessage /// private object u { get; set; } + private string cmt { get; set; } + public string Shard { get @@ -210,6 +212,18 @@ internal set u = value; } } + + public string CustomMessageType + { + get + { + return cmt; + } + internal set + { + cmt = value; + } + } } } diff --git a/src/Api/PubnubApi/NewtonsoftJsonDotNet.cs b/src/Api/PubnubApi/NewtonsoftJsonDotNet.cs index 66d7d0518..68511b36d 100644 --- a/src/Api/PubnubApi/NewtonsoftJsonDotNet.cs +++ b/src/Api/PubnubApi/NewtonsoftJsonDotNet.cs @@ -319,22 +319,21 @@ private T DeserializeMessageToObjectBasedOnPlatform(List listObject) // Set ChannelName PropertyInfo channelNameProp = specific.GetRuntimeProperty("Channel"); - channelNameProp.SetValue(message, - (listObject.Count == 6) ? listObject[5].ToString() : listObject[4].ToString(), null); + channelNameProp.SetValue(message, listObject[5]?.ToString(), null); // Set ChannelGroup - if (listObject.Count == 6) - { - PropertyInfo subsciptionProp = specific.GetRuntimeProperty("Subscription"); - subsciptionProp.SetValue(message, listObject[4].ToString(), null); - } - + PropertyInfo subsciptionProp = specific.GetRuntimeProperty("Subscription"); + subsciptionProp.SetValue(message, listObject[4]?.ToString(), null); + + PropertyInfo customMessageType = specific.GetRuntimeProperty("CustomMessageType"); + customMessageType.SetValue(message, listObject[6], null); //Set Metadata list second position, index=1 if (listObject[1] != null) { PropertyInfo userMetadataProp = specific.GetRuntimeProperty("UserMetadata"); userMetadataProp.SetValue(message, listObject[1], null); } + ret = (T)Convert.ChangeType(message, specific, CultureInfo.InvariantCulture); } diff --git a/src/Api/PubnubApi/Properties/AssemblyInfo.cs b/src/Api/PubnubApi/Properties/AssemblyInfo.cs index b4981c086..62a78e2dc 100644 --- a/src/Api/PubnubApi/Properties/AssemblyInfo.cs +++ b/src/Api/PubnubApi/Properties/AssemblyInfo.cs @@ -11,8 +11,8 @@ [assembly: AssemblyProduct("Pubnub C# SDK")] [assembly: AssemblyCopyright("Copyright © 2021")] [assembly: AssemblyTrademark("")] -[assembly: AssemblyVersion("7.0.0.0")] -[assembly: AssemblyFileVersion("7.0.0.0")] +[assembly: AssemblyVersion("7.1.0.0")] +[assembly: AssemblyFileVersion("7.1.0.0")] // Setting ComVisible to false makes the types in this assembly not visible // to COM components. If you need to access a type in this assembly from // COM, set the ComVisible attribute to true on that type. diff --git a/src/Api/PubnubApi/PubnubApi.csproj b/src/Api/PubnubApi/PubnubApi.csproj index 8cdfb456f..5aa9b1055 100644 --- a/src/Api/PubnubApi/PubnubApi.csproj +++ b/src/Api/PubnubApi/PubnubApi.csproj @@ -14,7 +14,7 @@ Pubnub - 7.0.0.0 + 7.1.0.0 PubNub C# .NET - Web Data Push API Pandu Masabathula PubNub @@ -22,11 +22,8 @@ http://pubnub.s3.amazonaws.com/2011/powered-by-pubnub/pubnub-icon-600x600.png true https://github.com/pubnub/c-sharp/ - Added support for `Channel`, `ChannelGroup`, `Subscription` and `SubscriptionSet`, `ChannelMetadata`, `UserMetadata` entities for Subscribe related operation. -BREAKING CHANGES: Added new event listeners support. -BREAKING CHANGES: All apis calls will be made through `HttpClient` by default. -Default value for `EnableEventEngine` is set to `true`, Subscribe operation will be executed by event engine by default. -Removed telemetry manager. + Added support for CustomMessageType in publish, signal, files features. +Added support for Type field in membership APIs. Web Data Push Real-time Notifications ESB Message Broadcasting Distributed Computing PubNub is a Massively Scalable Web Push Service for Web and Mobile Games. This is a cloud-based service for broadcasting messages to thousands of web and mobile clients simultaneously diff --git a/src/Api/PubnubApi/PubnubCoreBase.cs b/src/Api/PubnubApi/PubnubCoreBase.cs index b1736de32..680f201dd 100644 --- a/src/Api/PubnubApi/PubnubCoreBase.cs +++ b/src/Api/PubnubApi/PubnubCoreBase.cs @@ -353,6 +353,9 @@ private static List GetMessageFromMultiplexResult(List case "c": msg.Channel = dicItem[key].ToString(); break; + case "cmt": + msg.CustomMessageType = dicItem[key]?.ToString(); + break; case "d": msg.Payload = dicItem[key]; break; @@ -680,16 +683,10 @@ private void ResponseToUserCallback(List result, PNOperationType type payloadContainer.Add(currentMessage.PublishTimetokenMetadata.Timetoken); //Third one always Timetoken payloadContainer.Add(currentMessage.IssuingClientId); //Fourth one always Publisher - - if (!string.IsNullOrEmpty(currentMessageChannelGroup)) //Add cg first before channel - { - payloadContainer.Add(currentMessageChannelGroup); - } - - if (!string.IsNullOrEmpty(currentMessageChannel)) - { - payloadContainer.Add(currentMessageChannel); - } + + payloadContainer.Add(currentMessageChannelGroup); + + payloadContainer.Add(currentMessageChannel); if (currentMessage.MessageType == 1) { @@ -704,7 +701,8 @@ private void ResponseToUserCallback(List result, PNOperationType type Subscription = pnMessageResult.Subscription, Timetoken = pnMessageResult.Timetoken, UserMetadata = pnMessageResult.UserMetadata, - Publisher = pnMessageResult.Publisher + Publisher = pnMessageResult.Publisher, + CustomMessageType = pnMessageResult.CustomMessageType }; Announce(signalMessage); } @@ -729,6 +727,7 @@ private void ResponseToUserCallback(List result, PNOperationType type } else if (currentMessage.MessageType == 4) { + payloadContainer.Add(currentMessage.CustomMessageType); ResponseBuilder responseBuilder = new ResponseBuilder(currentConfig, jsonLib, currentLog); PNMessageResult pnFileResult = responseBuilder.JsonToObject>(payloadContainer, true); if (pnFileResult != null) @@ -785,6 +784,7 @@ private void ResponseToUserCallback(List result, PNOperationType type { LoggingMethod.WriteToLog(currentLog, string.Format(CultureInfo.InvariantCulture, "DateTime: {0}, ResponseToUserCallback - payload = {1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), jsonLib.SerializeToJsonString(payloadContainer)), currentConfig.LogVerbosity); } + payloadContainer.Add(currentMessage.CustomMessageType); ResponseBuilder responseBuilder = new ResponseBuilder(currentConfig, jsonLib, currentLog); PNMessageResult userMessage = responseBuilder.JsonToObject>(payloadContainer, true); if (userMessage != null) diff --git a/src/Api/PubnubApiPCL/PubnubApiPCL.csproj b/src/Api/PubnubApiPCL/PubnubApiPCL.csproj index f681576ca..a5c2af288 100644 --- a/src/Api/PubnubApiPCL/PubnubApiPCL.csproj +++ b/src/Api/PubnubApiPCL/PubnubApiPCL.csproj @@ -15,7 +15,7 @@ PubnubPCL - 7.0.0.0 + 7.1.0.0 PubNub C# .NET - Web Data Push API Pandu Masabathula PubNub @@ -23,11 +23,8 @@ http://pubnub.s3.amazonaws.com/2011/powered-by-pubnub/pubnub-icon-600x600.png true https://github.com/pubnub/c-sharp/ - Added support for `Channel`, `ChannelGroup`, `Subscription` and `SubscriptionSet`, `ChannelMetadata`, `UserMetadata` entities for Subscribe related operation. -BREAKING CHANGES: Added new event listeners support. -BREAKING CHANGES: All apis calls will be made through `HttpClient` by default. -Default value for `EnableEventEngine` is set to `true`, Subscribe operation will be executed by event engine by default. -Removed telemetry manager. + Added support for CustomMessageType in publish, signal, files features. +Added support for Type field in membership APIs. Web Data Push Real-time Notifications ESB Message Broadcasting Distributed Computing PubNub is a Massively Scalable Web Push Service for Web and Mobile Games. This is a cloud-based service for broadcasting messages to thousands of web and mobile clients simultaneously diff --git a/src/Api/PubnubApiUWP/PubnubApiUWP.csproj b/src/Api/PubnubApiUWP/PubnubApiUWP.csproj index b74ac7efa..105fef7f7 100644 --- a/src/Api/PubnubApiUWP/PubnubApiUWP.csproj +++ b/src/Api/PubnubApiUWP/PubnubApiUWP.csproj @@ -16,7 +16,7 @@ PubnubUWP - 7.0.0.0 + 7.1.0.0 PubNub C# .NET - Web Data Push API Pandu Masabathula PubNub @@ -24,11 +24,8 @@ http://pubnub.s3.amazonaws.com/2011/powered-by-pubnub/pubnub-icon-600x600.png true https://github.com/pubnub/c-sharp/ - Added support for `Channel`, `ChannelGroup`, `Subscription` and `SubscriptionSet`, `ChannelMetadata`, `UserMetadata` entities for Subscribe related operation. -BREAKING CHANGES: Added new event listeners support. -BREAKING CHANGES: All apis calls will be made through `HttpClient` by default. -Default value for `EnableEventEngine` is set to `true`, Subscribe operation will be executed by event engine by default. -Removed telemetry manager. + Added support for CustomMessageType in publish, signal, files features. +Added support for Type field in membership APIs. Web Data Push Real-time Notifications ESB Message Broadcasting Distributed Computing PubNub is a Massively Scalable Web Push Service for Web and Mobile Games. This is a cloud-based service for broadcasting messages to thousands of web and mobile clients simultaneously diff --git a/src/Api/PubnubApiUnity/PubnubApiUnity.csproj b/src/Api/PubnubApiUnity/PubnubApiUnity.csproj index 510ac70ec..ed0d66ae7 100644 --- a/src/Api/PubnubApiUnity/PubnubApiUnity.csproj +++ b/src/Api/PubnubApiUnity/PubnubApiUnity.csproj @@ -15,7 +15,7 @@ PubnubApiUnity - 7.0.0.0 + 7.1.0.0 PubNub C# .NET - Web Data Push API Pandu Masabathula PubNub diff --git a/src/UnitTests/AcceptanceTests/AcceptanceTests.csproj b/src/UnitTests/AcceptanceTests/AcceptanceTests.csproj index 0f341fd10..aab1c9c73 100644 --- a/src/UnitTests/AcceptanceTests/AcceptanceTests.csproj +++ b/src/UnitTests/AcceptanceTests/AcceptanceTests.csproj @@ -31,6 +31,10 @@ + + + + diff --git a/src/UnitTests/AcceptanceTests/Features/files/file-upload-withCustomMessageType.feature b/src/UnitTests/AcceptanceTests/Features/files/file-upload-withCustomMessageType.feature new file mode 100644 index 000000000..7f0cd64ba --- /dev/null +++ b/src/UnitTests/AcceptanceTests/Features/files/file-upload-withCustomMessageType.feature @@ -0,0 +1,22 @@ +@featureSet=files @beta + Feature: Send a file to Space + As a PubNub user I want to send a file with custom message type. + Client should be able to pass optional custom message type to the File endpoint. + + Background: + Given the demo keyset + + @contract=sendFileWithType + Scenario: Send a file success + When I send a file with 'test_message_type' customMessageType + Then I receive a successful response +# + @contract=sendFileWithTooShortType + Scenario: Send a file fails when message type is too short, shorten than 3 characters + When I send a file with 'ts' customMessageType + Then I receive an error response +# + @contract=sendFileWithTooLongType + Scenario: Send a file fails when message type is too long, longer than 50 characters + When I send a file with 'this-is-really-long-message-type-to-be-used-with-publish' customMessageType + Then I receive an error response \ No newline at end of file diff --git a/src/UnitTests/AcceptanceTests/Features/files/file-upload-withCustomMessageType.feature.cs b/src/UnitTests/AcceptanceTests/Features/files/file-upload-withCustomMessageType.feature.cs new file mode 100644 index 000000000..bb0cb1c14 --- /dev/null +++ b/src/UnitTests/AcceptanceTests/Features/files/file-upload-withCustomMessageType.feature.cs @@ -0,0 +1,189 @@ +// ------------------------------------------------------------------------------ +// +// This code was generated by SpecFlow (https://www.specflow.org/). +// SpecFlow Version:3.9.0.0 +// SpecFlow Generator Version:3.9.0.0 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ +#region Designer generated code +#pragma warning disable +namespace AcceptanceTests.Features.Files +{ + using TechTalk.SpecFlow; + using System; + using System.Linq; + + + [System.CodeDom.Compiler.GeneratedCodeAttribute("TechTalk.SpecFlow", "3.9.0.0")] + [System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [NUnit.Framework.TestFixtureAttribute()] + [NUnit.Framework.DescriptionAttribute("Send a file to Space")] + [NUnit.Framework.CategoryAttribute("featureSet=files")] + [NUnit.Framework.CategoryAttribute("beta")] + public partial class SendAFileToSpaceFeature + { + + private TechTalk.SpecFlow.ITestRunner testRunner; + + private static string[] featureTags = new string[] { + "featureSet=files", + "beta"}; + +#line 1 "file-upload-withCustomMessageType.feature" +#line hidden + + [NUnit.Framework.OneTimeSetUpAttribute()] + public virtual void FeatureSetup() + { + testRunner = TechTalk.SpecFlow.TestRunnerManager.GetTestRunner(); + TechTalk.SpecFlow.FeatureInfo featureInfo = new TechTalk.SpecFlow.FeatureInfo(new System.Globalization.CultureInfo("en-US"), "Features/files", "Send a file to Space", " As a PubNub user I want to send a file with custom message type.\n Client s" + + "hould be able to pass optional custom message type to the File endpoint.", ProgrammingLanguage.CSharp, featureTags); + testRunner.OnFeatureStart(featureInfo); + } + + [NUnit.Framework.OneTimeTearDownAttribute()] + public virtual void FeatureTearDown() + { + testRunner.OnFeatureEnd(); + testRunner = null; + } + + [NUnit.Framework.SetUpAttribute()] + public void TestInitialize() + { + } + + [NUnit.Framework.TearDownAttribute()] + public void TestTearDown() + { + testRunner.OnScenarioEnd(); + } + + public void ScenarioInitialize(TechTalk.SpecFlow.ScenarioInfo scenarioInfo) + { + testRunner.OnScenarioInitialize(scenarioInfo); + testRunner.ScenarioContext.ScenarioContainer.RegisterInstanceAs(NUnit.Framework.TestContext.CurrentContext); + } + + public void ScenarioStart() + { + testRunner.OnScenarioStart(); + } + + public void ScenarioCleanup() + { + testRunner.CollectScenarioErrors(); + } + + public virtual void FeatureBackground() + { +#line 6 + #line hidden +#line 7 + testRunner.Given("the demo keyset", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Given "); +#line hidden + } + + [NUnit.Framework.TestAttribute()] + [NUnit.Framework.DescriptionAttribute("Send a file success")] + [NUnit.Framework.CategoryAttribute("contract=sendFileWithType")] + public void SendAFileSuccess() + { + string[] tagsOfScenario = new string[] { + "contract=sendFileWithType"}; + System.Collections.Specialized.OrderedDictionary argumentsOfScenario = new System.Collections.Specialized.OrderedDictionary(); + TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Send a file success", null, tagsOfScenario, argumentsOfScenario, featureTags); +#line 10 + this.ScenarioInitialize(scenarioInfo); +#line hidden + if ((TagHelper.ContainsIgnoreTag(tagsOfScenario) || TagHelper.ContainsIgnoreTag(featureTags))) + { + testRunner.SkipScenario(); + } + else + { + this.ScenarioStart(); +#line 6 + this.FeatureBackground(); +#line hidden +#line 11 + testRunner.When("I send a file with \'test_message_type\' customMessageType", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); +#line hidden +#line 12 + testRunner.Then("I receive a successful response", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); +#line hidden + } + this.ScenarioCleanup(); + } + + [NUnit.Framework.TestAttribute()] + [NUnit.Framework.DescriptionAttribute("Send a file fails when message type is too short, shorten than 3 characters")] + [NUnit.Framework.CategoryAttribute("contract=sendFileWithTooShortType")] + public void SendAFileFailsWhenMessageTypeIsTooShortShortenThan3Characters() + { + string[] tagsOfScenario = new string[] { + "contract=sendFileWithTooShortType"}; + System.Collections.Specialized.OrderedDictionary argumentsOfScenario = new System.Collections.Specialized.OrderedDictionary(); + TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Send a file fails when message type is too short, shorten than 3 characters", null, tagsOfScenario, argumentsOfScenario, featureTags); +#line 15 + this.ScenarioInitialize(scenarioInfo); +#line hidden + if ((TagHelper.ContainsIgnoreTag(tagsOfScenario) || TagHelper.ContainsIgnoreTag(featureTags))) + { + testRunner.SkipScenario(); + } + else + { + this.ScenarioStart(); +#line 6 + this.FeatureBackground(); +#line hidden +#line 16 + testRunner.When("I send a file with \'ts\' customMessageType", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); +#line hidden +#line 17 + testRunner.Then("I receive an error response", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); +#line hidden + } + this.ScenarioCleanup(); + } + + [NUnit.Framework.TestAttribute()] + [NUnit.Framework.DescriptionAttribute("Send a file fails when message type is too long, longer than 50 characters")] + [NUnit.Framework.CategoryAttribute("contract=sendFileWithTooLongType")] + public void SendAFileFailsWhenMessageTypeIsTooLongLongerThan50Characters() + { + string[] tagsOfScenario = new string[] { + "contract=sendFileWithTooLongType"}; + System.Collections.Specialized.OrderedDictionary argumentsOfScenario = new System.Collections.Specialized.OrderedDictionary(); + TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Send a file fails when message type is too long, longer than 50 characters", null, tagsOfScenario, argumentsOfScenario, featureTags); +#line 20 + this.ScenarioInitialize(scenarioInfo); +#line hidden + if ((TagHelper.ContainsIgnoreTag(tagsOfScenario) || TagHelper.ContainsIgnoreTag(featureTags))) + { + testRunner.SkipScenario(); + } + else + { + this.ScenarioStart(); +#line 6 + this.FeatureBackground(); +#line hidden +#line 21 + testRunner.When("I send a file with \'this-is-really-long-message-type-to-be-used-with-publish\' cus" + + "tomMessageType", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); +#line hidden +#line 22 + testRunner.Then("I receive an error response", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); +#line hidden + } + this.ScenarioCleanup(); + } + } +} +#pragma warning restore +#endregion diff --git a/src/UnitTests/AcceptanceTests/Features/history/history-custom-mssg-type.feature b/src/UnitTests/AcceptanceTests/Features/history/history-custom-mssg-type.feature new file mode 100644 index 000000000..d36954f04 --- /dev/null +++ b/src/UnitTests/AcceptanceTests/Features/history/history-custom-mssg-type.feature @@ -0,0 +1,25 @@ +@featureSet=historyCustomMssgType @beta +Feature: History for VSP + As a PubNub user I want to fetch history with message type. + Client should be able to opt-out default `includeType`. + + Background: + Given the demo keyset with enabled storage + + @contract=fetchHistoryWithPubNubMessageTypes + Scenario: Client can fetch history with message types + When I fetch message history with messageType for 'simple-channel' channel + Then I receive a successful response + And history response contains messages with '0' and '4' message types + + @contract=fetchHistoryWithUserAndPubNubTypes + Scenario: Client can fetch history with customMessageType + When I fetch message history with customMessageType for 'some-channel' channel + Then I receive a successful response + And history response contains messages with 'custom-message-type' and 'user-custom-message-type' types + + @contract=fetchHistoryWithoutCustomMessageType + Scenario: Client can fetch history without customMessageType enabled by default + When I fetch message history with 'include_custom_message_type' set to 'false' for 'some-channel' channel + Then I receive a successful response + And history response contains messages without customMessageType diff --git a/src/UnitTests/AcceptanceTests/Features/history/history-custom-mssg-type.feature.cs b/src/UnitTests/AcceptanceTests/Features/history/history-custom-mssg-type.feature.cs new file mode 100644 index 000000000..48bc6c227 --- /dev/null +++ b/src/UnitTests/AcceptanceTests/Features/history/history-custom-mssg-type.feature.cs @@ -0,0 +1,199 @@ +// ------------------------------------------------------------------------------ +// +// This code was generated by SpecFlow (https://www.specflow.org/). +// SpecFlow Version:3.9.0.0 +// SpecFlow Generator Version:3.9.0.0 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ +#region Designer generated code +#pragma warning disable +namespace AcceptanceTests.Features.History +{ + using TechTalk.SpecFlow; + using System; + using System.Linq; + + + [System.CodeDom.Compiler.GeneratedCodeAttribute("TechTalk.SpecFlow", "3.9.0.0")] + [System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [NUnit.Framework.TestFixtureAttribute()] + [NUnit.Framework.DescriptionAttribute("History for VSP")] + [NUnit.Framework.CategoryAttribute("featureSet=historyCustomMssgType")] + [NUnit.Framework.CategoryAttribute("beta")] + public partial class HistoryForVSPFeature + { + + private TechTalk.SpecFlow.ITestRunner testRunner; + + private static string[] featureTags = new string[] { + "featureSet=historyCustomMssgType", + "beta"}; + +#line 1 "history-custom-mssg-type.feature" +#line hidden + + [NUnit.Framework.OneTimeSetUpAttribute()] + public virtual void FeatureSetup() + { + testRunner = TechTalk.SpecFlow.TestRunnerManager.GetTestRunner(); + TechTalk.SpecFlow.FeatureInfo featureInfo = new TechTalk.SpecFlow.FeatureInfo(new System.Globalization.CultureInfo("en-US"), "Features/history", "History for VSP", " As a PubNub user I want to fetch history with message type.\n Client should be " + + "able to opt-out default `includeType`.", ProgrammingLanguage.CSharp, featureTags); + testRunner.OnFeatureStart(featureInfo); + } + + [NUnit.Framework.OneTimeTearDownAttribute()] + public virtual void FeatureTearDown() + { + testRunner.OnFeatureEnd(); + testRunner = null; + } + + [NUnit.Framework.SetUpAttribute()] + public void TestInitialize() + { + } + + [NUnit.Framework.TearDownAttribute()] + public void TestTearDown() + { + testRunner.OnScenarioEnd(); + } + + public void ScenarioInitialize(TechTalk.SpecFlow.ScenarioInfo scenarioInfo) + { + testRunner.OnScenarioInitialize(scenarioInfo); + testRunner.ScenarioContext.ScenarioContainer.RegisterInstanceAs(NUnit.Framework.TestContext.CurrentContext); + } + + public void ScenarioStart() + { + testRunner.OnScenarioStart(); + } + + public void ScenarioCleanup() + { + testRunner.CollectScenarioErrors(); + } + + public virtual void FeatureBackground() + { +#line 6 + #line hidden +#line 7 + testRunner.Given("the demo keyset with enabled storage", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Given "); +#line hidden + } + + [NUnit.Framework.TestAttribute()] + [NUnit.Framework.DescriptionAttribute("Client can fetch history with message types")] + [NUnit.Framework.CategoryAttribute("contract=fetchHistoryWithPubNubMessageTypes")] + public void ClientCanFetchHistoryWithMessageTypes() + { + string[] tagsOfScenario = new string[] { + "contract=fetchHistoryWithPubNubMessageTypes"}; + System.Collections.Specialized.OrderedDictionary argumentsOfScenario = new System.Collections.Specialized.OrderedDictionary(); + TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Client can fetch history with message types", null, tagsOfScenario, argumentsOfScenario, featureTags); +#line 10 + this.ScenarioInitialize(scenarioInfo); +#line hidden + if ((TagHelper.ContainsIgnoreTag(tagsOfScenario) || TagHelper.ContainsIgnoreTag(featureTags))) + { + testRunner.SkipScenario(); + } + else + { + this.ScenarioStart(); +#line 6 + this.FeatureBackground(); +#line hidden +#line 11 + testRunner.When("I fetch message history with messageType for \'simple-channel\' channel", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); +#line hidden +#line 12 + testRunner.Then("I receive a successful response", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); +#line hidden +#line 13 + testRunner.And("history response contains messages with \'0\' and \'4\' message types", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); +#line hidden + } + this.ScenarioCleanup(); + } + + [NUnit.Framework.TestAttribute()] + [NUnit.Framework.DescriptionAttribute("Client can fetch history with customMessageType")] + [NUnit.Framework.CategoryAttribute("contract=fetchHistoryWithUserAndPubNubTypes")] + public void ClientCanFetchHistoryWithCustomMessageType() + { + string[] tagsOfScenario = new string[] { + "contract=fetchHistoryWithUserAndPubNubTypes"}; + System.Collections.Specialized.OrderedDictionary argumentsOfScenario = new System.Collections.Specialized.OrderedDictionary(); + TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Client can fetch history with customMessageType", null, tagsOfScenario, argumentsOfScenario, featureTags); +#line 16 + this.ScenarioInitialize(scenarioInfo); +#line hidden + if ((TagHelper.ContainsIgnoreTag(tagsOfScenario) || TagHelper.ContainsIgnoreTag(featureTags))) + { + testRunner.SkipScenario(); + } + else + { + this.ScenarioStart(); +#line 6 + this.FeatureBackground(); +#line hidden +#line 17 + testRunner.When("I fetch message history with customMessageType for \'some-channel\' channel", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); +#line hidden +#line 18 + testRunner.Then("I receive a successful response", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); +#line hidden +#line 19 + testRunner.And("history response contains messages with \'custom-message-type\' and \'user-custom-me" + + "ssage-type\' types", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); +#line hidden + } + this.ScenarioCleanup(); + } + + [NUnit.Framework.TestAttribute()] + [NUnit.Framework.DescriptionAttribute("Client can fetch history without customMessageType enabled by default")] + [NUnit.Framework.CategoryAttribute("contract=fetchHistoryWithoutCustomMessageType")] + public void ClientCanFetchHistoryWithoutCustomMessageTypeEnabledByDefault() + { + string[] tagsOfScenario = new string[] { + "contract=fetchHistoryWithoutCustomMessageType"}; + System.Collections.Specialized.OrderedDictionary argumentsOfScenario = new System.Collections.Specialized.OrderedDictionary(); + TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Client can fetch history without customMessageType enabled by default", null, tagsOfScenario, argumentsOfScenario, featureTags); +#line 22 + this.ScenarioInitialize(scenarioInfo); +#line hidden + if ((TagHelper.ContainsIgnoreTag(tagsOfScenario) || TagHelper.ContainsIgnoreTag(featureTags))) + { + testRunner.SkipScenario(); + } + else + { + this.ScenarioStart(); +#line 6 + this.FeatureBackground(); +#line hidden +#line 23 + testRunner.When("I fetch message history with \'include_custom_message_type\' set to \'false\' for \'so" + + "me-channel\' channel", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); +#line hidden +#line 24 + testRunner.Then("I receive a successful response", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); +#line hidden +#line 25 + testRunner.And("history response contains messages without customMessageType", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); +#line hidden + } + this.ScenarioCleanup(); + } + } +} +#pragma warning restore +#endregion diff --git a/src/UnitTests/AcceptanceTests/Features/publish/publish-custom-mssg-type.feature b/src/UnitTests/AcceptanceTests/Features/publish/publish-custom-mssg-type.feature new file mode 100644 index 000000000..ca828e128 --- /dev/null +++ b/src/UnitTests/AcceptanceTests/Features/publish/publish-custom-mssg-type.feature @@ -0,0 +1,47 @@ +@featureSet=publishWithCustomMssgType @beta +Feature: Publish to Space + As a PubNub user I want to publish messages to Space with type. + Client should be able to pass optional custom message type to publish endpoint. + + Background: + Given the demo keyset + + @contract=publishWithType + Scenario: Publish message success + When I publish message with 'test_step' customMessageType + Then I receive a successful response + + @contract=publishWithTooShortType + Scenario: Publish message fails when type is too short + When I publish message with 'ts' customMessageType + Then I receive an error response + + @contract=publishWithTooLongType + Scenario: Publish message fails when type is too long + When I publish message with 'this-is-really-long-message-type-to-be-used-with-publish' customMessageType + Then I receive an error response + + @contract=publishWithTypeStartingWithReservedStrings + Scenario: Publish message fails when type starts with reserved 'pn-' (hyphen) string + When I publish message with 'pn-test-step' customMessageType + Then I receive an error response + + @contract=publishWithTypeStartingWithReservedStrings + Scenario: Publish message fails when type starts with reserved 'pn_' (underscore) string + When I publish message with 'pn_test-step' customMessageType + Then I receive an error response + + @contract=publishWithTypeStartingWithNotAllowedCharacter + Scenario: Publish message fails when type starts with not allowed '-' (hyphen) character + When I publish message with '-test-step' customMessageType + Then I receive an error response + + @contract=publishWithTypeStartingWithNotAllowedCharacter + Scenario: Publish message fails when type starts with not allowed '_' (underscore) character + When I publish message with '_test-step' customMessageType + Then I receive an error response + + @contract=publishWithTypeContainingNotAllowedCharacter + Scenario: Publish message fails when type contains not allowed characters + When I publish message with 'test:step' customMessageType + Then I receive an error response diff --git a/src/UnitTests/AcceptanceTests/Features/publish/publish-custom-mssg-type.feature.cs b/src/UnitTests/AcceptanceTests/Features/publish/publish-custom-mssg-type.feature.cs new file mode 100644 index 000000000..c708b0c3a --- /dev/null +++ b/src/UnitTests/AcceptanceTests/Features/publish/publish-custom-mssg-type.feature.cs @@ -0,0 +1,351 @@ +// ------------------------------------------------------------------------------ +// +// This code was generated by SpecFlow (https://www.specflow.org/). +// SpecFlow Version:3.9.0.0 +// SpecFlow Generator Version:3.9.0.0 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ +#region Designer generated code +#pragma warning disable +namespace AcceptanceTests.Features.Publish +{ + using TechTalk.SpecFlow; + using System; + using System.Linq; + + + [System.CodeDom.Compiler.GeneratedCodeAttribute("TechTalk.SpecFlow", "3.9.0.0")] + [System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [NUnit.Framework.TestFixtureAttribute()] + [NUnit.Framework.DescriptionAttribute("Publish to Space")] + [NUnit.Framework.CategoryAttribute("featureSet=publishWithCustomMssgType")] + [NUnit.Framework.CategoryAttribute("beta")] + public partial class PublishToSpaceFeature + { + + private TechTalk.SpecFlow.ITestRunner testRunner; + + private static string[] featureTags = new string[] { + "featureSet=publishWithCustomMssgType", + "beta"}; + +#line 1 "publish-custom-mssg-type.feature" +#line hidden + + [NUnit.Framework.OneTimeSetUpAttribute()] + public virtual void FeatureSetup() + { + testRunner = TechTalk.SpecFlow.TestRunnerManager.GetTestRunner(); + TechTalk.SpecFlow.FeatureInfo featureInfo = new TechTalk.SpecFlow.FeatureInfo(new System.Globalization.CultureInfo("en-US"), "Features/publish", "Publish to Space", " As a PubNub user I want to publish messages to Space with type.\n Client should" + + " be able to pass optional custom message type to publish endpoint.", ProgrammingLanguage.CSharp, featureTags); + testRunner.OnFeatureStart(featureInfo); + } + + [NUnit.Framework.OneTimeTearDownAttribute()] + public virtual void FeatureTearDown() + { + testRunner.OnFeatureEnd(); + testRunner = null; + } + + [NUnit.Framework.SetUpAttribute()] + public void TestInitialize() + { + } + + [NUnit.Framework.TearDownAttribute()] + public void TestTearDown() + { + testRunner.OnScenarioEnd(); + } + + public void ScenarioInitialize(TechTalk.SpecFlow.ScenarioInfo scenarioInfo) + { + testRunner.OnScenarioInitialize(scenarioInfo); + testRunner.ScenarioContext.ScenarioContainer.RegisterInstanceAs(NUnit.Framework.TestContext.CurrentContext); + } + + public void ScenarioStart() + { + testRunner.OnScenarioStart(); + } + + public void ScenarioCleanup() + { + testRunner.CollectScenarioErrors(); + } + + public virtual void FeatureBackground() + { +#line 6 + #line hidden +#line 7 + testRunner.Given("the demo keyset", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Given "); +#line hidden + } + + [NUnit.Framework.TestAttribute()] + [NUnit.Framework.DescriptionAttribute("Publish message success")] + [NUnit.Framework.CategoryAttribute("contract=publishWithType")] + public void PublishMessageSuccess() + { + string[] tagsOfScenario = new string[] { + "contract=publishWithType"}; + System.Collections.Specialized.OrderedDictionary argumentsOfScenario = new System.Collections.Specialized.OrderedDictionary(); + TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Publish message success", null, tagsOfScenario, argumentsOfScenario, featureTags); +#line 10 + this.ScenarioInitialize(scenarioInfo); +#line hidden + if ((TagHelper.ContainsIgnoreTag(tagsOfScenario) || TagHelper.ContainsIgnoreTag(featureTags))) + { + testRunner.SkipScenario(); + } + else + { + this.ScenarioStart(); +#line 6 + this.FeatureBackground(); +#line hidden +#line 11 + testRunner.When("I publish message with \'test_step\' customMessageType", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); +#line hidden +#line 12 + testRunner.Then("I receive a successful response", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); +#line hidden + } + this.ScenarioCleanup(); + } + + [NUnit.Framework.TestAttribute()] + [NUnit.Framework.DescriptionAttribute("Publish message fails when type is too short")] + [NUnit.Framework.CategoryAttribute("contract=publishWithTooShortType")] + public void PublishMessageFailsWhenTypeIsTooShort() + { + string[] tagsOfScenario = new string[] { + "contract=publishWithTooShortType"}; + System.Collections.Specialized.OrderedDictionary argumentsOfScenario = new System.Collections.Specialized.OrderedDictionary(); + TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Publish message fails when type is too short", null, tagsOfScenario, argumentsOfScenario, featureTags); +#line 15 + this.ScenarioInitialize(scenarioInfo); +#line hidden + if ((TagHelper.ContainsIgnoreTag(tagsOfScenario) || TagHelper.ContainsIgnoreTag(featureTags))) + { + testRunner.SkipScenario(); + } + else + { + this.ScenarioStart(); +#line 6 + this.FeatureBackground(); +#line hidden +#line 16 + testRunner.When("I publish message with \'ts\' customMessageType", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); +#line hidden +#line 17 + testRunner.Then("I receive an error response", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); +#line hidden + } + this.ScenarioCleanup(); + } + + [NUnit.Framework.TestAttribute()] + [NUnit.Framework.DescriptionAttribute("Publish message fails when type is too long")] + [NUnit.Framework.CategoryAttribute("contract=publishWithTooLongType")] + public void PublishMessageFailsWhenTypeIsTooLong() + { + string[] tagsOfScenario = new string[] { + "contract=publishWithTooLongType"}; + System.Collections.Specialized.OrderedDictionary argumentsOfScenario = new System.Collections.Specialized.OrderedDictionary(); + TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Publish message fails when type is too long", null, tagsOfScenario, argumentsOfScenario, featureTags); +#line 20 + this.ScenarioInitialize(scenarioInfo); +#line hidden + if ((TagHelper.ContainsIgnoreTag(tagsOfScenario) || TagHelper.ContainsIgnoreTag(featureTags))) + { + testRunner.SkipScenario(); + } + else + { + this.ScenarioStart(); +#line 6 + this.FeatureBackground(); +#line hidden +#line 21 + testRunner.When("I publish message with \'this-is-really-long-message-type-to-be-used-with-publish\'" + + " customMessageType", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); +#line hidden +#line 22 + testRunner.Then("I receive an error response", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); +#line hidden + } + this.ScenarioCleanup(); + } + + [NUnit.Framework.TestAttribute()] + [NUnit.Framework.DescriptionAttribute("Publish message fails when type starts with reserved \'pn-\' (hyphen) string")] + [NUnit.Framework.CategoryAttribute("contract=publishWithTypeStartingWithReservedStrings")] + public void PublishMessageFailsWhenTypeStartsWithReservedPn_HyphenString() + { + string[] tagsOfScenario = new string[] { + "contract=publishWithTypeStartingWithReservedStrings"}; + System.Collections.Specialized.OrderedDictionary argumentsOfScenario = new System.Collections.Specialized.OrderedDictionary(); + TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Publish message fails when type starts with reserved \'pn-\' (hyphen) string", null, tagsOfScenario, argumentsOfScenario, featureTags); +#line 25 + this.ScenarioInitialize(scenarioInfo); +#line hidden + if ((TagHelper.ContainsIgnoreTag(tagsOfScenario) || TagHelper.ContainsIgnoreTag(featureTags))) + { + testRunner.SkipScenario(); + } + else + { + this.ScenarioStart(); +#line 6 + this.FeatureBackground(); +#line hidden +#line 26 + testRunner.When("I publish message with \'pn-test-step\' customMessageType", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); +#line hidden +#line 27 + testRunner.Then("I receive an error response", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); +#line hidden + } + this.ScenarioCleanup(); + } + + [NUnit.Framework.TestAttribute()] + [NUnit.Framework.DescriptionAttribute("Publish message fails when type starts with reserved \'pn_\' (underscore) string")] + [NUnit.Framework.CategoryAttribute("contract=publishWithTypeStartingWithReservedStrings")] + public void PublishMessageFailsWhenTypeStartsWithReservedPn_UnderscoreString() + { + string[] tagsOfScenario = new string[] { + "contract=publishWithTypeStartingWithReservedStrings"}; + System.Collections.Specialized.OrderedDictionary argumentsOfScenario = new System.Collections.Specialized.OrderedDictionary(); + TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Publish message fails when type starts with reserved \'pn_\' (underscore) string", null, tagsOfScenario, argumentsOfScenario, featureTags); +#line 30 + this.ScenarioInitialize(scenarioInfo); +#line hidden + if ((TagHelper.ContainsIgnoreTag(tagsOfScenario) || TagHelper.ContainsIgnoreTag(featureTags))) + { + testRunner.SkipScenario(); + } + else + { + this.ScenarioStart(); +#line 6 + this.FeatureBackground(); +#line hidden +#line 31 + testRunner.When("I publish message with \'pn_test-step\' customMessageType", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); +#line hidden +#line 32 + testRunner.Then("I receive an error response", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); +#line hidden + } + this.ScenarioCleanup(); + } + + [NUnit.Framework.TestAttribute()] + [NUnit.Framework.DescriptionAttribute("Publish message fails when type starts with not allowed \'-\' (hyphen) character")] + [NUnit.Framework.CategoryAttribute("contract=publishWithTypeStartingWithNotAllowedCharacter")] + public void PublishMessageFailsWhenTypeStartsWithNotAllowed_HyphenCharacter() + { + string[] tagsOfScenario = new string[] { + "contract=publishWithTypeStartingWithNotAllowedCharacter"}; + System.Collections.Specialized.OrderedDictionary argumentsOfScenario = new System.Collections.Specialized.OrderedDictionary(); + TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Publish message fails when type starts with not allowed \'-\' (hyphen) character", null, tagsOfScenario, argumentsOfScenario, featureTags); +#line 35 + this.ScenarioInitialize(scenarioInfo); +#line hidden + if ((TagHelper.ContainsIgnoreTag(tagsOfScenario) || TagHelper.ContainsIgnoreTag(featureTags))) + { + testRunner.SkipScenario(); + } + else + { + this.ScenarioStart(); +#line 6 + this.FeatureBackground(); +#line hidden +#line 36 + testRunner.When("I publish message with \'-test-step\' customMessageType", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); +#line hidden +#line 37 + testRunner.Then("I receive an error response", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); +#line hidden + } + this.ScenarioCleanup(); + } + + [NUnit.Framework.TestAttribute()] + [NUnit.Framework.DescriptionAttribute("Publish message fails when type starts with not allowed \'_\' (underscore) characte" + + "r")] + [NUnit.Framework.CategoryAttribute("contract=publishWithTypeStartingWithNotAllowedCharacter")] + public void PublishMessageFailsWhenTypeStartsWithNotAllowed_UnderscoreCharacter() + { + string[] tagsOfScenario = new string[] { + "contract=publishWithTypeStartingWithNotAllowedCharacter"}; + System.Collections.Specialized.OrderedDictionary argumentsOfScenario = new System.Collections.Specialized.OrderedDictionary(); + TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Publish message fails when type starts with not allowed \'_\' (underscore) characte" + + "r", null, tagsOfScenario, argumentsOfScenario, featureTags); +#line 40 + this.ScenarioInitialize(scenarioInfo); +#line hidden + if ((TagHelper.ContainsIgnoreTag(tagsOfScenario) || TagHelper.ContainsIgnoreTag(featureTags))) + { + testRunner.SkipScenario(); + } + else + { + this.ScenarioStart(); +#line 6 + this.FeatureBackground(); +#line hidden +#line 41 + testRunner.When("I publish message with \'_test-step\' customMessageType", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); +#line hidden +#line 42 + testRunner.Then("I receive an error response", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); +#line hidden + } + this.ScenarioCleanup(); + } + + [NUnit.Framework.TestAttribute()] + [NUnit.Framework.DescriptionAttribute("Publish message fails when type contains not allowed characters")] + [NUnit.Framework.CategoryAttribute("contract=publishWithTypeContainingNotAllowedCharacter")] + public void PublishMessageFailsWhenTypeContainsNotAllowedCharacters() + { + string[] tagsOfScenario = new string[] { + "contract=publishWithTypeContainingNotAllowedCharacter"}; + System.Collections.Specialized.OrderedDictionary argumentsOfScenario = new System.Collections.Specialized.OrderedDictionary(); + TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Publish message fails when type contains not allowed characters", null, tagsOfScenario, argumentsOfScenario, featureTags); +#line 45 + this.ScenarioInitialize(scenarioInfo); +#line hidden + if ((TagHelper.ContainsIgnoreTag(tagsOfScenario) || TagHelper.ContainsIgnoreTag(featureTags))) + { + testRunner.SkipScenario(); + } + else + { + this.ScenarioStart(); +#line 6 + this.FeatureBackground(); +#line hidden +#line 46 + testRunner.When("I publish message with \'test:step\' customMessageType", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); +#line hidden +#line 47 + testRunner.Then("I receive an error response", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); +#line hidden + } + this.ScenarioCleanup(); + } + } +} +#pragma warning restore +#endregion diff --git a/src/UnitTests/AcceptanceTests/Features/publish/signal-custom-mssg-type.feature b/src/UnitTests/AcceptanceTests/Features/publish/signal-custom-mssg-type.feature new file mode 100644 index 000000000..7162f526d --- /dev/null +++ b/src/UnitTests/AcceptanceTests/Features/publish/signal-custom-mssg-type.feature @@ -0,0 +1,47 @@ +@featureSet=signalWithCustomMssgType @beta +Feature: Send a signal to Space + As a PubNub user I want to send some signals to Space with type. + Client should be able to pass optional custom message type to the signal endpoint. + + Background: + Given the demo keyset + + @contract=signalWithType + Scenario: Send a signal success + When I send a signal with 'test_message_type' customMessageType + Then I receive a successful response + + @contract=signalWithTooShortType + Scenario: Send a signal fails when type is too short + When I send a signal with 'ts' customMessageType + Then I receive an error response + + @contract=signalWithTooLongType + Scenario: Send a signal fails when type is too long + When I send a signal with 'this-is-really-long-message-type-to-be-used-with-publish' customMessageType + Then I receive an error response + + @contract=signalWithTypeStartingWithReservedStrings + Scenario: Send a signal fails when type starts with reserved 'pn-' (hyphen) string + When I send a signal with 'pn-test_message_type' customMessageType + Then I receive an error response + + @contract=signalWithTypeStartingWithReservedStrings + Scenario: Send a signal fails when type starts with reserved 'pn_' (underscore) string + When I send a signal with 'pn_test_message_type' customMessageType + Then I receive an error response + + @contract=signalWithTypeStartingWithNotAllowedCharacter + Scenario: Send a signal fails when type starts with not allowed '-' (hyphen) character + When I send a signal with '-test_message_type' customMessageType + Then I receive an error response + + @contract=signalWithTypeStartingWithNotAllowedCharacter + Scenario: Send a signal fails when type starts with not allowed '_' (underscore) character + When I send a signal with '_test_message_type' customMessageType + Then I receive an error response + + @contract=signalWithTypeContainingNotAllowedCharacter + Scenario: Send a signal fails when type contains not allowed characters + When I send a signal with 'test:message_type' customMessageType + Then I receive an error response diff --git a/src/UnitTests/AcceptanceTests/Features/publish/signal-custom-mssg-type.feature.cs b/src/UnitTests/AcceptanceTests/Features/publish/signal-custom-mssg-type.feature.cs new file mode 100644 index 000000000..85bc47af8 --- /dev/null +++ b/src/UnitTests/AcceptanceTests/Features/publish/signal-custom-mssg-type.feature.cs @@ -0,0 +1,349 @@ +// ------------------------------------------------------------------------------ +// +// This code was generated by SpecFlow (https://www.specflow.org/). +// SpecFlow Version:3.9.0.0 +// SpecFlow Generator Version:3.9.0.0 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ +#region Designer generated code +#pragma warning disable +namespace AcceptanceTests.Features.Publish +{ + using TechTalk.SpecFlow; + using System; + using System.Linq; + + + [System.CodeDom.Compiler.GeneratedCodeAttribute("TechTalk.SpecFlow", "3.9.0.0")] + [System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [NUnit.Framework.TestFixtureAttribute()] + [NUnit.Framework.DescriptionAttribute("Send a signal to Space")] + [NUnit.Framework.CategoryAttribute("featureSet=signalWithCustomMssgType")] + [NUnit.Framework.CategoryAttribute("beta")] + public partial class SendASignalToSpaceFeature + { + + private TechTalk.SpecFlow.ITestRunner testRunner; + + private static string[] featureTags = new string[] { + "featureSet=signalWithCustomMssgType", + "beta"}; + +#line 1 "signal-custom-mssg-type.feature" +#line hidden + + [NUnit.Framework.OneTimeSetUpAttribute()] + public virtual void FeatureSetup() + { + testRunner = TechTalk.SpecFlow.TestRunnerManager.GetTestRunner(); + TechTalk.SpecFlow.FeatureInfo featureInfo = new TechTalk.SpecFlow.FeatureInfo(new System.Globalization.CultureInfo("en-US"), "Features/publish", "Send a signal to Space", " As a PubNub user I want to send some signals to Space with type.\n Client shoul" + + "d be able to pass optional custom message type to the signal endpoint.", ProgrammingLanguage.CSharp, featureTags); + testRunner.OnFeatureStart(featureInfo); + } + + [NUnit.Framework.OneTimeTearDownAttribute()] + public virtual void FeatureTearDown() + { + testRunner.OnFeatureEnd(); + testRunner = null; + } + + [NUnit.Framework.SetUpAttribute()] + public void TestInitialize() + { + } + + [NUnit.Framework.TearDownAttribute()] + public void TestTearDown() + { + testRunner.OnScenarioEnd(); + } + + public void ScenarioInitialize(TechTalk.SpecFlow.ScenarioInfo scenarioInfo) + { + testRunner.OnScenarioInitialize(scenarioInfo); + testRunner.ScenarioContext.ScenarioContainer.RegisterInstanceAs(NUnit.Framework.TestContext.CurrentContext); + } + + public void ScenarioStart() + { + testRunner.OnScenarioStart(); + } + + public void ScenarioCleanup() + { + testRunner.CollectScenarioErrors(); + } + + public virtual void FeatureBackground() + { +#line 6 + #line hidden +#line 7 + testRunner.Given("the demo keyset", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Given "); +#line hidden + } + + [NUnit.Framework.TestAttribute()] + [NUnit.Framework.DescriptionAttribute("Send a signal success")] + [NUnit.Framework.CategoryAttribute("contract=signalWithType")] + public void SendASignalSuccess() + { + string[] tagsOfScenario = new string[] { + "contract=signalWithType"}; + System.Collections.Specialized.OrderedDictionary argumentsOfScenario = new System.Collections.Specialized.OrderedDictionary(); + TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Send a signal success", null, tagsOfScenario, argumentsOfScenario, featureTags); +#line 10 + this.ScenarioInitialize(scenarioInfo); +#line hidden + if ((TagHelper.ContainsIgnoreTag(tagsOfScenario) || TagHelper.ContainsIgnoreTag(featureTags))) + { + testRunner.SkipScenario(); + } + else + { + this.ScenarioStart(); +#line 6 + this.FeatureBackground(); +#line hidden +#line 11 + testRunner.When("I send a signal with \'test_message_type\' customMessageType", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); +#line hidden +#line 12 + testRunner.Then("I receive a successful response", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); +#line hidden + } + this.ScenarioCleanup(); + } + + [NUnit.Framework.TestAttribute()] + [NUnit.Framework.DescriptionAttribute("Send a signal fails when type is too short")] + [NUnit.Framework.CategoryAttribute("contract=signalWithTooShortType")] + public void SendASignalFailsWhenTypeIsTooShort() + { + string[] tagsOfScenario = new string[] { + "contract=signalWithTooShortType"}; + System.Collections.Specialized.OrderedDictionary argumentsOfScenario = new System.Collections.Specialized.OrderedDictionary(); + TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Send a signal fails when type is too short", null, tagsOfScenario, argumentsOfScenario, featureTags); +#line 15 + this.ScenarioInitialize(scenarioInfo); +#line hidden + if ((TagHelper.ContainsIgnoreTag(tagsOfScenario) || TagHelper.ContainsIgnoreTag(featureTags))) + { + testRunner.SkipScenario(); + } + else + { + this.ScenarioStart(); +#line 6 + this.FeatureBackground(); +#line hidden +#line 16 + testRunner.When("I send a signal with \'ts\' customMessageType", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); +#line hidden +#line 17 + testRunner.Then("I receive an error response", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); +#line hidden + } + this.ScenarioCleanup(); + } + + [NUnit.Framework.TestAttribute()] + [NUnit.Framework.DescriptionAttribute("Send a signal fails when type is too long")] + [NUnit.Framework.CategoryAttribute("contract=signalWithTooLongType")] + public void SendASignalFailsWhenTypeIsTooLong() + { + string[] tagsOfScenario = new string[] { + "contract=signalWithTooLongType"}; + System.Collections.Specialized.OrderedDictionary argumentsOfScenario = new System.Collections.Specialized.OrderedDictionary(); + TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Send a signal fails when type is too long", null, tagsOfScenario, argumentsOfScenario, featureTags); +#line 20 + this.ScenarioInitialize(scenarioInfo); +#line hidden + if ((TagHelper.ContainsIgnoreTag(tagsOfScenario) || TagHelper.ContainsIgnoreTag(featureTags))) + { + testRunner.SkipScenario(); + } + else + { + this.ScenarioStart(); +#line 6 + this.FeatureBackground(); +#line hidden +#line 21 + testRunner.When("I send a signal with \'this-is-really-long-message-type-to-be-used-with-publish\' c" + + "ustomMessageType", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); +#line hidden +#line 22 + testRunner.Then("I receive an error response", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); +#line hidden + } + this.ScenarioCleanup(); + } + + [NUnit.Framework.TestAttribute()] + [NUnit.Framework.DescriptionAttribute("Send a signal fails when type starts with reserved \'pn-\' (hyphen) string")] + [NUnit.Framework.CategoryAttribute("contract=signalWithTypeStartingWithReservedStrings")] + public void SendASignalFailsWhenTypeStartsWithReservedPn_HyphenString() + { + string[] tagsOfScenario = new string[] { + "contract=signalWithTypeStartingWithReservedStrings"}; + System.Collections.Specialized.OrderedDictionary argumentsOfScenario = new System.Collections.Specialized.OrderedDictionary(); + TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Send a signal fails when type starts with reserved \'pn-\' (hyphen) string", null, tagsOfScenario, argumentsOfScenario, featureTags); +#line 25 + this.ScenarioInitialize(scenarioInfo); +#line hidden + if ((TagHelper.ContainsIgnoreTag(tagsOfScenario) || TagHelper.ContainsIgnoreTag(featureTags))) + { + testRunner.SkipScenario(); + } + else + { + this.ScenarioStart(); +#line 6 + this.FeatureBackground(); +#line hidden +#line 26 + testRunner.When("I send a signal with \'pn-test_message_type\' customMessageType", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); +#line hidden +#line 27 + testRunner.Then("I receive an error response", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); +#line hidden + } + this.ScenarioCleanup(); + } + + [NUnit.Framework.TestAttribute()] + [NUnit.Framework.DescriptionAttribute("Send a signal fails when type starts with reserved \'pn_\' (underscore) string")] + [NUnit.Framework.CategoryAttribute("contract=signalWithTypeStartingWithReservedStrings")] + public void SendASignalFailsWhenTypeStartsWithReservedPn_UnderscoreString() + { + string[] tagsOfScenario = new string[] { + "contract=signalWithTypeStartingWithReservedStrings"}; + System.Collections.Specialized.OrderedDictionary argumentsOfScenario = new System.Collections.Specialized.OrderedDictionary(); + TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Send a signal fails when type starts with reserved \'pn_\' (underscore) string", null, tagsOfScenario, argumentsOfScenario, featureTags); +#line 30 + this.ScenarioInitialize(scenarioInfo); +#line hidden + if ((TagHelper.ContainsIgnoreTag(tagsOfScenario) || TagHelper.ContainsIgnoreTag(featureTags))) + { + testRunner.SkipScenario(); + } + else + { + this.ScenarioStart(); +#line 6 + this.FeatureBackground(); +#line hidden +#line 31 + testRunner.When("I send a signal with \'pn_test_message_type\' customMessageType", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); +#line hidden +#line 32 + testRunner.Then("I receive an error response", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); +#line hidden + } + this.ScenarioCleanup(); + } + + [NUnit.Framework.TestAttribute()] + [NUnit.Framework.DescriptionAttribute("Send a signal fails when type starts with not allowed \'-\' (hyphen) character")] + [NUnit.Framework.CategoryAttribute("contract=signalWithTypeStartingWithNotAllowedCharacter")] + public void SendASignalFailsWhenTypeStartsWithNotAllowed_HyphenCharacter() + { + string[] tagsOfScenario = new string[] { + "contract=signalWithTypeStartingWithNotAllowedCharacter"}; + System.Collections.Specialized.OrderedDictionary argumentsOfScenario = new System.Collections.Specialized.OrderedDictionary(); + TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Send a signal fails when type starts with not allowed \'-\' (hyphen) character", null, tagsOfScenario, argumentsOfScenario, featureTags); +#line 35 + this.ScenarioInitialize(scenarioInfo); +#line hidden + if ((TagHelper.ContainsIgnoreTag(tagsOfScenario) || TagHelper.ContainsIgnoreTag(featureTags))) + { + testRunner.SkipScenario(); + } + else + { + this.ScenarioStart(); +#line 6 + this.FeatureBackground(); +#line hidden +#line 36 + testRunner.When("I send a signal with \'-test_message_type\' customMessageType", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); +#line hidden +#line 37 + testRunner.Then("I receive an error response", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); +#line hidden + } + this.ScenarioCleanup(); + } + + [NUnit.Framework.TestAttribute()] + [NUnit.Framework.DescriptionAttribute("Send a signal fails when type starts with not allowed \'_\' (underscore) character")] + [NUnit.Framework.CategoryAttribute("contract=signalWithTypeStartingWithNotAllowedCharacter")] + public void SendASignalFailsWhenTypeStartsWithNotAllowed_UnderscoreCharacter() + { + string[] tagsOfScenario = new string[] { + "contract=signalWithTypeStartingWithNotAllowedCharacter"}; + System.Collections.Specialized.OrderedDictionary argumentsOfScenario = new System.Collections.Specialized.OrderedDictionary(); + TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Send a signal fails when type starts with not allowed \'_\' (underscore) character", null, tagsOfScenario, argumentsOfScenario, featureTags); +#line 40 + this.ScenarioInitialize(scenarioInfo); +#line hidden + if ((TagHelper.ContainsIgnoreTag(tagsOfScenario) || TagHelper.ContainsIgnoreTag(featureTags))) + { + testRunner.SkipScenario(); + } + else + { + this.ScenarioStart(); +#line 6 + this.FeatureBackground(); +#line hidden +#line 41 + testRunner.When("I send a signal with \'_test_message_type\' customMessageType", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); +#line hidden +#line 42 + testRunner.Then("I receive an error response", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); +#line hidden + } + this.ScenarioCleanup(); + } + + [NUnit.Framework.TestAttribute()] + [NUnit.Framework.DescriptionAttribute("Send a signal fails when type contains not allowed characters")] + [NUnit.Framework.CategoryAttribute("contract=signalWithTypeContainingNotAllowedCharacter")] + public void SendASignalFailsWhenTypeContainsNotAllowedCharacters() + { + string[] tagsOfScenario = new string[] { + "contract=signalWithTypeContainingNotAllowedCharacter"}; + System.Collections.Specialized.OrderedDictionary argumentsOfScenario = new System.Collections.Specialized.OrderedDictionary(); + TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Send a signal fails when type contains not allowed characters", null, tagsOfScenario, argumentsOfScenario, featureTags); +#line 45 + this.ScenarioInitialize(scenarioInfo); +#line hidden + if ((TagHelper.ContainsIgnoreTag(tagsOfScenario) || TagHelper.ContainsIgnoreTag(featureTags))) + { + testRunner.SkipScenario(); + } + else + { + this.ScenarioStart(); +#line 6 + this.FeatureBackground(); +#line hidden +#line 46 + testRunner.When("I send a signal with \'test:message_type\' customMessageType", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); +#line hidden +#line 47 + testRunner.Then("I receive an error response", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); +#line hidden + } + this.ScenarioCleanup(); + } + } +} +#pragma warning restore +#endregion diff --git a/src/UnitTests/AcceptanceTests/Features/subscribe/subscribe-custom-mssg-type.feature b/src/UnitTests/AcceptanceTests/Features/subscribe/subscribe-custom-mssg-type.feature new file mode 100644 index 000000000..ef8578595 --- /dev/null +++ b/src/UnitTests/AcceptanceTests/Features/subscribe/subscribe-custom-mssg-type.feature @@ -0,0 +1,14 @@ +@featureSet=subscribeCustomMssgType @beta +Feature: Subscribe for VSP + As a PubNub user I want to subscribe and receive custom message type. + Client should be able to receive custom message type from subscribe response without any + additional options set (like `include_custom_message_type`for other API). + + Background: + Given the demo keyset + + @contract=subscribeReceiveMessagesWithTypes + Scenario: Client can subscribe and receive messages with types + When I subscribe to 'some-channel' channel + Then I receive 2 messages in my subscribe response + And response contains messages with 'custom-message-type' and 'user-custom-message-type' types diff --git a/src/UnitTests/AcceptanceTests/Features/subscribe/subscribe-custom-mssg-type.feature.cs b/src/UnitTests/AcceptanceTests/Features/subscribe/subscribe-custom-mssg-type.feature.cs new file mode 100644 index 000000000..b2e56dd00 --- /dev/null +++ b/src/UnitTests/AcceptanceTests/Features/subscribe/subscribe-custom-mssg-type.feature.cs @@ -0,0 +1,129 @@ +// ------------------------------------------------------------------------------ +// +// This code was generated by SpecFlow (https://www.specflow.org/). +// SpecFlow Version:3.9.0.0 +// SpecFlow Generator Version:3.9.0.0 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ +#region Designer generated code +#pragma warning disable +namespace AcceptanceTests.Features.Subscribe +{ + using TechTalk.SpecFlow; + using System; + using System.Linq; + + + [System.CodeDom.Compiler.GeneratedCodeAttribute("TechTalk.SpecFlow", "3.9.0.0")] + [System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [NUnit.Framework.TestFixtureAttribute()] + [NUnit.Framework.DescriptionAttribute("Subscribe for VSP")] + [NUnit.Framework.CategoryAttribute("featureSet=subscribeCustomMssgType")] + [NUnit.Framework.CategoryAttribute("beta")] + public partial class SubscribeForVSPFeature + { + + private TechTalk.SpecFlow.ITestRunner testRunner; + + private static string[] featureTags = new string[] { + "featureSet=subscribeCustomMssgType", + "beta"}; + +#line 1 "subscribe-custom-mssg-type.feature" +#line hidden + + [NUnit.Framework.OneTimeSetUpAttribute()] + public virtual void FeatureSetup() + { + testRunner = TechTalk.SpecFlow.TestRunnerManager.GetTestRunner(); + TechTalk.SpecFlow.FeatureInfo featureInfo = new TechTalk.SpecFlow.FeatureInfo(new System.Globalization.CultureInfo("en-US"), "Features/subscribe", "Subscribe for VSP", " As a PubNub user I want to subscribe and receive custom message type.\n Client " + + "should be able to receive custom message type from subscribe response without an" + + "y\n additional options set (like `include_custom_message_type`for other API).", ProgrammingLanguage.CSharp, featureTags); + testRunner.OnFeatureStart(featureInfo); + } + + [NUnit.Framework.OneTimeTearDownAttribute()] + public virtual void FeatureTearDown() + { + testRunner.OnFeatureEnd(); + testRunner = null; + } + + [NUnit.Framework.SetUpAttribute()] + public void TestInitialize() + { + } + + [NUnit.Framework.TearDownAttribute()] + public void TestTearDown() + { + testRunner.OnScenarioEnd(); + } + + public void ScenarioInitialize(TechTalk.SpecFlow.ScenarioInfo scenarioInfo) + { + testRunner.OnScenarioInitialize(scenarioInfo); + testRunner.ScenarioContext.ScenarioContainer.RegisterInstanceAs(NUnit.Framework.TestContext.CurrentContext); + } + + public void ScenarioStart() + { + testRunner.OnScenarioStart(); + } + + public void ScenarioCleanup() + { + testRunner.CollectScenarioErrors(); + } + + public virtual void FeatureBackground() + { +#line 7 + #line hidden +#line 8 + testRunner.Given("the demo keyset", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Given "); +#line hidden + } + + [NUnit.Framework.TestAttribute()] + [NUnit.Framework.DescriptionAttribute("Client can subscribe and receive messages with types")] + [NUnit.Framework.CategoryAttribute("contract=subscribeReceiveMessagesWithTypes")] + public void ClientCanSubscribeAndReceiveMessagesWithTypes() + { + string[] tagsOfScenario = new string[] { + "contract=subscribeReceiveMessagesWithTypes"}; + System.Collections.Specialized.OrderedDictionary argumentsOfScenario = new System.Collections.Specialized.OrderedDictionary(); + TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Client can subscribe and receive messages with types", null, tagsOfScenario, argumentsOfScenario, featureTags); +#line 11 + this.ScenarioInitialize(scenarioInfo); +#line hidden + if ((TagHelper.ContainsIgnoreTag(tagsOfScenario) || TagHelper.ContainsIgnoreTag(featureTags))) + { + testRunner.SkipScenario(); + } + else + { + this.ScenarioStart(); +#line 7 + this.FeatureBackground(); +#line hidden +#line 12 + testRunner.When("I subscribe to \'some-channel\' channel", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); +#line hidden +#line 13 + testRunner.Then("I receive 2 messages in my subscribe response", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); +#line hidden +#line 14 + testRunner.And("response contains messages with \'custom-message-type\' and \'user-custom-message-ty" + + "pe\' types", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); +#line hidden + } + this.ScenarioCleanup(); + } + } +} +#pragma warning restore +#endregion diff --git a/src/UnitTests/AcceptanceTests/Steps/EventEngineSteps.cs b/src/UnitTests/AcceptanceTests/Steps/EventEngineSteps.cs index 62345b8c6..4234d347e 100644 --- a/src/UnitTests/AcceptanceTests/Steps/EventEngineSteps.cs +++ b/src/UnitTests/AcceptanceTests/Steps/EventEngineSteps.cs @@ -235,8 +235,8 @@ public void GivenTheDemoKeysetWithEventEngineEnabled() config = new PNConfiguration(new UserId("pn-csharp-acceptance-test-uuid")); config.Origin = acceptance_test_origin; config.Secure = false; - config.PublishKey = System.Environment.GetEnvironmentVariable("PN_PUB_KEY"); - config.SubscribeKey = System.Environment.GetEnvironmentVariable("PN_SUB_KEY"); + config.PublishKey = System.Environment.GetEnvironmentVariable("PN_PUB_KEY")??"pubKey"; + config.SubscribeKey = System.Environment.GetEnvironmentVariable("PN_SUB_KEY")??"subkey"; config.SecretKey = System.Environment.GetEnvironmentVariable("PN_SEC_KEY"); if (enableIntenalPubnubLogging) { @@ -254,7 +254,6 @@ public void GivenTheDemoKeysetWithEventEngineEnabled() statusCallback = new SubscribeCallbackExt(delegate (Pubnub pnObj, PNStatus status) { pnStatus = status; - Console.WriteLine("{0} {1} {2}", pnStatus.Operation, pnStatus.Category, pnStatus.StatusCode); if (currentContract == "subscribeHandshakeFailure" && pn.PubnubUnitTest.Attempts == 3) { statusReceivedEvent.Set(); } @@ -266,30 +265,24 @@ public void GivenTheDemoKeysetWithEventEngineEnabled() subscribeCallback = new SubscribeCallbackExt( delegate (Pubnub pnObj, PNMessageResult pubMsg) { - Console.WriteLine($"Message received in listener. {pn.JsonPluggableLibrary.SerializeToJsonString(pubMsg)}"); messageResult = pubMsg; messageReceivedEvent.Set(); }, delegate (Pubnub pnObj, PNPresenceEventResult presenceEvnt) { - Console.WriteLine(pn.JsonPluggableLibrary.SerializeToJsonString(presenceEvnt)); presenceEvent.Set(); }, delegate (Pubnub pnObj, PNSignalResult signalMsg) { - Console.WriteLine(pn.JsonPluggableLibrary.SerializeToJsonString(signalMsg)); }, delegate (Pubnub pnObj, PNObjectEventResult objectEventObj) { - Console.WriteLine(pn.JsonPluggableLibrary.SerializeToJsonString(objectEventObj)); }, delegate (Pubnub pnObj, PNMessageActionEventResult msgActionEvent) { - System.Diagnostics.Debug.WriteLine(pn.JsonPluggableLibrary.SerializeToJsonString(msgActionEvent)); }, delegate (Pubnub pnObj, PNFileEventResult fileEvent) { - System.Diagnostics.Debug.WriteLine(pn.JsonPluggableLibrary.SerializeToJsonString(fileEvent)); }); } @@ -303,12 +296,14 @@ public void GivenTheDemoKeysetWithPresenceEEenabled() unitTest.IncludePnsdk = true; unitTest.IncludeUuid = true; - config = new PNConfiguration(new UserId("pn-csharp-acceptance-test-uuid")); - config.Origin = acceptance_test_origin; - config.Secure = false; - config.PublishKey = System.Environment.GetEnvironmentVariable("PN_PUB_KEY"); - config.SubscribeKey = System.Environment.GetEnvironmentVariable("PN_SUB_KEY"); - config.SecretKey = System.Environment.GetEnvironmentVariable("PN_SEC_KEY"); + config = new PNConfiguration(new UserId("pn-csharp-acceptance-test-uuid")) + { + Origin = acceptance_test_origin, + Secure = false, + PublishKey = System.Environment.GetEnvironmentVariable("PN_PUB_KEY"), + SubscribeKey = System.Environment.GetEnvironmentVariable("PN_SUB_KEY"), + SecretKey = System.Environment.GetEnvironmentVariable("PN_SEC_KEY") + }; if (enableIntenalPubnubLogging) { config.LogVerbosity = PNLogVerbosity.BODY; @@ -336,13 +331,11 @@ public void GivenTheDemoKeysetWithPresenceEEenabled() subscribeCallback = new SubscribeCallbackExt( delegate (Pubnub pnObj, PNMessageResult pubMsg) { - Console.WriteLine($"Message received in listener. {pn.JsonPluggableLibrary.SerializeToJsonString(pubMsg)}"); messageResult = pubMsg; messageReceivedEvent.Set(); }, delegate (Pubnub pnObj, PNPresenceEventResult presenceEvnt) { - Console.WriteLine(pn.JsonPluggableLibrary.SerializeToJsonString(presenceEvnt)); presenceEvent.Set(); }); } @@ -356,8 +349,10 @@ public void GivenPresenceConfiguration(string heartbeatInterval, string timeout, [When(@"I join '(.*)', '(.*)', '(.*)' channels")] public void WhenIJoinChannels(string first, string second, string third) { - pn = new Pubnub(config); - pn.PubnubUnitTest = unitTest; + pn = new Pubnub(config) + { + PubnubUnitTest = unitTest + }; pn.PubnubUnitTest.PresenceActivityList?.Clear(); messageReceivedEvent = new ManualResetEvent(false); diff --git a/src/UnitTests/AcceptanceTests/Steps/FilesCustomMessageTypeSteps.cs b/src/UnitTests/AcceptanceTests/Steps/FilesCustomMessageTypeSteps.cs new file mode 100644 index 000000000..b7d73e810 --- /dev/null +++ b/src/UnitTests/AcceptanceTests/Steps/FilesCustomMessageTypeSteps.cs @@ -0,0 +1,157 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Net.Http; +using System.Threading.Tasks; +using NUnit.Framework; +using PubnubApi; +using TechTalk.SpecFlow; + +namespace AcceptanceTests.Steps; + +[Binding] +[Scope(Feature = "Send a file to Space")] +public class FilesCustomMessageTypeSteps +{ + private readonly ScenarioContext _scenarioContext; + + public static bool enableIntenalPubnubLogging = true; + public static string currentFeature = string.Empty; + public static string currentContract = string.Empty; + public static bool betaVersion = false; + private string acceptance_test_origin = "localhost:8090"; + private bool bypassMockServer = false; + private Pubnub pn; + private PNConfiguration config = null; + private string channel = "test"; + private string channelGroup = "test"; + private string publishMsg = "hello_world"; + PNPublishResult publishResult = null; + SubscribeCallback subscribeCallback = null; + SubscribeCallback statusCallback = null; + private PNFileUploadResult fileResult = null; + PNStatus pnStatus = null; + EventEngineSteps.PubnubError pnError = null; + SubscriptionSet subscriptionFirstSecond; + IPubnubUnitTest unitTest; + public FilesCustomMessageTypeSteps(ScenarioContext scenarioContext) + { + _scenarioContext = scenarioContext; + } + + [BeforeFeature] + public static void BeforeFeature(FeatureContext featureContext) + { + betaVersion = false; + if (featureContext.FeatureInfo != null && featureContext.FeatureInfo.Tags.Length > 0) + { + List tagList = featureContext.FeatureInfo.Tags.AsEnumerable().ToList(); + foreach (string tag in tagList) + { + if (tag.IndexOf("featureSet=") == 0) + { + currentFeature = tag.Replace("featureSet=", ""); + } + + if (tag.IndexOf("beta") == 0) + { + betaVersion = true; + } + } + } + + System.Diagnostics.Debug.WriteLine("Starting " + featureContext.FeatureInfo.Title); + } + + [AfterFeature] + public static void AfterFeature(FeatureContext featureContext) + { + System.Diagnostics.Debug.WriteLine("Finished " + featureContext.FeatureInfo.Title); + } + + [BeforeScenario()] + public void BeforeScenario() + { + currentContract = ""; + if (_scenarioContext.ScenarioInfo != null && _scenarioContext.ScenarioInfo.Tags.Length > 0) + { + List tagList = _scenarioContext.ScenarioInfo.Tags.AsEnumerable().ToList(); + foreach (string tag in tagList) + { + if (tag.IndexOf("contract=") == 0) + { + currentContract = tag.Replace("contract=", ""); + break; + } + } + if (!string.IsNullOrEmpty(currentContract) && !bypassMockServer) + { + string mockInitContract = string.Format("http://{0}/init?__contract__script__={1}", acceptance_test_origin, currentContract); + System.Diagnostics.Debug.WriteLine(mockInitContract); + HttpClient httpclient = new HttpClient(); + string mockInitResponse = httpclient.GetStringAsync(new Uri(mockInitContract)).Result; + System.Diagnostics.Debug.WriteLine(mockInitResponse); + } + } + + } + + [AfterScenario()] + public void AfterScenario() + { + if (!bypassMockServer) + { + string mockExpectContract = string.Format("http://{0}/expect", acceptance_test_origin); + System.Diagnostics.Debug.WriteLine(mockExpectContract); + WebClient webClient = new WebClient(); + string mockExpectResponse = webClient.DownloadString(mockExpectContract); + System.Diagnostics.Debug.WriteLine(mockExpectResponse); + } + if (pn != null) { + pn.Disconnect(); + pn.Destroy(); + } + } + + [Given(@"the demo keyset")] + public void GivenTheDemoKeyset() + { + unitTest = new EventEngineSteps.PubnubUnitTest(); + unitTest.Timetoken = 16820876821905844; + unitTest.RequestId = "myRequestId"; + unitTest.InternetAvailable = true; + unitTest.SdkVersion = "Csharp"; + unitTest.IncludePnsdk = true; + unitTest.IncludeUuid = true; + + config = new PNConfiguration(new UserId("test-uuid")) + { + Origin = acceptance_test_origin, + Secure = false, + PublishKey = System.Environment.GetEnvironmentVariable("PN_PUB_KEY")??"test", + SubscribeKey = System.Environment.GetEnvironmentVariable("PN_SUB_KEY")??"test" + }; + } + + [When(@"I send a file with '(.*)' customMessageType")] + public async Task WhenSendFileWithCustomMessageType(string customMessageType) + { + pn = new Pubnub(config); + var result = await pn.SendFile().Channel(channel).File(new byte[] { (byte)'1' }).FileName("any.txt").CustomMessageType(customMessageType).Message("success").ExecuteAsync(); + pnStatus = result.Status; + fileResult = result.Result; + } + + [Then(@"I receive a successful response")] + public void ThenIReceiveASuccessfulResponse() + { + Assert.IsTrue(pnStatus.StatusCode==200); + } + + [Then(@"I receive an error response")] + public void ThenIReceiveErrorResponse() + { + Assert.IsTrue(pnStatus.StatusCode!=200); + } +} \ No newline at end of file diff --git a/src/UnitTests/AcceptanceTests/Steps/HistoryCustomMessageTypeSteps.cs b/src/UnitTests/AcceptanceTests/Steps/HistoryCustomMessageTypeSteps.cs new file mode 100644 index 000000000..886e20ce0 --- /dev/null +++ b/src/UnitTests/AcceptanceTests/Steps/HistoryCustomMessageTypeSteps.cs @@ -0,0 +1,192 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Net.Http; +using System.Threading.Tasks; +using NUnit.Framework; +using PubnubApi; +using TechTalk.SpecFlow; + +namespace AcceptanceTests.Steps; + +[Binding] +[Scope(Feature = "History for VSP")] +public class HistoryCustomMessageTypeSteps +{ + public static bool enableIntenalPubnubLogging = true; + public static string currentFeature = string.Empty; + public static string currentContract = string.Empty; + public static bool betaVersion = false; + private string acceptance_test_origin = "localhost:8090"; + private bool bypassMockServer = false; + private readonly ScenarioContext _scenarioContext; + private Pubnub pn; + private PNConfiguration config = null; + private string channel; + private string channelGroup = "test"; + private string publishMsg = "hello_world"; + PNPublishResult publishResult = null; + SubscribeCallback subscribeCallback = null; + SubscribeCallback statusCallback = null; + private PNMessageResult messageResult = null; + PNStatus pnStatus = null; + EventEngineSteps.PubnubError pnError = null; + SubscriptionSet subscriptionFirstSecond; + IPubnubUnitTest unitTest; + private PNResult historyResult = null; + public HistoryCustomMessageTypeSteps(ScenarioContext scenarioContext) + { + _scenarioContext = scenarioContext; + } + + [BeforeFeature] + public static void BeforeFeature(FeatureContext featureContext) + { + betaVersion = false; + if (featureContext.FeatureInfo != null && featureContext.FeatureInfo.Tags.Length > 0) + { + List tagList = featureContext.FeatureInfo.Tags.AsEnumerable().ToList(); + foreach (string tag in tagList) + { + if (tag.IndexOf("featureSet=") == 0) + { + currentFeature = tag.Replace("featureSet=", ""); + } + + if (tag.IndexOf("beta") == 0) + { + betaVersion = true; + } + } + } + + System.Diagnostics.Debug.WriteLine("Starting " + featureContext.FeatureInfo.Title); + } + + [AfterFeature] + public static void AfterFeature(FeatureContext featureContext) + { + System.Diagnostics.Debug.WriteLine("Finished " + featureContext.FeatureInfo.Title); + } + + [BeforeScenario()] + public void BeforeScenario() + { + currentContract = ""; + if (_scenarioContext.ScenarioInfo != null && _scenarioContext.ScenarioInfo.Tags.Length > 0) + { + List tagList = _scenarioContext.ScenarioInfo.Tags.AsEnumerable().ToList(); + foreach (string tag in tagList) + { + if (tag.IndexOf("contract=") == 0) + { + currentContract = tag.Replace("contract=", ""); + break; + } + } + if (!string.IsNullOrEmpty(currentContract) && !bypassMockServer) + { + string mockInitContract = string.Format("http://{0}/init?__contract__script__={1}", acceptance_test_origin, currentContract); + System.Diagnostics.Debug.WriteLine(mockInitContract); + HttpClient httpclient = new HttpClient(); + string mockInitResponse = httpclient.GetStringAsync(new Uri(mockInitContract)).Result; + System.Diagnostics.Debug.WriteLine(mockInitResponse); + } + } + + } + + [AfterScenario()] + public void AfterScenario() + { + if (!bypassMockServer) + { + string mockExpectContract = string.Format("http://{0}/expect", acceptance_test_origin); + System.Diagnostics.Debug.WriteLine(mockExpectContract); + WebClient webClient = new WebClient(); + string mockExpectResponse = webClient.DownloadString(mockExpectContract); + System.Diagnostics.Debug.WriteLine(mockExpectResponse); + } + if (pn != null) { + pn.Disconnect(); + pn.Destroy(); + } + } + + [Given(@"the demo keyset with enabled storage")] + public void GivenTheDemoKeysetWithEnabledStorage() + { + unitTest = new EventEngineSteps.PubnubUnitTest(); + unitTest.Timetoken = 16820876821905844; //Hardcoded timetoken + unitTest.RequestId = "myRequestId"; + unitTest.InternetAvailable = true; + unitTest.SdkVersion = "Csharp"; + unitTest.IncludePnsdk = true; + unitTest.IncludeUuid = true; + + config = new PNConfiguration(new UserId("pn-csharp-acceptance-test-uuid")) + { + Origin = acceptance_test_origin, + Secure = false, + PublishKey = System.Environment.GetEnvironmentVariable("PN_PUB_KEY")??"test", + SubscribeKey = System.Environment.GetEnvironmentVariable("PN_SUB_KEY")??"test" + }; + } + + [When(@"I fetch message history with messageType for '(.*)' channel")] + public async Task WhenIFetchMessageHistoryWithMessageTypeForChannel(string channel) + { + pn = new Pubnub(config); + this.channel = channel; + historyResult = await pn.FetchHistory().Channels(new[] { channel }).IncludeMessageType(true).ExecuteAsync(); + pnStatus = historyResult.Status; + } + + [When(@"I fetch message history with customMessageType for '(.*)' channel")] + public async Task WhenIFetchMessageHistoryWithCustomMessageTypeForChannel(string channel) + { + pn = new Pubnub(config); + this.channel = channel; + historyResult = await pn.FetchHistory().Channels(new[] { channel }).IncludeMessageType(true).IncludeCustomMessageType(true).ExecuteAsync(); + pnStatus = historyResult.Status; + } + + [When(@"I fetch message history with 'include_custom_message_type' set to '(.*)' for '(.*)' channel")] + public async Task WhenIFetchMessageHistoryWithCustomMessageTypeForChannel(bool include,string channel) + { + pn = new Pubnub(config); + this.channel = channel; + historyResult = await pn.FetchHistory().Channels(new[] { channel }).IncludeCustomMessageType(include).ExecuteAsync(); + pnStatus = historyResult.Status; + } + [Then(@"I receive a successful response")] + public async Task ThenIReceiveASuccessfulResponse() + { + Assert.IsTrue(pnStatus.StatusCode==200); + } + + [Then(@"history response contains messages with '(.*)' and '(.*)' message types")] + public void ThenHistoryResponseContainsMessageTypes(string valueOne, string valueTwo) + { + var channelMessages = historyResult.Result.Messages[channel]; + Assert.IsTrue(channelMessages.Where(m=> m.MessageType == int.Parse(valueOne)).ToList().Count >0); + Assert.IsTrue(channelMessages.Where(m=> m.MessageType == int.Parse(valueTwo)).ToList().Count >0); + } + + [Then(@"history response contains messages with '(.*)' and '(.*)' types")] + public void ThenHistoryResponseContainsTypes(string valueOne, string valueTwo) + { + var channelMessages = historyResult.Result.Messages[channel]; + Assert.IsTrue(channelMessages.Where(m=> m.CustomMessageType == valueOne).ToList().Count >0); + Assert.IsTrue(channelMessages.Where(m=> m.CustomMessageType == valueTwo).ToList().Count >0); + } + + [Then(@"history response contains messages without customMessageType")] + public void ThenHistoryMessagesDoNotContainCustomMessageType() + { + var channelMessages = historyResult.Result.Messages[channel]; + Assert.IsTrue(channelMessages.Where(m=> m.CustomMessageType != null).ToList().Count == 0); + } + +} \ No newline at end of file diff --git a/src/UnitTests/AcceptanceTests/Steps/PublishCustomMessageTypeSteps.cs b/src/UnitTests/AcceptanceTests/Steps/PublishCustomMessageTypeSteps.cs new file mode 100644 index 000000000..5586c75b1 --- /dev/null +++ b/src/UnitTests/AcceptanceTests/Steps/PublishCustomMessageTypeSteps.cs @@ -0,0 +1,169 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; +using NUnit.Framework; +using PubnubApi; +using TechTalk.SpecFlow; + +namespace AcceptanceTests.Steps; + +[Binding] +[Scope(Feature = "Publish to Space")] +[Scope(Feature = "Send a signal to Space")] +public class PublishCustomMessageTypeSteps +{ + private readonly ScenarioContext _scenarioContext; + + public static bool enableIntenalPubnubLogging = true; + public static string currentFeature = string.Empty; + public static string currentContract = string.Empty; + public static bool betaVersion = false; + private string acceptance_test_origin = "localhost:8090"; + private bool bypassMockServer = false; + private Pubnub pn; + private PNConfiguration config = null; + private string channel = "test"; + private string channelGroup = "test"; + private string publishMsg = "hello_world"; + PNPublishResult publishResult = null; + SubscribeCallback subscribeCallback = null; + SubscribeCallback statusCallback = null; + private PNMessageResult messageResult = null; + PNStatus pnStatus = null; + EventEngineSteps.PubnubError pnError = null; + SubscriptionSet subscriptionFirstSecond; + IPubnubUnitTest unitTest; + + public PublishCustomMessageTypeSteps(ScenarioContext scenarioContext) + { + _scenarioContext = scenarioContext; + } + + [BeforeFeature] + public static void BeforeFeature(FeatureContext featureContext) + { + betaVersion = false; + if (featureContext.FeatureInfo != null && featureContext.FeatureInfo.Tags.Length > 0) + { + List tagList = featureContext.FeatureInfo.Tags.AsEnumerable().ToList(); + foreach (string tag in tagList) + { + if (tag.IndexOf("featureSet=") == 0) + { + currentFeature = tag.Replace("featureSet=", ""); + } + + if (tag.IndexOf("beta") == 0) + { + betaVersion = true; + } + } + } + + System.Diagnostics.Debug.WriteLine("Starting " + featureContext.FeatureInfo.Title); + } + + [AfterFeature] + public static void AfterFeature(FeatureContext featureContext) + { + System.Diagnostics.Debug.WriteLine("Finished " + featureContext.FeatureInfo.Title); + } + + [BeforeScenario()] + public void BeforeScenario() + { + currentContract = ""; + if (_scenarioContext.ScenarioInfo != null && _scenarioContext.ScenarioInfo.Tags.Length > 0) + { + List tagList = _scenarioContext.ScenarioInfo.Tags.AsEnumerable().ToList(); + foreach (string tag in tagList) + { + if (tag.IndexOf("contract=") == 0) + { + currentContract = tag.Replace("contract=", ""); + break; + } + } + if (!string.IsNullOrEmpty(currentContract) && !bypassMockServer) + { + string mockInitContract = string.Format("http://{0}/init?__contract__script__={1}", acceptance_test_origin, currentContract); + System.Diagnostics.Debug.WriteLine(mockInitContract); + HttpClient httpclient = new HttpClient(); + string mockInitResponse = httpclient.GetStringAsync(new Uri(mockInitContract)).Result; + System.Diagnostics.Debug.WriteLine(mockInitResponse); + } + } + + } + + [AfterScenario()] + public void AfterScenario() + { + if (!bypassMockServer) + { + string mockExpectContract = string.Format("http://{0}/expect", acceptance_test_origin); + System.Diagnostics.Debug.WriteLine(mockExpectContract); + WebClient webClient = new WebClient(); + string mockExpectResponse = webClient.DownloadString(mockExpectContract); + System.Diagnostics.Debug.WriteLine(mockExpectResponse); + } + if (pn != null) { + pn.Disconnect(); + pn.Destroy(); + } + } + + [Given(@"the demo keyset")] + public void GivenTheDemoKeyset() + { + unitTest = new EventEngineSteps.PubnubUnitTest(); + unitTest.Timetoken = 16820876821905844; //Hardcoded timetoken + unitTest.RequestId = "myRequestId"; + unitTest.InternetAvailable = true; + unitTest.SdkVersion = "Csharp"; + unitTest.IncludePnsdk = true; + unitTest.IncludeUuid = true; + + config = new PNConfiguration(new UserId("test-uuid")) + { + Origin = acceptance_test_origin, + Secure = false, + PublishKey = System.Environment.GetEnvironmentVariable("PN_PUB_KEY")??"test", + SubscribeKey = System.Environment.GetEnvironmentVariable("PN_SUB_KEY")??"test" + }; + } + + [When(@"I publish message with '(.*)' customMessageType")] + public async Task WhenPublishMessageWithCusomMessageType(string customMessageType) + { + pn = new Pubnub(config); + var result = await pn.Publish().Channel("demo").Message("dummy").CustomMessageType(customMessageType).ExecuteAsync(); + pnStatus = result.Status; + publishResult = result.Result; + } + + [Then(@"I receive a successful response")] + public async Task ThenIReceiveASuccessfulResponse() + { + Assert.IsTrue(pnStatus.StatusCode==200); + } + + [Then(@"I receive an error response")] + public async Task ThenIReceiveErrorResponse() + { + Assert.IsTrue(pnStatus.StatusCode!=200); + } + + [When(@"I send a signal with '(.*)' customMessageType")] + public async Task WhenSignalMessageWithCusomMessageType(string customMessageType) + { + pn = new Pubnub(config); + var result = await pn.Signal().Channel("demo").Message("dummy").CustomMessageType(customMessageType).ExecuteAsync(); + pnStatus = result.Status; + publishResult = result.Result; + } +} \ No newline at end of file diff --git a/src/UnitTests/AcceptanceTests/Steps/SubscribeCustomMessageTypeSteps.cs b/src/UnitTests/AcceptanceTests/Steps/SubscribeCustomMessageTypeSteps.cs new file mode 100644 index 000000000..e06fc12f8 --- /dev/null +++ b/src/UnitTests/AcceptanceTests/Steps/SubscribeCustomMessageTypeSteps.cs @@ -0,0 +1,184 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Net.Http; +using System.Threading; +using NUnit.Framework; +using PubnubApi; +using TechTalk.SpecFlow; + +namespace AcceptanceTests.Steps; + +[Binding] +public class SubscribeCustomMessageTypeSteps +{ + public static bool enableIntenalPubnubLogging = true; + public static string currentFeature = string.Empty; + public static string currentContract = string.Empty; + public static bool betaVersion = false; + private string acceptance_test_origin = "localhost:8090"; + private bool bypassMockServer = false; + private readonly ScenarioContext _scenarioContext; + private Pubnub pn; + private PNConfiguration config = null; + private string channel = "test"; + private string channelGroup = "test"; + private string publishMsg = "hello_world"; + PNPublishResult publishResult = null; + SubscribeCallback subscribeCallback = null; + SubscribeCallback statusCallback = null; + private PNMessageResult messageResult = null; + ManualResetEvent messageReceivedEvent = new ManualResetEvent(false); + ManualResetEvent statusReceivedEvent = new ManualResetEvent(false); + ManualResetEvent presenceEvent = new ManualResetEvent(false); + PNStatus pnStatus = null; + EventEngineSteps.PubnubError pnError = null; + SubscriptionSet subscriptionFirstSecond; + IPubnubUnitTest unitTest; + List receivedMessages = new List(); + private static int messageCount = 0; + + public SubscribeCustomMessageTypeSteps(ScenarioContext scenarioContext) + { + _scenarioContext = scenarioContext; + } + + [BeforeFeature] + public static void BeforeFeature(FeatureContext featureContext) + { + betaVersion = false; + if (featureContext.FeatureInfo != null && featureContext.FeatureInfo.Tags.Length > 0) + { + List tagList = featureContext.FeatureInfo.Tags.AsEnumerable().ToList(); + foreach (string tag in tagList) + { + if (tag.IndexOf("featureSet=") == 0) + { + currentFeature = tag.Replace("featureSet=", ""); + } + + if (tag.IndexOf("beta") == 0) + { + betaVersion = true; + } + } + } + + System.Diagnostics.Debug.WriteLine("Starting " + featureContext.FeatureInfo.Title); + } + + [AfterFeature] + public static void AfterFeature(FeatureContext featureContext) + { + System.Diagnostics.Debug.WriteLine("Finished " + featureContext.FeatureInfo.Title); + } + + [BeforeScenario()] + public void BeforeScenario() + { + currentContract = ""; + if (_scenarioContext.ScenarioInfo != null && _scenarioContext.ScenarioInfo.Tags.Length > 0) + { + List tagList = _scenarioContext.ScenarioInfo.Tags.AsEnumerable().ToList(); + foreach (string tag in tagList) + { + if (tag.IndexOf("contract=") == 0) + { + currentContract = tag.Replace("contract=", ""); + break; + } + } + if (!string.IsNullOrEmpty(currentContract) && !bypassMockServer) + { + string mockInitContract = string.Format("http://{0}/init?__contract__script__={1}", acceptance_test_origin, currentContract); + System.Diagnostics.Debug.WriteLine(mockInitContract); + HttpClient httpclient = new HttpClient(); + string mockInitResponse = httpclient.GetStringAsync(new Uri(mockInitContract)).Result; + System.Diagnostics.Debug.WriteLine(mockInitResponse); + } + } + + } + + [AfterScenario()] + public void AfterScenario() + { + if (!bypassMockServer) + { + string mockExpectContract = string.Format("http://{0}/expect", acceptance_test_origin); + System.Diagnostics.Debug.WriteLine(mockExpectContract); + WebClient webClient = new WebClient(); + string mockExpectResponse = webClient.DownloadString(mockExpectContract); + System.Diagnostics.Debug.WriteLine(mockExpectResponse); + } + if (pn != null) { + pn.Disconnect(); + pn.Destroy(); + } + } + + + [When(@"I subscribe to '(.*)' channel")] + public void WhenISubscribe(string channel) + { + config = new PNConfiguration(new UserId("test-uuid")) + { + Origin = acceptance_test_origin, + Secure = false, + PublishKey = System.Environment.GetEnvironmentVariable("PN_PUB_KEY")??"test", + SubscribeKey = System.Environment.GetEnvironmentVariable("PN_SUB_KEY")??"test" + }; + pn = new Pubnub(config); + + messageReceivedEvent = new ManualResetEvent(false); + statusReceivedEvent = new ManualResetEvent(false); + + subscribeCallback = new SubscribeCallbackExt( + delegate (Pubnub pnObj, PNMessageResult messageResult) + { + receivedMessages.Add(messageResult); + messageCount++; + if (messageCount == 2) + messageReceivedEvent.Set(); + }, + delegate (Pubnub pnObj, PNPresenceEventResult presenceEvnt) + { + Console.WriteLine(pn.JsonPluggableLibrary.SerializeToJsonString(presenceEvnt)); + presenceEvent.Set(); + }, + delegate (Pubnub pnObj, PNSignalResult signalMsg) + { + Console.WriteLine(pn.JsonPluggableLibrary.SerializeToJsonString(signalMsg)); + }, + delegate (Pubnub pnObj, PNObjectEventResult objectEventObj) + { + Console.WriteLine(pn.JsonPluggableLibrary.SerializeToJsonString(objectEventObj)); + }, + delegate (Pubnub pnObj, PNMessageActionEventResult msgActionEvent) + { + System.Diagnostics.Debug.WriteLine(pn.JsonPluggableLibrary.SerializeToJsonString(msgActionEvent)); + }, + delegate (Pubnub pnObj, PNFileEventResult fileEvent) + { + System.Diagnostics.Debug.WriteLine(pn.JsonPluggableLibrary.SerializeToJsonString(fileEvent)); + }); + pn.AddListener(subscribeCallback); + pn.Subscribe().Channels(new[] {channel}).Execute(); + } + + [Then(@"I receive 2 messages in my subscribe response")] + public void ThenIReceive2MessagesInMySubscribeResponse() + { + messageReceivedEvent.WaitOne (TimeSpan.FromSeconds(5)); + Assert.IsTrue(receivedMessages.Count == 2); + } + + [Then(@"response contains messages with '(.*)' and '(.*)' types")] + public void ThenResponseContainsCustomMessageTypes(string customeMessageTypeOne, string customeMessageTypeTwo) + { + + Assert.IsTrue(receivedMessages.Exists(x=>((PNMessageResult)x).CustomMessageType == customeMessageTypeOne)); + Assert.IsTrue(receivedMessages.Exists(x=>((PNMessageResult)x).CustomMessageType == customeMessageTypeTwo)); + } +} \ No newline at end of file diff --git a/src/UnitTests/PubnubApi.Tests/TestHarness.cs b/src/UnitTests/PubnubApi.Tests/TestHarness.cs index 8e6d90185..5550c391c 100644 --- a/src/UnitTests/PubnubApi.Tests/TestHarness.cs +++ b/src/UnitTests/PubnubApi.Tests/TestHarness.cs @@ -29,7 +29,6 @@ protected static Pubnub createPubNubInstance(PNConfiguration pnConfiguration, st else { pnConfiguration.Origin = "ps.pndsn.com"; - pnConfiguration.EnableEventEngine = false; pubnub = new Pubnub(pnConfiguration); } if (!string.IsNullOrEmpty(authToken)) diff --git a/src/UnitTests/PubnubApi.Tests/WhenAClientIsPresented.cs b/src/UnitTests/PubnubApi.Tests/WhenAClientIsPresented.cs index 3635f6b5f..f6bfe8680 100644 --- a/src/UnitTests/PubnubApi.Tests/WhenAClientIsPresented.cs +++ b/src/UnitTests/PubnubApi.Tests/WhenAClientIsPresented.cs @@ -22,6 +22,7 @@ public class WhenAClientIsPresented : TestHarness private static Pubnub pubnub; private static Server server; private static string authToken; + private static string presenceTestChannel = $"presenceTest{new Random().Next(100,1000)}"; public class TestLog : IPubnubLog { @@ -116,8 +117,14 @@ public static async Task Init() }, { channel4+"-pnpres", fullAccess - } - } + }, + { + presenceTestChannel, fullAccess + }, + { + $"{presenceTestChannel}{Constants.Pnpres}", fullAccess + }, + }, }).ExecuteAsync(); await Task.Delay(4000); @@ -2472,5 +2479,63 @@ public static void ThenPresenceHeartbeatShouldReturnMessage() Assert.IsTrue(receivedPresenceMessage, "ThenPresenceHeartbeatShouldReturnMessage not received"); } + [Test] + public static async Task ThenReceiveCustomObjectPresenceCallback() + { + bool receivedPresenceMessage = false; + + PNConfiguration config = new PNConfiguration(new UserId("mytestuuid")) + { + PublishKey = PubnubCommon.PublishKey, + SubscribeKey = PubnubCommon.SubscribeKey, + Secure = false + }; + if (PubnubCommon.PAMServerSideRun) + { + config.SecretKey = PubnubCommon.SecretKey; + } + ManualResetEvent presenceManualEvent = new ManualResetEvent(false); + SubscribeCallback listenerSubCallack = new SubscribeCallbackExt( + (o, m) => { Debug.WriteLine(pubnub.JsonPluggableLibrary.SerializeToJsonString(m)); }, + (o, p) => { + Debug.WriteLine(pubnub.JsonPluggableLibrary.SerializeToJsonString(p)); + if (p.Event == "join") { receivedPresenceMessage = true; } + presenceManualEvent.Set(); + }, + (o, s) => { + Debug.WriteLine(string.Format("{0} {1} {2}", s.Operation, s.Category, s.StatusCode)); + if (s.StatusCode != 200 || s.Error) + { + if (s.ErrorData != null) { Debug.WriteLine(s.ErrorData.Information); } + presenceManualEvent.Set(); + } + }); + pubnub = createPubNubInstance(config, authToken); + if (!pubnub.AddListener(listenerSubCallack)) + { + Assert.Fail("ATTENTION: AddListener failed"); + } + + manualResetEventWaitTimeout = 15000; + + pubnub.Subscribe().Channels(new [] { presenceTestChannel }).WithPresence().Execute(); + presenceManualEvent.WaitOne(manualResetEventWaitTimeout); + + await Task.Delay(10000); + + pubnub.Unsubscribe().Channels(new [] { presenceTestChannel }).Execute(); + + await Task.Delay(2000); + + if (!pubnub.RemoveListener(listenerSubCallack)) + { + Assert.Fail("ATTENTION: RemoveListener failed"); + } + pubnub.Destroy(); + pubnub.PubnubUnitTest = null; + pubnub = null; + Assert.IsTrue(receivedPresenceMessage, "ThenReceiveCustomObjectPresenceCallback not received"); + } + } } diff --git a/src/UnitTests/PubnubApi.Tests/WhenAMessageIsPublished.cs b/src/UnitTests/PubnubApi.Tests/WhenAMessageIsPublished.cs index 93e9a6367..26bab89a5 100644 --- a/src/UnitTests/PubnubApi.Tests/WhenAMessageIsPublished.cs +++ b/src/UnitTests/PubnubApi.Tests/WhenAMessageIsPublished.cs @@ -167,7 +167,6 @@ public static void ThenNullMessageShouldReturnException() .Message(message) .Execute(new PNPublishResultExt((r, s) => { })); }); - pubnub.Destroy(); pubnub.PubnubUnitTest = null; pubnub = null; @@ -441,7 +440,70 @@ public static void ThenUnencryptFireGETShouldReturnSuccessCodeAndInfo() Assert.IsTrue(receivedPublishMessage, "Unencrypt Fire Failed"); } + + public class MockObject + { + public string Text; + public int Number; + public bool Flag; + } + [Test] + public static async Task ThenSendAndReceiveCustomObject() + { + var config = new PNConfiguration(new UserId("mytestuuid")) + { + PublishKey = PubnubCommon.PublishKey, + SubscribeKey = PubnubCommon.SubscribeKey, + Secure = false, + }; + if (PubnubCommon.PAMServerSideRun) + { + config.SecretKey = PubnubCommon.SecretKey; + } + else if (!string.IsNullOrEmpty(authKey) && !PubnubCommon.SuppressAuthKey) + { + config.AuthKey = authKey; + } + pubnub = createPubNubInstance(config); + + var objectMessage = new MockObject() + { + Text = "some_text", + Flag = true, + Number = 2137 + }; + + var receivedObject = new ManualResetEvent(false); + var listener = new SubscribeCallbackExt( + (o, m) => + { + if (m is { Message: MockObject { Text: "some_text", Flag: true, Number: 2137 } }) + { + receivedObject.Set(); + } + }, + (o, p) => { + }, + (o, s) => { + }); + pubnub.AddListener(listener); + + var channel = "hello_my_channel"; + + pubnub.Subscribe().Channels(new []{channel}).Execute(); + + await Task.Delay(1000); + + await pubnub.Publish().Channel(channel).Message(objectMessage).ExecuteAsync(); + + var received = receivedObject.WaitOne(10000); + Assert.True(received); + pubnub.Unsubscribe().Channels(new []{channel}).Execute(); + pubnub.Destroy(); + pubnub.PubnubUnitTest = null; + pubnub = null; + } [Test] public static void ThenUnencryptPublishPOSTShouldReturnSuccessCodeAndInfo() diff --git a/src/UnitTests/PubnubApi.Tests/WhenAMessageIsSignaled.cs b/src/UnitTests/PubnubApi.Tests/WhenAMessageIsSignaled.cs index e46ca84ff..c2e14e247 100644 --- a/src/UnitTests/PubnubApi.Tests/WhenAMessageIsSignaled.cs +++ b/src/UnitTests/PubnubApi.Tests/WhenAMessageIsSignaled.cs @@ -355,18 +355,17 @@ public static void ThenUnencryptSignalListenerShouldGetMessagae() subscribeManualEvent.WaitOne(manualResetEventWaitTimeout); - pubnub.Unsubscribe().Channels(new[] { channel }).Execute(); - Thread.Sleep(1000); - pubnub.RemoveListener(listenerSubCallack); - pubnub.Destroy(); - pubnub.PubnubUnitTest = null; - pubnub = null; if (receivedErrorMessage) { internalReceivedMessage = false; } + pubnub.RemoveListener(listenerSubCallack); + pubnub.Unsubscribe().Channels(new[] { channel }).Execute(); + pubnub.Destroy(); + pubnub.PubnubUnitTest = null; + pubnub = null; Assert.IsTrue(internalReceivedMessage, "WhenSubscribedToAChannel --> ThenUnencryptSignalListenerShouldGetMessagae Failed"); } } @@ -463,18 +462,16 @@ public static async Task ThenWithAsyncUnencryptSignalListenerShouldGetMessagae() subscribeManualEvent.WaitOne(manualResetEventWaitTimeout); - pubnub.Unsubscribe().Channels(new[] { channel }).Execute(); - Thread.Sleep(1000); - - pubnub.RemoveListener(listenerSubCallack); - pubnub.Destroy(); - pubnub.PubnubUnitTest = null; - pubnub = null; if (receivedErrorMessage) { internalReceivedMessage = false; } + pubnub.RemoveListener(listenerSubCallack); + pubnub.Unsubscribe().Channels(new[] { channel }).Execute(); + pubnub.Destroy(); + pubnub.PubnubUnitTest = null; + pubnub = null; Assert.IsTrue(internalReceivedMessage, "WhenSubscribedToAChannel --> ThenWithAsyncUnencryptSignalListenerShouldGetMessagae Failed"); } } @@ -520,7 +517,7 @@ public static void ThenIgnoreCipherKeyUnencryptSignalListenerShouldGetMessagae() if (m != null) { Debug.WriteLine(string.Format("Signal SubscribeCallback: PNMessageResult: {0}", pubnub.JsonPluggableLibrary.SerializeToJsonString(m.Message))); - if (pubnub.JsonPluggableLibrary.SerializeToJsonString(messageForUnencryptSignal) == m.Message.ToString()) + if (messageForUnencryptSignal == m.Message.ToString()) { internalReceivedMessage = true; } @@ -570,18 +567,17 @@ public static void ThenIgnoreCipherKeyUnencryptSignalListenerShouldGetMessagae() subscribeManualEvent.WaitOne(manualResetEventWaitTimeout); - pubnub.Unsubscribe().Channels(new[] { channel }).Execute(); - Thread.Sleep(1000); - - pubnub.RemoveListener(listenerSubCallack); - pubnub.Destroy(); - pubnub.PubnubUnitTest = null; - pubnub = null; + if (receivedErrorMessage) { internalReceivedMessage = false; } + pubnub.RemoveListener(listenerSubCallack); + pubnub.Unsubscribe().Channels(new[] { channel }).Execute(); + pubnub.Destroy(); + pubnub.PubnubUnitTest = null; + pubnub = null; Assert.IsTrue(internalReceivedMessage, "WhenSubscribedToAChannel --> ThenUnencryptSignalListenerShouldGetMessagae Failed"); } } @@ -676,18 +672,17 @@ public static async Task ThenWithAsyncIgnoreCipherKeyUnencryptSignalListenerShou internalReceivedMessage = true; } - pubnub.Unsubscribe().Channels(new[] { channel }).Execute(); - Thread.Sleep(1000); - - pubnub.RemoveListener(listenerSubCallack); - pubnub.Destroy(); - pubnub.PubnubUnitTest = null; - pubnub = null; + if (receivedErrorMessage) { internalReceivedMessage = false; } + pubnub.RemoveListener(listenerSubCallack); + pubnub.Unsubscribe().Channels(new[] { channel }).Execute(); + pubnub.Destroy(); + pubnub.PubnubUnitTest = null; + pubnub = null; Assert.IsTrue(internalReceivedMessage, "WhenSubscribedToAChannel --> ThenWithAsyncIgnoreCipherKeyUnencryptSignalListenerShouldGetMessagae Failed"); } } diff --git a/src/UnitTests/PubnubApi.Tests/WhenObjectUuidMetadata.cs b/src/UnitTests/PubnubApi.Tests/WhenObjectUuidMetadata.cs index 75a50643c..100195df1 100644 --- a/src/UnitTests/PubnubApi.Tests/WhenObjectUuidMetadata.cs +++ b/src/UnitTests/PubnubApi.Tests/WhenObjectUuidMetadata.cs @@ -216,7 +216,7 @@ public static void ThenUuidMetadataCRUDShouldReturnSuccessCodeAndInfo() manualEvent = new ManualResetEvent(false); #region "GetAllUuidMetadata" System.Diagnostics.Debug.WriteLine("pubnub.GetAllUuidMetadata() STARTED"); - pubnub.GetAllUuidMetadata().IncludeCount(true) + pubnub.GetAllUuidMetadata().IncludeCount(true).Filter($"id LIKE '{uuidMetadataId}*'") .Execute(new PNGetAllUuidMetadataResultExt((r, s) => { if (r != null && s.StatusCode == 200 && !s.Error) @@ -364,7 +364,7 @@ public static async Task ThenWithAsyncUuidMetadataCRUDShouldReturnSuccessCodeAnd #if NET40 PNResult getUsersResult = Task.Factory.StartNew(async () => await pubnub.GetAllUuidMetadata().IncludeCount(true).ExecuteAsync()).Result.Result; #else - PNResult getUsersResult = await pubnub.GetAllUuidMetadata().IncludeCount(true).ExecuteAsync(); + PNResult getUsersResult = await pubnub.GetAllUuidMetadata().IncludeCount(true).Filter($"id LIKE '{uuidMetadataId}*'").ExecuteAsync(); #endif if (getUsersResult.Result != null && getUsersResult.Status.StatusCode == 200 && !getUsersResult.Status.Error) { diff --git a/src/UnitTests/PubnubApi.Tests/WhenSubscribedToAChannel.cs b/src/UnitTests/PubnubApi.Tests/WhenSubscribedToAChannel.cs index 4687bb96d..a2e3d0501 100644 --- a/src/UnitTests/PubnubApi.Tests/WhenSubscribedToAChannel.cs +++ b/src/UnitTests/PubnubApi.Tests/WhenSubscribedToAChannel.cs @@ -433,7 +433,7 @@ public static void ThenSubscribeShouldReturnConnectStatus() LogVerbosity = PNLogVerbosity.BODY, PubnubLog = new TestLog(), NonSubscribeRequestTimeout = 120, - //EnableEventEngine = true, TODO: Event engine fails those tests... + //EnableEventEngine = true, //default enabled }; if (PubnubCommon.PAMServerSideRun) { @@ -514,7 +514,6 @@ public static void ThenMultiSubscribeShouldReturnConnectStatus() PublishKey = PubnubCommon.PublishKey, SubscribeKey = PubnubCommon.SubscribeKey, Secure = false, - EnableEventEngine = false }; if (PubnubCommon.PAMServerSideRun) { @@ -573,9 +572,10 @@ public static void ThenMultiSubscribeShouldReturnConnectStatus() string channel2 = "hello_my_channel2"; if (receivedMessage) { - receivedMessage = false; + // Reason: As per eventEngine specification, Connected Status won't be emitted on Subscription entity changes + // receivedMessage = false; - subscribeManualEvent = new ManualResetEvent(false); + // subscribeManualEvent = new ManualResetEvent(false); expected = "{\"t\":{\"t\":\"14836303477713304\",\"r\":7},\"m\":[]}"; @@ -600,13 +600,14 @@ public static void ThenMultiSubscribeShouldReturnConnectStatus() Thread.Sleep(1000); pubnub.Subscribe().Channels(new [] { channel2 }).Execute(); - subscribeManualEvent.WaitOne(manualResetEventWaitTimeout); //Wait for Connect Status + // subscribeManualEvent.WaitOne(manualResetEventWaitTimeout); //Wait for Connect Status } Thread.Sleep(1000); - - pubnub.Unsubscribe().Channels(new [] { channel1, channel2 }).Execute(); + pubnub.RemoveListener(listenerSubCallack); + pubnub.Unsubscribe().Channels(new [] { channel1, channel2 }).Execute(); + pubnub.Disconnect(); pubnub.Destroy(); pubnub.PubnubUnitTest = null; pubnub = null; @@ -687,8 +688,9 @@ public static void ThenMultiSubscribeShouldReturnConnectStatusSSL() string channel2 = "hello_my_channel2"; if (receivedMessage) { - receivedMessage = false; - subscribeManualEvent = new ManualResetEvent(false); + // Reason: EventEngine will not emit connected status when a new channel entity is added. + // receivedMessage = false; + // subscribeManualEvent = new ManualResetEvent(false); expected = "{\"t\":{\"t\":\"14836303477713304\",\"r\":7},\"m\":[]}"; @@ -719,8 +721,9 @@ public static void ThenMultiSubscribeShouldReturnConnectStatusSSL() Thread.Sleep(1000); - pubnub.Unsubscribe().Channels(new [] { channel1, channel2 }).Execute(); + pubnub.RemoveListener(listenerSubCallack); + pubnub.Unsubscribe().Channels(new [] { channel1, channel2 }).Execute(); pubnub.Destroy(); pubnub.PubnubUnitTest = null; pubnub = null; diff --git a/src/UnitTests/PubnubApi.Tests/WhenSubscribedToAChannel3.cs b/src/UnitTests/PubnubApi.Tests/WhenSubscribedToAChannel3.cs index 76d3e6e0b..d4053a85e 100644 --- a/src/UnitTests/PubnubApi.Tests/WhenSubscribedToAChannel3.cs +++ b/src/UnitTests/PubnubApi.Tests/WhenSubscribedToAChannel3.cs @@ -56,7 +56,6 @@ public static void Init() SecretKey = PubnubCommon.SecretKey, AuthKey = authKey, Secure = false, - EnableEventEngine = false }; server.RunOnHttps(false); diff --git a/src/UnitTests/PubnubApi.Tests/WhenSubscribedToWildcardChannel.cs b/src/UnitTests/PubnubApi.Tests/WhenSubscribedToWildcardChannel.cs index 49d5915f6..679308cf8 100644 --- a/src/UnitTests/PubnubApi.Tests/WhenSubscribedToWildcardChannel.cs +++ b/src/UnitTests/PubnubApi.Tests/WhenSubscribedToWildcardChannel.cs @@ -1094,7 +1094,7 @@ public static void ThenSubscribeShouldReturnWildCardPresenceEventInWildcardPrese bool receivedMessage = false; bool receivedErrorMessage = true; - PNConfiguration config = new PNConfiguration(new UserId("mytestuuid")) + PNConfiguration config = new PNConfiguration(new UserId($"user{new Random().Next(10,100)}")) { PublishKey = PubnubCommon.PublishKey, SubscribeKey = PubnubCommon.SubscribeKey, diff --git a/src/UnitTests/PubnubApi.Tests/WhenUnsubscribedToAChannel.cs b/src/UnitTests/PubnubApi.Tests/WhenUnsubscribedToAChannel.cs index 9e04290f3..fb360ef32 100644 --- a/src/UnitTests/PubnubApi.Tests/WhenUnsubscribedToAChannel.cs +++ b/src/UnitTests/PubnubApi.Tests/WhenUnsubscribedToAChannel.cs @@ -247,35 +247,36 @@ public override void MessageAction(Pubnub pubnub, PNMessageActionEventResult mes public override void Status(Pubnub pubnub, PNStatus status) { Debug.WriteLine("SubscribeCallback: PNStatus: " + status.StatusCode.ToString()); - if (status.StatusCode != 200 || status.Error) + // Reason: No status code info in status of Dicsonnected as per Event Engine specification + if (status.Category == PNStatusCategory.PNDisconnectedCategory) { switch (currentTestCase) { case "ThenShouldReturnUnsubscribedMessage": + receivedMessage = true; subscribeManualEvent.Set(); break; default: break; } - - if (status.ErrorData != null) - { - Debug.WriteLine(status.ErrorData.Information); - } } - else if (status.StatusCode == 200 && status.Category == PNStatusCategory.PNConnectedCategory) + else if (status.StatusCode != 200 || status.Error) { switch (currentTestCase) { case "ThenShouldReturnUnsubscribedMessage": - receivedMessage = true; subscribeManualEvent.Set(); break; default: break; } + + if (status.ErrorData != null) + { + Debug.WriteLine(status.ErrorData.Information); + } } - else if (status.StatusCode == 200 && status.Category == PNStatusCategory.PNDisconnectedCategory) + else if (status.StatusCode == 200 && status.Category == PNStatusCategory.PNConnectedCategory) { switch (currentTestCase) { @@ -288,7 +289,6 @@ public override void Status(Pubnub pubnub, PNStatus status) } } - } public override void File(Pubnub pubnub, PNFileEventResult fileEvent) diff --git a/src/UnitTests/PubnubApi.Tests/WhenUnsubscribedToAChannelGroup.cs b/src/UnitTests/PubnubApi.Tests/WhenUnsubscribedToAChannelGroup.cs index ed13eeae6..8719aad5b 100644 --- a/src/UnitTests/PubnubApi.Tests/WhenUnsubscribedToAChannelGroup.cs +++ b/src/UnitTests/PubnubApi.Tests/WhenUnsubscribedToAChannelGroup.cs @@ -150,7 +150,12 @@ public static void ThenShouldReturnUnsubscribedMessage() (o, p) => { /* Catch the presence events */ }, (o, s) => { Debug.WriteLine("SubscribeCallback: PNStatus: " + s.StatusCode.ToString()); - if (s.StatusCode != 200 || s.Error) + // Reason: No Status code information emitted on Disconnected Event + if (s.Category == PNStatusCategory.PNConnectedCategory || s.Category == PNStatusCategory.PNDisconnectedCategory) + { + receivedMessage = true; + subscribeManualEvent.Set(); + } else if (s.StatusCode != 200 || s.Error) { subscribeManualEvent.Set(); if (s.ErrorData != null) @@ -158,11 +163,6 @@ public static void ThenShouldReturnUnsubscribedMessage() Debug.WriteLine(s.ErrorData.Information); } } - else if (s.StatusCode == 200 && (s.Category == PNStatusCategory.PNConnectedCategory || s.Category == PNStatusCategory.PNDisconnectedCategory)) - { - receivedMessage = true; - subscribeManualEvent.Set(); - } }); pubnub = createPubNubInstance(config); pubnub.AddListener(listenerSubCallack);