Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Concurrent mic publish tests #349

Merged
merged 21 commits into from
Mar 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 14 additions & 3 deletions .github/workflows/testing-matrix.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ name: Testing Matrix
on:
workflow_dispatch:
push:
branches: [ main ]
branches: [main]
pull_request:
branches: [ main ]
branches: [main]

concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
Expand All @@ -17,13 +17,24 @@ jobs:
fail-fast: false
matrix:
xcode-version: [14.2, 15.2]
destination: ['platform=iOS Simulator,OS=17.2,name=iPhone 14 Pro', 'platform=macOS', 'platform=macOS,variant=Mac Catalyst']
destination:
[
"platform=iOS Simulator,OS=17.2,name=iPhone 14 Pro",
"platform=macOS",
"platform=macOS,variant=Mac Catalyst",
]

runs-on: macos-13

steps:
- uses: actions/checkout@v4

- name: Install LiveKit Server
run: brew install livekit

- name: Run LiveKit Server
run: livekit-server --dev &

- uses: maxim-lobanov/setup-xcode@v1
with:
xcode-version: ${{ matrix.xcode-version }}
Expand Down
49 changes: 49 additions & 0 deletions LiveKit.xctestplan
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
{
"configurations" : [
{
"id" : "C13DBD7E-A26D-4166-987B-8BB0E3A8A56F",
"name" : "Test Scheme Action",
"options" : {

}
}
],
"defaultOptions" : {
"environmentVariableEntries" : [
{
"key" : "LIVEKIT_TESTING_URL",
"value" : "$(LIVEKIT_TESTING_URL)"
},
{
"key" : "LIVEKIT_TESTING_API_KEY",
"value" : "$(LIVEKIT_TESTING_API_KEY)"
},
{
"key" : "LIVEKIT_TESTING_API_SECRET",
"value" : "$(LIVEKIT_TESTING_API_SECRET)"
}
],
"targetForVariableExpansion" : {
"containerPath" : "container:",
"identifier" : "LiveKit",
"name" : "LiveKit"
}
},
"testTargets" : [
{
"target" : {
"containerPath" : "container:",
"identifier" : "LiveKitTests",
"name" : "LiveKitTests"
}
},
{
"target" : {
"containerPath" : "container:",
"identifier" : "LiveKitTestsObjC",
"name" : "LiveKitTestsObjC"
}
}
],
"version" : 1
}
17 changes: 13 additions & 4 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,11 @@ let package = Package(
// LK-Prefixed Dynamic WebRTC XCFramework
.package(url: "https://github.com/livekit/webrtc-xcframework.git", exact: "114.5735.13"),
.package(url: "https://github.com/apple/swift-protobuf.git", .upToNextMajor(from: "1.25.2")),
.package(url: "https://github.com/apple/swift-log.git", .upToNextMajor(from: "1.5.3")),
.package(url: "https://github.com/apple/swift-docc-plugin", from: "1.3.0"),
.package(url: "https://github.com/apple/swift-log.git", .upToNextMajor(from: "1.5.4")),
// Only used for DocC generation
.package(url: "https://github.com/apple/swift-docc-plugin", .upToNextMajor(from: "1.3.0")),
// Only used for Testing
.package(url: "https://github.com/vapor/jwt-kit.git", .upToNextMajor(from: "4.13.2")),
],
targets: [
.systemLibrary(name: "CHeaders"),
Expand All @@ -37,11 +40,17 @@ let package = Package(
),
.testTarget(
name: "LiveKitTests",
dependencies: ["LiveKit"]
dependencies: [
"LiveKit",
.product(name: "JWTKit", package: "jwt-kit"),
]
),
.testTarget(
name: "LiveKitTestsObjC",
dependencies: ["LiveKit"]
dependencies: [
"LiveKit",
.product(name: "JWTKit", package: "jwt-kit"),
]
),
]
)
1 change: 0 additions & 1 deletion Sources/LiveKit/Core/Transport.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
*/

import Foundation
import SwiftProtobuf

@_implementationOnly import LiveKitWebRTC

Expand Down
6 changes: 5 additions & 1 deletion Tests/LiveKitTests/Basic.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,8 @@
@testable import LiveKit
import XCTest

class Basic: XCTestCase {}
class Basic: XCTestCase {
func testReadVersion() {
print("LiveKitSDK.version: \(LiveKitSDK.version)")
}
}
108 changes: 108 additions & 0 deletions Tests/LiveKitTests/PublishTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
/*
* Copyright 2024 LiveKit
*
* 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 Combine
import CoreMedia
@testable import LiveKit
import XCTest

class PublishTests: XCTestCase {
let room1 = Room()
let room2 = Room()

var watchRoom1: AnyCancellable?
var watchRoom2: AnyCancellable?

override func setUp() async throws {
let url = testUrl()

let token1 = try testToken(for: "room01", identity: "identity01")
try await room1.connect(url: url, token: token1)

let token2 = try testToken(for: "room01", identity: "identity02")
try await room2.connect(url: url, token: token2)

let room1ParticipantCountIs2 = expectation(description: "Room1 Participant count is 2")
room1ParticipantCountIs2.assertForOverFulfill = false

let room2ParticipantCountIs2 = expectation(description: "Room2 Participant count is 2")
room2ParticipantCountIs2.assertForOverFulfill = false

watchRoom1 = room1.objectWillChange.sink { _ in
if self.room1.allParticipants.count == 2 {
room1ParticipantCountIs2.fulfill()
}
}

watchRoom2 = room2.objectWillChange.sink { _ in
if self.room2.allParticipants.count == 2 {
room2ParticipantCountIs2.fulfill()
}
}

// Wait until both room's participant count is 2
await fulfillment(of: [room1ParticipantCountIs2, room2ParticipantCountIs2], timeout: 30)
}

override func tearDown() async throws {
await room1.disconnect()
await room2.disconnect()
watchRoom1?.cancel()
watchRoom2?.cancel()
}

func testResolveSid() async throws {
XCTAssert(room1.connectionState == .connected)

let sid = try await room1.sid()
print("Room.sid(): \(String(describing: sid))")
XCTAssert(sid.stringValue.starts(with: "RM_"))
}

func testConcurrentMicPublish() async throws {
// Lock
struct State {
var firstMicPublication: LocalTrackPublication?
}

let _state = StateSync(State())

// Run Tasks concurrently
try await withThrowingTaskGroup(of: Void.self) { group in
for _ in 1 ... 100 {
group.addTask {
let result = try await self.room1.localParticipant.setMicrophone(enabled: true)

if let result {
_state.mutate {
if let firstMicPublication = $0.firstMicPublication {
XCTAssert(result == firstMicPublication, "Duplicate mic track has been published")
} else {
$0.firstMicPublication = result
print("Did publish first mic track: \(String(describing: result))")
}
}
}
}
}

try await group.waitForAll()
}

// Reset
await room1.localParticipant.unpublishAll()
}
}
Loading