Skip to content

Commit

Permalink
[Rollouts] Rollouts serilization
Browse files Browse the repository at this point in the history
  • Loading branch information
themiswang committed Jan 10, 2024
1 parent 97094c8 commit a8873d5
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public class CrashlyticsRemoteConfigManager: NSObject {
public static let maxParameterValueLength = 256

var remoteConfig: RemoteConfigInterop
public private(set) var rolloutAssignment: [RolloutAssignment] = []
@objc public private(set) var rolloutAssignment: [RolloutAssignment] = []
weak var persistenceDelegate: CrashlyticsPersistentLog?

@objc public init(remoteConfig: RemoteConfigInterop) {
Expand All @@ -35,6 +35,22 @@ public class CrashlyticsRemoteConfigManager: NSObject {
@objc public func updateRolloutsState(rolloutsState: RolloutsState) {
rolloutAssignment = normalizeRolloutAssignment(assignments: Array(rolloutsState.assignments))
}

@objc public func getRolloutAssignmentsEncodedJson() -> String? {
let encodedRolloutAssignments = rolloutAssignment.map { assignment in
EncodedRolloutAssignment(assignment: assignment)
}

let encoder = JSONEncoder()
encoder.keyEncodingStrategy = .convertToSnakeCase
encoder.outputFormatting = .sortedKeys
let encodeData = try? encoder.encode(encodedRolloutAssignments)
if let data = encodeData, let returnString = String(data: data, encoding: .utf8) {
return returnString
}
debugPrint("Failed to serialize rollouts", encodeData ?? "nil")
return nil
}
}

private extension CrashlyticsRemoteConfigManager {
Expand Down
34 changes: 34 additions & 0 deletions Crashlytics/Crashlytics/Rollouts/EncodedRolloutAssignment.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Copyright 2024 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import FirebaseRemoteConfigInterop
import Foundation

@objc(FIRCLSEncodedRolloutAssignment)
class EncodedRolloutAssignment: NSObject, Codable {
@objc public private(set) var rolloutId: String
@objc public private(set) var variantId: String
@objc public private(set) var templateVersion: Int64
@objc public private(set) var parameterKey: String
@objc public private(set) var parameterValue: String

public init(assignment: RolloutAssignment) {
rolloutId = stringToHexConverter(for: assignment.rolloutId)
variantId = stringToHexConverter(for: assignment.variantId)
templateVersion = assignment.templateVersion
parameterKey = stringToHexConverter(for: assignment.parameterKey)
parameterValue = stringToHexConverter(for: assignment.parameterValue)
super.init()
}
}
35 changes: 35 additions & 0 deletions Crashlytics/Crashlytics/Rollouts/StringToHexConverter.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Copyright 2024 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import Foundation

// This is a swift rewrite for the logic in FIRCLSFile for the function FIRCLSFileHexEncodeString()
public func stringToHexConverter(for string: String) -> String {
let hexMap = "0123456789abcdef"

var processedString = ""
let utf8Array = string.utf8.map { UInt8($0) }
for c in utf8Array {
let index1 = String.Index(
utf16Offset: Int(c >> 4),
in: hexMap
)
let index2 = String.Index(
utf16Offset: Int(c & 0x0F),
in: hexMap
)
processedString = processedString + String(hexMap[index1]) + String(hexMap[index2])
}
return processedString
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,18 @@ final class CrashlyticsRemoteConfigManagerTests: XCTestCase {
return rollouts
}()

let singleRollout: RolloutsState = {
let assignment1 = RolloutAssignment(
rolloutId: "rollout_1",
variantId: "control",
templateVersion: 1,
parameterKey: "my_feature",
parameterValue: "这是themis的测试数据,输入中文" // check unicode
)
let rollouts = RolloutsState(assignmentList: [assignment1])
return rollouts
}()

let rcInterop = RemoteConfigConfigMock()

func testRemoteConfigManagerProperlyProcessRolloutsState() throws {
Expand All @@ -61,4 +73,15 @@ final class CrashlyticsRemoteConfigManagerTests: XCTestCase {
}
}
}

func testRemoteConfigManagerGenerateEncodedRolloutAssignmentsJson() throws {
let expectedString =
"[{\"parameter_key\":\"6d795f66656174757265\",\"parameter_value\":\"e8bf99e698af7468656d6973e79a84e6b58be8af95e695b0e68daeefbc8ce8be93e585a5e4b8ade69687\",\"rollout_id\":\"726f6c6c6f75745f31\",\"template_version\":1,\"variant_id\":\"636f6e74726f6c\"}]"

let rcManager = CrashlyticsRemoteConfigManager(remoteConfig: rcInterop)
rcManager.updateRolloutsState(rolloutsState: singleRollout)

let string = rcManager.getRolloutAssignmentsEncodedJson()
XCTAssertEqual(string, expectedString)
}
}

0 comments on commit a8873d5

Please sign in to comment.