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

[web] Run fake integration test #1384

Merged
merged 1 commit into from
Oct 24, 2023
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
22 changes: 22 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,28 @@ jobs:
run: |
bash ci/run_flutter_windows_integration_test.sh

integration_test_web:
name: Run Flutter Web Integration Tests
if: ${{ !contains(github.event.pull_request.labels.*.name, 'ci:skip') }}
strategy:
matrix:
version: ['3.13.7']
runs-on: ubuntu-latest
timeout-minutes: 60
env:
TEST_APP_ID: ${{ secrets.MY_APP_ID }}
steps:
- uses: actions/checkout@v3
- uses: subosito/flutter-action@v2
with:
flutter-version: ${{ matrix.version }}
cache: true
- name: Run web integration test
shell: bash
run: |
chromedriver --port=4444 --trace-buffer-size=100000 &
bash ci/run_flutter_integration_test.sh web

build_android_ubuntu:
name: Build Android on Ubuntu
if: ${{ !contains(github.event.pull_request.labels.*.name, 'ci:skip') }}
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,5 @@ third_party/
**/.plugin_dev

.ccls-cache/

test_shard/**/scripts/iris_web_version.js
33 changes: 26 additions & 7 deletions ci/run_flutter_integration_test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,32 @@
set -e
set -x

flutter packages get
MY_PATH=$(dirname "$0")
PLATFORM=$1 # android/ios/macos/windows/web

cd integration_test_app
if [[ ${PLATFORM} == "web" ]];then
pushd ${MY_PATH}/../test_shard/fake_test_app

pushd iris_integration_test
git submodule update
popd
echo "Run integration test on web"

flutter packages get
flutter test integration_test --dart-define=TEST_APP_ID="${TEST_APP_ID}"
flutter packages get

for filename in integration_test/*.dart; do
if [[ "$filename" == *.generated.dart ]]; then
continue
fi

flutter drive \
--verbose-system-logs \
-d web-server \
--driver=test_driver/integration_test.dart \
--target=${filename}
done

popd

elif [[ ${PLATFORM} == "android" || ${PLATFORM} == "ios" ]];then
echo "Not implemented"
else
echo "Not implemented"
fi
12 changes: 6 additions & 6 deletions lib/src/impl/agora_rtc_engine_impl.dart
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,11 @@ import 'platform/global_video_view_controller.dart';

// ignore_for_file: public_member_api_docs

int? _mockRtcEngineNativeHandle;
InitilizationArgProvider? _mockRtcEngineProvider;
@visibleForTesting
void setMockRtcEngineNativeHandle(int? mockRtcEngineNativeHandle) {
void setMockRtcEngineProvider(InitilizationArgProvider? mockRtcEngineProvider) {
assert(() {
_mockRtcEngineNativeHandle = mockRtcEngineNativeHandle;
_mockRtcEngineProvider = mockRtcEngineProvider;
return true;
}());
}
Expand Down Expand Up @@ -377,10 +377,10 @@ class RtcEngineImpl extends rtc_engine_ex_binding.RtcEngineExImpl
await engineMethodChannel.invokeMethod('androidInit');
}

List<int> args = [];
List<InitilizationArgProvider> args = [];
assert(() {
if (_mockRtcEngineNativeHandle != null) {
args.add(_mockRtcEngineNativeHandle!);
if (_mockRtcEngineProvider != null) {
args.add(_mockRtcEngineProvider!);
}
return true;
}());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,14 @@ class NativeIrisApiEngineBindingsDelegate
}

@override
CreateApiEngineResult createApiEngine(List<Object> args) {
CreateApiEngineResult createApiEngine(List<InitilizationArgProvider> args) {
ffi.Pointer<ffi.Void> enginePtr = ffi.nullptr;
assert(() {
if (args.isNotEmpty) {
assert(args.length == 1);
enginePtr = args[0] as ffi.Pointer<ffi.Void>;
final engineIntPtr =
args[0].provide(const IrisApiEngineHandle(0))() as int;
enginePtr = ffi.Pointer<ffi.Void>.fromAddress(engineIntPtr);
}
return true;
}());
Expand Down
16 changes: 14 additions & 2 deletions lib/src/impl/platform/web/iris_web_rtc_bindings_js.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,17 @@ library iris_web_rtc;
import 'package:iris_method_channel/iris_method_channel_bindings_web.dart';
import 'package:js/js.dart';

@JS('AgoraWrapper.initIrisRtc')
external void initIrisRtc(IrisApiEngine irisApiEngine);
@JS('IrisWebRtc.initIrisRtc')
external void initIrisRtc(
IrisApiEngine irisApiEngine, InitIrisRtcOptions? options);

@JS('InitIrisRtcOptions')
@anonymous
class InitIrisRtcOptions {
// Must have an unnamed factory constructor with named arguments.
external factory InitIrisRtcOptions(
{Object? agoraRTC, Object? irisRtcEngine});

external Object get agoraRTC;
external Object get irisRtcEngine;
}
17 changes: 14 additions & 3 deletions lib/src/impl/platform/web/js_iris_api_engine_binding_delegate.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,22 @@ class IrisApiEngineBindingsDelegateJS
void initialize() {}

@override
CreateApiEngineResult createApiEngine(List<Object> args) {
CreateApiEngineResult createApiEngine(List<InitilizationArgProvider> args) {
final apiEnginePtr = js.createIrisApiEngine();
initIrisRtc(apiEnginePtr);
final irisApiEngineHandle = IrisApiEngineHandle(apiEnginePtr);
InitIrisRtcOptions? options;
// Only set the option in debug mode
assert(() {
if (args.isNotEmpty) {
final arg = args[0].provide(irisApiEngineHandle)();
options = InitIrisRtcOptions(irisRtcEngine: arg);
}

return true;
}());
initIrisRtc(apiEnginePtr, options);

final res = CreateApiEngineResult(IrisApiEngineHandle(apiEnginePtr));
final res = CreateApiEngineResult(irisApiEngineHandle);

return res;
}
Expand Down
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ dependencies:
ffi: '>=1.1.2'
async: ^2.8.2
meta: ^1.7.0
iris_method_channel: 2.0.0-dev.3
iris_method_channel: 2.0.0-dev.4
js: ^0.6.3
dev_dependencies:
flutter_test:
Expand Down
23 changes: 23 additions & 0 deletions scripts/iris_web_version.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Share the iris web url to all the tests

// This url should be same as the url inside the `example/web/index.html`
const irisWebUrl = 'https://download.agora.io/staging/iris-web-rtc_0.1.2-dev.4.js';
const irisWebFakeUrl = 'https://download.agora.io/staging/iris-web-rtc-fake_0.1.2-dev.4.js';

(function() {
var scriptLoaded = false;
function _appendScript(url) {
var scriptTag = document.createElement('script');
scriptTag.src = url;
scriptTag.type = 'text/javascript';
scriptTag.async = false;
document.body.append(scriptTag);
}
if (scriptLoaded) {
return;
}
scriptLoaded = true;

_appendScript(irisWebUrl);
_appendScript(irisWebFakeUrl);
})();
1 change: 0 additions & 1 deletion test_shard/fake_test_app/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ migrate_working_dir/
/build/

# Web related
lib/generated_plugin_registrant.dart

# Symbolication related
app.*.symbols
Expand Down
46 changes: 37 additions & 9 deletions test_shard/fake_test_app/integration_test/apis_call_fake_test.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import 'dart:async';

import 'package:flutter/foundation.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:integration_test/integration_test.dart';
import 'generated/audiodevicemanager_fake_test.generated.dart'
Expand All @@ -17,30 +20,55 @@ import 'generated/videodevicemanager_fake_test.generated.dart'

import 'package:iris_tester/iris_tester.dart';
import 'package:agora_rtc_engine/src/impl/agora_rtc_engine_impl.dart';
import 'package:iris_method_channel/iris_method_channel.dart';

class TestInitilizationArgProvider implements InitilizationArgProvider {
TestInitilizationArgProvider(this.testerArgs);
TestInitilizationArgProvider.fromValue(IrisHandle this.value)
: testerArgs = [];
final List<TesterArgsProvider> testerArgs;
IrisHandle? value;
@override
IrisHandle provide(IrisApiEngineHandle apiEngineHandle) {
return value ?? ObjectIrisHandle(testerArgs[0](apiEngineHandle()));
}
}

void main() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();

IrisTester irisTester = IrisTester();
IrisTester irisTester = createIrisTester();

setUp(() {
irisTester.initialize();
setMockRtcEngineNativeHandle(irisTester.getfakeRtcEngineHandle());
if (kIsWeb) {
setMockRtcEngineProvider(
TestInitilizationArgProvider(irisTester.getTesterArgs()));
} else {
// On IO, the function return from the `irisTester.getTesterArgs()` capture
// the `Pointer` from `IrisTester`, which is invalid to pass to the `Isolate`,
// so directly pass the `ObjectIrisHandle` as value to the `setMockRtcEngineProvider`
final value = irisTester.getTesterArgs()[0](const IrisApiEngineHandle(0));
setMockRtcEngineProvider(
TestInitilizationArgProvider.fromValue(ObjectIrisHandle(value)));
}
});

tearDown(() {
irisTester.dispose();
setMockRtcEngineNativeHandle(null);
setMockRtcEngineProvider(null);
});

audiodevicemanager.audioDeviceManagerSmokeTestCases();
localspatialaudioengine.testCases();
if (!kIsWeb) {
audiodevicemanager.audioDeviceManagerSmokeTestCases();
localspatialaudioengine.testCases();
mediaplayer.mediaPlayerControllerSmokeTestCases();
mediarecorder.mediaRecorderSmokeTestCases();
musiccontentcenter.musicContentCenterSmokeTestCases();
rtcengine_debug.testCases();
}

mediaengine.mediaEngineSmokeTestCases();
mediaplayer.mediaPlayerControllerSmokeTestCases();
mediarecorder.mediaRecorderSmokeTestCases();
musiccontentcenter.musicContentCenterSmokeTestCases();
rtcengine_debug.testCases();
rtcengine.testCases();
rtcengineex.testCases();
videodevicemanager.videoDeviceManagerSmokeTestCases();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import 'package:flutter/foundation.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:integration_test/integration_test.dart';
import 'package:iris_tester/iris_tester.dart';
import 'apis_call_fake_test.dart';
import 'testcases/rtcengine_rtcengineeventhandler_testcases.dart'
as rtcengine_rtcengineeventhandler;
import 'generated/rtcengine_audiospectrumobserver_testcases.generated.dart'
Expand All @@ -26,42 +28,57 @@ import 'generated/mediarecorder_mediarecorderobserver_testcases.generated.dart'
import 'generated/musiccontentcenter_musiccontentcentereventhandler_testcases.generated.dart'
as musiccontentcenter_musiccontentcentereventhandler;
import 'package:agora_rtc_engine/src/impl/agora_rtc_engine_impl.dart';
import 'package:iris_method_channel/iris_method_channel.dart';

void main() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();

IrisTester irisTester = IrisTester();
IrisTester irisTester = createIrisTester();

setUp(() {
irisTester.initialize();
setMockRtcEngineNativeHandle(irisTester.getfakeRtcEngineHandle());
if (kIsWeb) {
setMockRtcEngineProvider(
TestInitilizationArgProvider(irisTester.getTesterArgs()));
} else {
// On IO, the function return from the `irisTester.getTesterArgs()` capture
// the `Pointer` from `IrisTester`, which is invalid to pass to the `Isolate`,
// so directly pass the `ObjectIrisHandle` as value to the `setMockRtcEngineProvider`
final value = irisTester.getTesterArgs()[0](const IrisApiEngineHandle(0));
setMockRtcEngineProvider(
TestInitilizationArgProvider.fromValue(ObjectIrisHandle(value)));
}
});

tearDown(() {
irisTester.dispose();
setMockRtcEngineNativeHandle(null);
setMockRtcEngineProvider(null);
});

// RtcEngine events
// RtcEngine events
rtcengine_rtcengineeventhandler.testCases(irisTester);
rtcengine_audiospectrumobserver.generatedTestCases(irisTester);
rtcengine_audioencodedframeobserver.generatedTestCases(irisTester);
rtcengine_metadataobserver.generatedTestCases(irisTester);

// MediaEngine events
mediaengine_videoframeobserver.generatedTestCases(irisTester);
mediaengine_videoencodedframeobserver.generatedTestCases(irisTester);
// These callbacks not are implemented on web
if (!kIsWeb) {
rtcengine_audiospectrumobserver.generatedTestCases(irisTester);
rtcengine_audioencodedframeobserver.generatedTestCases(irisTester);
rtcengine_metadataobserver.generatedTestCases(irisTester);

// MediaPlayerController events
mediaplayer_audiospectrumobserver.generatedTestCases(irisTester);
mediaplayer_audiopcmframesink.generatedTestCases(irisTester);
mediaplayer_mediaplayersourceobserver.generatedTestCases(irisTester);
mediaplayer_mediaplayervideoframeobserver.generatedTestCases(irisTester);
// MediaEngine events
mediaengine_videoframeobserver.generatedTestCases(irisTester);
mediaengine_videoencodedframeobserver.generatedTestCases(irisTester);

// MediaRecorder events
mediarecorder_mediarecorderobserver.generatedTestCases(irisTester);
// MediaPlayerController events
mediaplayer_audiospectrumobserver.generatedTestCases(irisTester);
mediaplayer_audiopcmframesink.generatedTestCases(irisTester);
mediaplayer_mediaplayersourceobserver.generatedTestCases(irisTester);
mediaplayer_mediaplayervideoframeobserver.generatedTestCases(irisTester);

// MusicContentCenter events
musiccontentcenter_musiccontentcentereventhandler
.generatedTestCases(irisTester);
// MediaRecorder events
mediarecorder_mediarecorderobserver.generatedTestCases(irisTester);

// MusicContentCenter events
musiccontentcenter_musiccontentcentereventhandler
.generatedTestCases(irisTester);
}
}
Loading
Loading