From 35248778e4c950d8bc652129ef4f80c621dd4167 Mon Sep 17 00:00:00 2001 From: Benny Daon Date: Thu, 3 Nov 2022 23:04:19 +0200 Subject: [PATCH 01/33] WIP: Initial draft of aatp --- aatp/.gitignore | 2 + aatp/README.md | 23 +++ aatp/datachannels/README.md | 37 +++++ aatp/datachannels/client/demo.css | 4 + aatp/datachannels/client/demo.details | 5 + aatp/datachannels/client/demo.html | 16 ++ aatp/datachannels/client/demo.js | 49 ++++++ aatp/datachannels/example.spec.ts | 131 +++++++++++++++ aatp/datachannels/lab.yaml | 30 ++++ aatp/datachannels/main.go | 96 +++++++++++ aatp/infra/pion/Dockerfile | 9 + aatp/infra/pion/docker_entry.sh | 13 ++ aatp/infra/pion/ssh_config | 7 + aatp/infra/runner/Dockerfile | 9 + aatp/infra/runner/package.json | 21 +++ aatp/infra/runner/yarn.lock | 227 ++++++++++++++++++++++++++ aatp/run | 79 +++++++++ 17 files changed, 758 insertions(+) create mode 100644 aatp/.gitignore create mode 100644 aatp/README.md create mode 100644 aatp/datachannels/README.md create mode 100644 aatp/datachannels/client/demo.css create mode 100644 aatp/datachannels/client/demo.details create mode 100644 aatp/datachannels/client/demo.html create mode 100644 aatp/datachannels/client/demo.js create mode 100644 aatp/datachannels/example.spec.ts create mode 100644 aatp/datachannels/lab.yaml create mode 100644 aatp/datachannels/main.go create mode 100644 aatp/infra/pion/Dockerfile create mode 100755 aatp/infra/pion/docker_entry.sh create mode 100644 aatp/infra/pion/ssh_config create mode 100644 aatp/infra/runner/Dockerfile create mode 100644 aatp/infra/runner/package.json create mode 100644 aatp/infra/runner/yarn.lock create mode 100755 aatp/run diff --git a/aatp/.gitignore b/aatp/.gitignore new file mode 100644 index 00000000000..c4e558971d5 --- /dev/null +++ b/aatp/.gitignore @@ -0,0 +1,2 @@ +rseult +assets diff --git a/aatp/README.md b/aatp/README.md new file mode 100644 index 00000000000..e338f9eb480 --- /dev/null +++ b/aatp/README.md @@ -0,0 +1,23 @@ +# Acceptance Test Procedure + +TL:DR; From the project's root `./aatp/test` + +This folder contains automated acceptance test procedures for webexec. +The tests are using docker-compose for lab setup and playwright +for end-to-end and browser testing. + +The script support some old style options, use `./aatp/test -h` to see the +current options. It also accepts one of more argument with a folder name. + +## The runner + +We use [playwright](https://playwright.dev) as the test runner and use +its syntax and expectations. To pass options to playwright use the +`PWARGS` enviornment variable. I use it to get the tests to stop +after the first failure and keep the logs short: + +``` +PWARGS=-x ./aatp/test ./aatp/accept +``` + +Run `npx playwright test --help` for its list of options diff --git a/aatp/datachannels/README.md b/aatp/datachannels/README.md new file mode 100644 index 00000000000..aef47a7461b --- /dev/null +++ b/aatp/datachannels/README.md @@ -0,0 +1,37 @@ +# data-channels + +data-channels is a Pion WebRTC application that shows how you can send/recv +DataChannel messages from a web browser + +## Testing suite + +The runner starts by + +### Download data-channels +``` +export GO111MODULE=on +go get github.com/pion/webrtc/v3/examples/data-channels +``` + +### Open data-channels example page +[jsfiddle.net](https://jsfiddle.net/9tsx15mg/90/) + +### Run data-channels, with your browsers SessionDescription as stdin +In the jsfiddle the top textarea is your browser's session description, copy that and: +#### Linux/macOS +Run `echo $BROWSER_SDP | data-channels` +#### Windows +1. Paste the SessionDescription into a file. +1. Run `data-channels < my_file` + +### Input data-channels's SessionDescription into your browser +Copy the text that `data-channels` just emitted and copy into second text area + +### Hit 'Start Session' in jsfiddle +Under Start Session you should see 'Checking' as it starts connecting. If everything worked you should see `New DataChannel foo 1` + +Now you can put whatever you want in the `Message` textarea, and when you hit `Send Message` it should appear in your terminal! + +Pion WebRTC will send random messages every 5 seconds that will appear in your browser. + +Congrats, you have used Pion WebRTC! Now start building something cool diff --git a/aatp/datachannels/client/demo.css b/aatp/datachannels/client/demo.css new file mode 100644 index 00000000000..9e43d340755 --- /dev/null +++ b/aatp/datachannels/client/demo.css @@ -0,0 +1,4 @@ +textarea { + width: 500px; + min-height: 75px; +} \ No newline at end of file diff --git a/aatp/datachannels/client/demo.details b/aatp/datachannels/client/demo.details new file mode 100644 index 00000000000..c7729b4ddda --- /dev/null +++ b/aatp/datachannels/client/demo.details @@ -0,0 +1,5 @@ +--- + name: data-channels + description: Example of using Pion WebRTC to communicate with a web browser using bi-direction DataChannels + authors: + - Sean DuBois diff --git a/aatp/datachannels/client/demo.html b/aatp/datachannels/client/demo.html new file mode 100644 index 00000000000..5a8823b580a --- /dev/null +++ b/aatp/datachannels/client/demo.html @@ -0,0 +1,16 @@ +Browser base64 Session Description
+
+ +Golang base64 Session Description
+
+
+ +
+ +Message
+
+
+ +
+Logs
+
\ No newline at end of file diff --git a/aatp/datachannels/client/demo.js b/aatp/datachannels/client/demo.js new file mode 100644 index 00000000000..16b466d3b89 --- /dev/null +++ b/aatp/datachannels/client/demo.js @@ -0,0 +1,49 @@ +/* eslint-env browser */ + +let pc = new RTCPeerConnection({ + iceServers: [ + { + urls: 'stun:stun.l.google.com:19302' + } + ] +}) +let log = msg => { + document.getElementById('logs').innerHTML += msg + '
' +} + +let sendChannel = pc.createDataChannel('foo') +sendChannel.onclose = () => console.log('sendChannel has closed') +sendChannel.onopen = () => console.log('sendChannel has opened') +sendChannel.onmessage = e => log(`Message from DataChannel '${sendChannel.label}' payload '${e.data}'`) + +pc.oniceconnectionstatechange = e => log(pc.iceConnectionState) +pc.onicecandidate = event => { + if (event.candidate === null) { + document.getElementById('localSessionDescription').value = btoa(JSON.stringify(pc.localDescription)) + } +} + +pc.onnegotiationneeded = e => + pc.createOffer().then(d => pc.setLocalDescription(d)).catch(log) + +window.sendMessage = () => { + let message = document.getElementById('message').value + if (message === '') { + return alert('Message must not be empty') + } + + sendChannel.send(message) +} + +window.startSession = () => { + let sd = document.getElementById('remoteSessionDescription').value + if (sd === '') { + return alert('Session Description must not be empty') + } + + try { + pc.setRemoteDescription(new RTCSessionDescription(JSON.parse(atob(sd)))) + } catch (e) { + alert(e) + } +} diff --git a/aatp/datachannels/example.spec.ts b/aatp/datachannels/example.spec.ts new file mode 100644 index 00000000000..8e466efba95 --- /dev/null +++ b/aatp/datachannels/example.spec.ts @@ -0,0 +1,131 @@ +import { Buffer } from 'node:buffer'; +import { test, expect, Page, BrowserContext } from '@playwright/test' +import { Client } from 'ssh2' +import { getOffer } from '../infra/lib' +import * as fs from 'fs' +import waitPort from 'wait-port' + +test.describe("pion's data channels example", () => { + + const sleep = (ms) => { return new Promise(r => setTimeout(r, ms)) } + + let page: Page, + context: BrowserContext + + test.beforeAll(async ({ browser }) => { + context = await browser.newContext() + page = await context.newPage() + page.on('console', (msg) => console.log('console log:', msg.text())) + page.on('pageerror', (err: Error) => console.log('PAGEERROR', err.message)) + const response = await page.goto("http://client/demo.html") + await expect(response.ok()).toBeTruthy() + }) + + test('can connect', async () => { + await sleep(2000) + const offer = await page.evalute(() => + document.getElementById('localSessionDescription').value + ) + let cmdClosed = false + let conn, stream + let sentCans = [] + try { + conn = await new Promise((resolve, reject) => { + const conn = new Client() + conn.on('error', e => reject(e)) + conn.on('ready', () => resolve(conn)) + conn.connect({ + host: 'pion', + port: 22, + username: 'pion', + password: 'pion' + }) + }) + } catch(e) { expect(e).toBeNull() } + // log key SSH events + conn.on('error', e => console.log("ssh error", e)) + conn.on('close', e => { + cmdClosed = true + console.log("ssh closed", e) + }) + conn.on('end', e => console.log("ssh ended", e)) + conn.on('keyboard-interactive', e => console.log("ssh interaction", e)) + try { + stream = await new Promise((resolve, reject) => { + conn.exec("webexec accept", { pty: true }, async (err, s) => { + if (err) + reject(err) + else + resolve(s) + }) + }) + } catch(e) { expect(e).toBeNull() } + let dataLines = 0 + let webexecCan = "" + stream.on('close', (code, signal) => { + console.log(`closed with ${signal}`) + cmdClosed = true + conn.end() + }).on('data', async (data) => { + let s + let b = new Buffer.from(data) + webexecCan += b.toString() + // remove the CR & LF in the end + if (webexecCan.slice(-1) == "\n") + webexecCan = webexecCan.slice(0, -2) + // ignore the leading READY + if (webexecCan == "READY") { + webexecCan = "" + return + } + try { + s = JSON.parse(webexecCan) + } catch(e) { return } + let found = sentCans.indexOf(webexecCan) + webexecCan = "" + if (found >= 0) { + return + } + await page.evaluate(async (can) => { + if (!can) + return + if (can.candidate) { + try { + await window.pc.addIceCandidate(can) + } catch(e) { expect(e).toBeNull() } + } else { + try { + await window.pc.setRemoteDescription(can) + } catch(e) { expect(e).toBeNull() } + } + + + }, s) + }).stderr.on('data', (data) => { + console.log("ERROR: " + data) + }) + const offer = await getOffer(page) + sentCans.push(offer) + stream.write(offer + "\n") + let pcState = null + while (pcState != "connected") { + let cans = [] + try { + cans = await page.evaluate(() => { + ret = window.candidates + window.candidates = [] + return ret + }) + } catch(e) { expect(e).toBeNull() } + cans.forEach((c) => { + const s = JSON.stringify(c) + stream.write(s+"\n") + sentCans.push(s) + }) + try { + pcState = await page.evaluate(() => window.pc.connectionState) + } catch(e) { expect(e).toBeNull() } + await sleep(500) + } + }) +}) diff --git a/aatp/datachannels/lab.yaml b/aatp/datachannels/lab.yaml new file mode 100644 index 00000000000..39a17418ad2 --- /dev/null +++ b/aatp/datachannels/lab.yaml @@ -0,0 +1,30 @@ +version: "3.9" +services: + runner: + build: + context: . + dockerfile: ./aatp/infra/runner/Dockerfile + volumes: + - ./aatp/datachannels:/suite + - ./aatp/result:/result + depends_on: + - client + - pion + environment: + PWARGS: ${PWARGS--x} + client: + image: halverneus/static-file-server:latest + environment: + PORT: 80 + expose: + - "80" + volumes: + - ./aatp/datachannels/client:/web + pion: + build: + context: . + dockerfile: ./aatp/infra/pion/Dockerfile + expose: + - "22" + volumes: + - ./aatp/datachannels:/source diff --git a/aatp/datachannels/main.go b/aatp/datachannels/main.go new file mode 100644 index 00000000000..89f74002cee --- /dev/null +++ b/aatp/datachannels/main.go @@ -0,0 +1,96 @@ +package main + +import ( + "fmt" + "time" + + "github.com/pion/webrtc/v3" + "github.com/pion/webrtc/v3/examples/internal/signal" +) + +func main() { + // Everything below is the Pion WebRTC API! Thanks for using it ❤️. + + // Prepare the configuration + config := webrtc.Configuration{ + ICEServers: []webrtc.ICEServer{ + { + URLs: []string{"stun:stun.l.google.com:19302"}, + }, + }, + } + + // Create a new RTCPeerConnection + peerConnection, err := webrtc.NewPeerConnection(config) + if err != nil { + panic(err) + } + + // Set the handler for ICE connection state + // This will notify you when the peer has connected/disconnected + peerConnection.OnICEConnectionStateChange(func(connectionState webrtc.ICEConnectionState) { + fmt.Printf("ICE Connection State has changed: %s\n", connectionState.String()) + }) + + // Register data channel creation handling + peerConnection.OnDataChannel(func(d *webrtc.DataChannel) { + fmt.Printf("New DataChannel %s %d\n", d.Label(), d.ID()) + + // Register channel opening handling + d.OnOpen(func() { + fmt.Printf("Data channel '%s'-'%d' open. Random messages will now be sent to any connected DataChannels every 5 seconds\n", d.Label(), d.ID()) + + for range time.NewTicker(5 * time.Second).C { + message := signal.RandSeq(15) + fmt.Printf("Sending '%s'\n", message) + + // Send the message as text + sendErr := d.SendText(message) + if sendErr != nil { + panic(sendErr) + } + } + }) + + // Register text message handling + d.OnMessage(func(msg webrtc.DataChannelMessage) { + fmt.Printf("Message from DataChannel '%s': '%s'\n", d.Label(), string(msg.Data)) + }) + }) + + // Wait for the offer to be pasted + offer := webrtc.SessionDescription{} + signal.Decode(signal.MustReadStdin(), &offer) + + // Set the remote SessionDescription + err = peerConnection.SetRemoteDescription(offer) + if err != nil { + panic(err) + } + + // Create an answer + answer, err := peerConnection.CreateAnswer(nil) + if err != nil { + panic(err) + } + + // Create channel that is blocked until ICE Gathering is complete + gatherComplete := webrtc.GatheringCompletePromise(peerConnection) + + // Sets the LocalDescription, and starts our UDP listeners + err = peerConnection.SetLocalDescription(answer) + if err != nil { + panic(err) + } + + // Block until ICE Gathering is complete, disabling trickle ICE + // we do this because we only can exchange one signaling message + // in a production application you should exchange ICE Candidates via OnICECandidate + <-gatherComplete + + // Output the answer in base64 so we can paste it in browser + fmt.Println(signal.Encode(*peerConnection.LocalDescription())) + + // Block forever + select {} +} diff --git a/aatp/infra/pion/Dockerfile b/aatp/infra/pion/Dockerfile new file mode 100644 index 00000000000..0f1dffc68de --- /dev/null +++ b/aatp/infra/pion/Dockerfile @@ -0,0 +1,9 @@ +FROM golang:bullseye +RUN apt update +RUN apt install -y git bash openssh-server +COPY ./aatp/infra/pion/ssh_config /etc/ssh/ +COPY ./aatp/infra/pion/docker_entry.sh /usr/local/bin +RUN /etc/init.d/ssh start +RUN useradd -s /bin/bash -d /home/pion -M -p '$y$j9T$6LsNr6MtK4Nt6NeECphjP1$Try0q9dVUdZGihzzxJZ0soO09wQhseYzyB/E2Jf4tO8' pion +WORKDIR /source +CMD go run . diff --git a/aatp/infra/pion/docker_entry.sh b/aatp/infra/pion/docker_entry.sh new file mode 100755 index 00000000000..66867c3d11c --- /dev/null +++ b/aatp/infra/pion/docker_entry.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash + +set -x +EXE="/assets/webexec" +CONF="/config/webexec" + +/etc/init.d/ssh start +cp $EXE /usr/local/bin +rm -rf /home/runner/.local +mkdir -p /home/runner/.config/webexec +cp -r "$CONF" /home/runner/.config/ +chown -R runner /home/runner +su -c "$EXE start --debug" runner diff --git a/aatp/infra/pion/ssh_config b/aatp/infra/pion/ssh_config new file mode 100644 index 00000000000..5626c673f76 --- /dev/null +++ b/aatp/infra/pion/ssh_config @@ -0,0 +1,7 @@ +Include /etc/ssh/ssh_config.d/*.conf + +Host * +PasswordAuthentication yes +SendEnv LANG LC_* +HashKnownHosts yes +GSSAPIAuthentication yes diff --git a/aatp/infra/runner/Dockerfile b/aatp/infra/runner/Dockerfile new file mode 100644 index 00000000000..595605db8c4 --- /dev/null +++ b/aatp/infra/runner/Dockerfile @@ -0,0 +1,9 @@ +FROM mcr.microsoft.com/playwright:v1.22.2-focal +ENV NODE_PATH="/usr/lib/node_modules" +RUN mkdir -p /aatp/CURRENT +WORKDIR /aatp/CURRENT +ADD ./aatp/infra ../infra +COPY ./aatp/infra/runner/package.json . +COPY ./aatp/infra/runner/yarn.lock . +RUN yarn install --frozen-lockfile +CMD cp /suite/*.spec.ts . && npx playwright test ${PWARGS} diff --git a/aatp/infra/runner/package.json b/aatp/infra/runner/package.json new file mode 100644 index 00000000000..6f039b28336 --- /dev/null +++ b/aatp/infra/runner/package.json @@ -0,0 +1,21 @@ +{ + "name": "terminal7-tester", + "version": "0.1.0", + "description": "A playwright based box testing for Terminal7", + "main": "runner.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "ISC", + "dependencies": { + "@playwright/test": "^1.22.2", + "playwright-chromium": "^1.22.2", + "playwright-firefox": "^1.22.2", + "playwright-webkit": "^1.22.2", + "redis": "<5", + "ssh2": "~1.11.0", + "wait-port": "^0.2.9", + "@types/node": "^18.7.18" + } +} diff --git a/aatp/infra/runner/yarn.lock b/aatp/infra/runner/yarn.lock new file mode 100644 index 00000000000..9653139008f --- /dev/null +++ b/aatp/infra/runner/yarn.lock @@ -0,0 +1,227 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@playwright/test@^1.22.2": + version "1.26.0" + resolved "https://registry.yarnpkg.com/@playwright/test/-/test-1.26.0.tgz#d0c4a7ffaa7df5b4a63e0d8dea133fdb1d6c5aef" + integrity sha512-D24pu1k/gQw3Lhbpc38G5bXlBjGDrH5A52MsrH12wz6ohGDeQ+aZg/JFSEsT/B3G8zlJe/EU4EkJK74hpqsjEg== + dependencies: + "@types/node" "*" + playwright-core "1.26.0" + +"@redis/bloom@1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@redis/bloom/-/bloom-1.0.2.tgz#42b82ec399a92db05e29fffcdfd9235a5fc15cdf" + integrity sha512-EBw7Ag1hPgFzdznK2PBblc1kdlj5B5Cw3XwI9/oG7tSn85/HKy3X9xHy/8tm/eNXJYHLXHJL/pkwBpFMVVefkw== + +"@redis/client@1.3.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@redis/client/-/client-1.3.0.tgz#c62ccd707f16370a2dc2f9e158a28b7da049fa77" + integrity sha512-XCFV60nloXAefDsPnYMjHGtvbtHR8fV5Om8cQ0JYqTNbWcQo/4AryzJ2luRj4blveWazRK/j40gES8M7Cp6cfQ== + dependencies: + cluster-key-slot "1.1.0" + generic-pool "3.8.2" + yallist "4.0.0" + +"@redis/graph@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@redis/graph/-/graph-1.0.1.tgz#eabc58ba99cd70d0c907169c02b55497e4ec8a99" + integrity sha512-oDE4myMCJOCVKYMygEMWuriBgqlS5FqdWerikMoJxzmmTUErnTRRgmIDa2VcgytACZMFqpAOWDzops4DOlnkfQ== + +"@redis/json@1.0.4": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@redis/json/-/json-1.0.4.tgz#f372b5f93324e6ffb7f16aadcbcb4e5c3d39bda1" + integrity sha512-LUZE2Gdrhg0Rx7AN+cZkb1e6HjoSKaeeW8rYnt89Tly13GBI5eP4CwDVr+MY8BAYfCg4/N15OUrtLoona9uSgw== + +"@redis/search@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@redis/search/-/search-1.1.0.tgz#7abb18d431f27ceafe6bcb4dd83a3fa67e9ab4df" + integrity sha512-NyFZEVnxIJEybpy+YskjgOJRNsfTYqaPbK/Buv6W2kmFNaRk85JiqjJZA5QkRmWvGbyQYwoO5QfDi2wHskKrQQ== + +"@redis/time-series@1.0.3": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@redis/time-series/-/time-series-1.0.3.tgz#4cfca8e564228c0bddcdf4418cba60c20b224ac4" + integrity sha512-OFp0q4SGrTH0Mruf6oFsHGea58u8vS/iI5+NpYdicaM+7BgqBZH8FFvNZ8rYYLrUO/QRqMq72NpXmxLVNcdmjA== + +"@types/node@*", "@types/node@^18.7.18": + version "18.7.23" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.7.23.tgz#75c580983846181ebe5f4abc40fe9dfb2d65665f" + integrity sha512-DWNcCHolDq0ZKGizjx2DZjR/PqsYwAcYUJmfMWqtVU2MBMG5Mo+xFZrhGId5r/O5HOuMPyQEcM6KUBp5lBZZBg== + +ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + +asn1@^0.2.4: + version "0.2.6" + resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.6.tgz#0d3a7bb6e64e02a90c0303b31f292868ea09a08d" + integrity sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ== + dependencies: + safer-buffer "~2.1.0" + +bcrypt-pbkdf@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" + integrity sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w== + dependencies: + tweetnacl "^0.14.3" + +buildcheck@0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/buildcheck/-/buildcheck-0.0.3.tgz#70451897a95d80f7807e68fc412eb2e7e35ff4d5" + integrity sha512-pziaA+p/wdVImfcbsZLNF32EiWyujlQLwolMqUQE8xpKNOH7KmZQaY8sXN7DGOEzPAElo9QTaeNRfGnf3iOJbA== + +chalk@^2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +cluster-key-slot@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/cluster-key-slot/-/cluster-key-slot-1.1.0.tgz#30474b2a981fb12172695833052bc0d01336d10d" + integrity sha512-2Nii8p3RwAPiFwsnZvukotvow2rIHM+yQ6ZcBXGHdniadkYGZYiGmkHJIbZPIV9nfv7m/U1IPMVVcAhoWFeklw== + +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== + +commander@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/commander/-/commander-3.0.2.tgz#6837c3fb677ad9933d1cfba42dd14d5117d6b39e" + integrity sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow== + +cpu-features@~0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/cpu-features/-/cpu-features-0.0.4.tgz#0023475bb4f4c525869c162e4108099e35bf19d8" + integrity sha512-fKiZ/zp1mUwQbnzb9IghXtHtDoTMtNeb8oYGx6kX2SYfhnG0HNdBEBIzB9b5KlXu5DQPhfy3mInbBxFcgwAr3A== + dependencies: + buildcheck "0.0.3" + nan "^2.15.0" + +debug@^4.1.1: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + +escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== + +generic-pool@3.8.2: + version "3.8.2" + resolved "https://registry.yarnpkg.com/generic-pool/-/generic-pool-3.8.2.tgz#aab4f280adb522fdfbdc5e5b64d718d3683f04e9" + integrity sha512-nGToKy6p3PAbYQ7p1UlWl6vSPwfwU6TMSWK7TTu+WUY4ZjyZQGniGGt2oNVvyNSpyZYSB43zMXVLcBm08MTMkg== + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +nan@^2.15.0, nan@^2.16.0: + version "2.16.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.16.0.tgz#664f43e45460fb98faf00edca0bb0d7b8dce7916" + integrity sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA== + +playwright-chromium@^1.22.2: + version "1.26.0" + resolved "https://registry.yarnpkg.com/playwright-chromium/-/playwright-chromium-1.26.0.tgz#fa4e75a2034a016b9e2e825fc6577f3efb0d2792" + integrity sha512-4hDiVmMKmtuHW5ne11S1HCQTdL+wytprQMhWYecEjMSIKBR1DJ3JLrcUDgqA0L5Jzi/CBKYQQk6TOVlTjXybXQ== + dependencies: + playwright-core "1.26.0" + +playwright-core@1.26.0: + version "1.26.0" + resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.26.0.tgz#850228f0638d410a5cdd69800d552f60e4d295cd" + integrity sha512-p8huU8eU4gD3VkJd3DA1nA7R3XA6rFvFL+1RYS96cSljCF2yJE9CWEHTPF4LqX8KN9MoWCrAfVKP5381X3CZqg== + +playwright-firefox@^1.22.2: + version "1.26.0" + resolved "https://registry.yarnpkg.com/playwright-firefox/-/playwright-firefox-1.26.0.tgz#4375e8c4eff71c169237260840cf13042527eb89" + integrity sha512-9cKbCBQo4VUeKUdBHkh5Cwx95DPbYr3JYlAJWJlAcItBqlTyxUSfXrptBA7zwZCMQ11cjBAVuumVRJhqOMplPQ== + dependencies: + playwright-core "1.26.0" + +playwright-webkit@^1.22.2: + version "1.26.0" + resolved "https://registry.yarnpkg.com/playwright-webkit/-/playwright-webkit-1.26.0.tgz#139f692d600c62cc34a5b59a6ec2fba2a18dd602" + integrity sha512-U9G4/pb4pRND3QF+Iv0JQGodIAbNLe02WSaW9DtQp91w4JkaZrP+iWfGGHCB409+rwiIfdCzVaWDp1ixfG1Mlw== + dependencies: + playwright-core "1.26.0" + +redis@<5: + version "4.3.1" + resolved "https://registry.yarnpkg.com/redis/-/redis-4.3.1.tgz#290532a0c22221e05e991162ac4dca1e1b2ff6da" + integrity sha512-cM7yFU5CA6zyCF7N/+SSTcSJQSRMEKN0k0Whhu6J7n9mmXRoXugfWDBo5iOzGwABmsWKSwGPTU5J4Bxbl+0mrA== + dependencies: + "@redis/bloom" "1.0.2" + "@redis/client" "1.3.0" + "@redis/graph" "1.0.1" + "@redis/json" "1.0.4" + "@redis/search" "1.1.0" + "@redis/time-series" "1.0.3" + +safer-buffer@~2.1.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +ssh2@~1.11.0: + version "1.11.0" + resolved "https://registry.yarnpkg.com/ssh2/-/ssh2-1.11.0.tgz#ce60186216971e12f6deb553dcf82322498fe2e4" + integrity sha512-nfg0wZWGSsfUe/IBJkXVll3PEZ//YH2guww+mP88gTpuSU4FtZN7zu9JoeTGOyCNx2dTDtT9fOpWwlzyj4uOOw== + dependencies: + asn1 "^0.2.4" + bcrypt-pbkdf "^1.0.2" + optionalDependencies: + cpu-features "~0.0.4" + nan "^2.16.0" + +supports-color@^5.3.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + +tweetnacl@^0.14.3: + version "0.14.5" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" + integrity sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA== + +wait-port@^0.2.9: + version "0.2.14" + resolved "https://registry.yarnpkg.com/wait-port/-/wait-port-0.2.14.tgz#6df40629be2c95aa4073ceb895abef7d872b28c6" + integrity sha512-kIzjWcr6ykl7WFbZd0TMae8xovwqcqbx6FM9l+7agOgUByhzdjfzZBPK2CPufldTOMxbUivss//Sh9MFawmPRQ== + dependencies: + chalk "^2.4.2" + commander "^3.0.2" + debug "^4.1.1" + +yallist@4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== diff --git a/aatp/run b/aatp/run new file mode 100755 index 00000000000..d1ff704a101 --- /dev/null +++ b/aatp/run @@ -0,0 +1,79 @@ +#!/usr/bin/env bash +BUILD=1 +build_n_run() { + + if [ $BUILD -eq 1 ] + then + docker compose -f $1 --project-directory . build $BUILD_OPTIONS + if [ $? -ne 0 ] + then + exit "docker compose build failed" + fi + fi + docker compose -f $1 --project-directory . up --exit-code-from runner +} +usage() { + cat < +options: + +h Print this usage +z Build the docker images from scratch before running +n Don't build the images + +EOS +} + +exit_error() { + usage + exit 1 +} +mkdir -p aatp/assets +while getopts ":hnz" option; do + echo "option " $option + case $option in + h) # display usage + usage + exit;; + n) # No Build + BUILD=0 + ;; + z) # No Cache + BUILD_OPTIONS="--no-cache" + ;; + \?) # Invalid option + echo "Error: Invalid option" + exit_error;; + esac +done +shift $((OPTIND-1)) +if [ $# -eq 0 ] +then + for compose in `find aatp -name "lab.yaml"` + do + dir=$(dirname $compose) + echo ">>> Setting a lab based on $dir" + build_n_run $compose + if [ $? -ne 0 ] + then + echo ">>> $dir tests FAILED" + exit 4 + fi + done +else + for arg in $@ + do + echo ">>> Setting a lab based on $arg" + build_n_run $arg/lab.yaml + if [ $? -ne 0 ] + then + echo ">>> $arg FAILED" + exit 4 + fi + echo ">>> $arg tests PASSED" + done +fi From 51f188f1de2f7994ccc8187be9b085ae3524fb8e Mon Sep 17 00:00:00 2001 From: Benny Daon Date: Thu, 17 Nov 2022 13:49:28 +0200 Subject: [PATCH 02/33] Renaming aatp to ats --- aatp/datachannels/client/demo.css | 4 -- aatp/datachannels/client/demo.details | 5 --- aatp/datachannels/client/demo.html | 16 ------- aatp/datachannels/client/demo.js | 49 ---------------------- {aatp => ats}/.gitignore | 0 {aatp => ats}/README.md | 12 +++--- {aatp => ats}/datachannels/README.md | 0 ats/datachannels/client | 1 + {aatp => ats}/datachannels/example.spec.ts | 0 {aatp => ats}/datachannels/lab.yaml | 12 +++--- {aatp => ats}/datachannels/main.go | 0 {aatp => ats}/infra/pion/Dockerfile | 4 +- {aatp => ats}/infra/pion/docker_entry.sh | 0 {aatp => ats}/infra/pion/ssh_config | 0 {aatp => ats}/infra/runner/Dockerfile | 10 ++--- {aatp => ats}/infra/runner/package.json | 0 {aatp => ats}/infra/runner/yarn.lock | 0 {aatp => ats}/run | 6 +-- 18 files changed, 23 insertions(+), 96 deletions(-) delete mode 100644 aatp/datachannels/client/demo.css delete mode 100644 aatp/datachannels/client/demo.details delete mode 100644 aatp/datachannels/client/demo.html delete mode 100644 aatp/datachannels/client/demo.js rename {aatp => ats}/.gitignore (100%) rename {aatp => ats}/README.md (58%) rename {aatp => ats}/datachannels/README.md (100%) create mode 120000 ats/datachannels/client rename {aatp => ats}/datachannels/example.spec.ts (100%) rename {aatp => ats}/datachannels/lab.yaml (60%) rename {aatp => ats}/datachannels/main.go (100%) rename {aatp => ats}/infra/pion/Dockerfile (72%) rename {aatp => ats}/infra/pion/docker_entry.sh (100%) rename {aatp => ats}/infra/pion/ssh_config (100%) rename {aatp => ats}/infra/runner/Dockerfile (54%) rename {aatp => ats}/infra/runner/package.json (100%) rename {aatp => ats}/infra/runner/yarn.lock (100%) rename {aatp => ats}/run (91%) diff --git a/aatp/datachannels/client/demo.css b/aatp/datachannels/client/demo.css deleted file mode 100644 index 9e43d340755..00000000000 --- a/aatp/datachannels/client/demo.css +++ /dev/null @@ -1,4 +0,0 @@ -textarea { - width: 500px; - min-height: 75px; -} \ No newline at end of file diff --git a/aatp/datachannels/client/demo.details b/aatp/datachannels/client/demo.details deleted file mode 100644 index c7729b4ddda..00000000000 --- a/aatp/datachannels/client/demo.details +++ /dev/null @@ -1,5 +0,0 @@ ---- - name: data-channels - description: Example of using Pion WebRTC to communicate with a web browser using bi-direction DataChannels - authors: - - Sean DuBois diff --git a/aatp/datachannels/client/demo.html b/aatp/datachannels/client/demo.html deleted file mode 100644 index 5a8823b580a..00000000000 --- a/aatp/datachannels/client/demo.html +++ /dev/null @@ -1,16 +0,0 @@ -Browser base64 Session Description
-
- -Golang base64 Session Description
-
-
- -
- -Message
-
-
- -
-Logs
-
\ No newline at end of file diff --git a/aatp/datachannels/client/demo.js b/aatp/datachannels/client/demo.js deleted file mode 100644 index 16b466d3b89..00000000000 --- a/aatp/datachannels/client/demo.js +++ /dev/null @@ -1,49 +0,0 @@ -/* eslint-env browser */ - -let pc = new RTCPeerConnection({ - iceServers: [ - { - urls: 'stun:stun.l.google.com:19302' - } - ] -}) -let log = msg => { - document.getElementById('logs').innerHTML += msg + '
' -} - -let sendChannel = pc.createDataChannel('foo') -sendChannel.onclose = () => console.log('sendChannel has closed') -sendChannel.onopen = () => console.log('sendChannel has opened') -sendChannel.onmessage = e => log(`Message from DataChannel '${sendChannel.label}' payload '${e.data}'`) - -pc.oniceconnectionstatechange = e => log(pc.iceConnectionState) -pc.onicecandidate = event => { - if (event.candidate === null) { - document.getElementById('localSessionDescription').value = btoa(JSON.stringify(pc.localDescription)) - } -} - -pc.onnegotiationneeded = e => - pc.createOffer().then(d => pc.setLocalDescription(d)).catch(log) - -window.sendMessage = () => { - let message = document.getElementById('message').value - if (message === '') { - return alert('Message must not be empty') - } - - sendChannel.send(message) -} - -window.startSession = () => { - let sd = document.getElementById('remoteSessionDescription').value - if (sd === '') { - return alert('Session Description must not be empty') - } - - try { - pc.setRemoteDescription(new RTCSessionDescription(JSON.parse(atob(sd)))) - } catch (e) { - alert(e) - } -} diff --git a/aatp/.gitignore b/ats/.gitignore similarity index 100% rename from aatp/.gitignore rename to ats/.gitignore diff --git a/aatp/README.md b/ats/README.md similarity index 58% rename from aatp/README.md rename to ats/README.md index e338f9eb480..269c5241947 100644 --- a/aatp/README.md +++ b/ats/README.md @@ -1,13 +1,13 @@ -# Acceptance Test Procedure +# Acceptance Test Specifications -TL:DR; From the project's root `./aatp/test` +TL:DR; From the project's root `./ats/test` -This folder contains automated acceptance test procedures for webexec. +This folder contains automated acceptance test specifications. The tests are using docker-compose for lab setup and playwright for end-to-end and browser testing. -The script support some old style options, use `./aatp/test -h` to see the -current options. It also accepts one of more argument with a folder name. +The script support some old style options, use `./ats/test -h` to see the +all the options. It also accepts one of more argument with a folder name. ## The runner @@ -17,7 +17,7 @@ its syntax and expectations. To pass options to playwright use the after the first failure and keep the logs short: ``` -PWARGS=-x ./aatp/test ./aatp/accept +PWARGS=-x ./ats/test ./ats/accept ``` Run `npx playwright test --help` for its list of options diff --git a/aatp/datachannels/README.md b/ats/datachannels/README.md similarity index 100% rename from aatp/datachannels/README.md rename to ats/datachannels/README.md diff --git a/ats/datachannels/client b/ats/datachannels/client new file mode 120000 index 00000000000..9fb0a7dbebc --- /dev/null +++ b/ats/datachannels/client @@ -0,0 +1 @@ +./examples/data-channels/jsfiddle \ No newline at end of file diff --git a/aatp/datachannels/example.spec.ts b/ats/datachannels/example.spec.ts similarity index 100% rename from aatp/datachannels/example.spec.ts rename to ats/datachannels/example.spec.ts diff --git a/aatp/datachannels/lab.yaml b/ats/datachannels/lab.yaml similarity index 60% rename from aatp/datachannels/lab.yaml rename to ats/datachannels/lab.yaml index 39a17418ad2..3f62939b2c1 100644 --- a/aatp/datachannels/lab.yaml +++ b/ats/datachannels/lab.yaml @@ -3,10 +3,10 @@ services: runner: build: context: . - dockerfile: ./aatp/infra/runner/Dockerfile + dockerfile: ./ats/infra/runner/Dockerfile volumes: - - ./aatp/datachannels:/suite - - ./aatp/result:/result + - ./ats/datachannels:/suite + - ./ats/result:/result depends_on: - client - pion @@ -19,12 +19,12 @@ services: expose: - "80" volumes: - - ./aatp/datachannels/client:/web + - ./ats/datachannels/client:/web pion: build: context: . - dockerfile: ./aatp/infra/pion/Dockerfile + dockerfile: ./ats/infra/pion/Dockerfile expose: - "22" volumes: - - ./aatp/datachannels:/source + - ./ats/datachannels:/source diff --git a/aatp/datachannels/main.go b/ats/datachannels/main.go similarity index 100% rename from aatp/datachannels/main.go rename to ats/datachannels/main.go diff --git a/aatp/infra/pion/Dockerfile b/ats/infra/pion/Dockerfile similarity index 72% rename from aatp/infra/pion/Dockerfile rename to ats/infra/pion/Dockerfile index 0f1dffc68de..8a332b93f86 100644 --- a/aatp/infra/pion/Dockerfile +++ b/ats/infra/pion/Dockerfile @@ -1,8 +1,8 @@ FROM golang:bullseye RUN apt update RUN apt install -y git bash openssh-server -COPY ./aatp/infra/pion/ssh_config /etc/ssh/ -COPY ./aatp/infra/pion/docker_entry.sh /usr/local/bin +COPY ./ats/infra/pion/ssh_config /etc/ssh/ +COPY ./ats/infra/pion/docker_entry.sh /usr/local/bin RUN /etc/init.d/ssh start RUN useradd -s /bin/bash -d /home/pion -M -p '$y$j9T$6LsNr6MtK4Nt6NeECphjP1$Try0q9dVUdZGihzzxJZ0soO09wQhseYzyB/E2Jf4tO8' pion WORKDIR /source diff --git a/aatp/infra/pion/docker_entry.sh b/ats/infra/pion/docker_entry.sh similarity index 100% rename from aatp/infra/pion/docker_entry.sh rename to ats/infra/pion/docker_entry.sh diff --git a/aatp/infra/pion/ssh_config b/ats/infra/pion/ssh_config similarity index 100% rename from aatp/infra/pion/ssh_config rename to ats/infra/pion/ssh_config diff --git a/aatp/infra/runner/Dockerfile b/ats/infra/runner/Dockerfile similarity index 54% rename from aatp/infra/runner/Dockerfile rename to ats/infra/runner/Dockerfile index 595605db8c4..ab4df06768c 100644 --- a/aatp/infra/runner/Dockerfile +++ b/ats/infra/runner/Dockerfile @@ -1,9 +1,9 @@ FROM mcr.microsoft.com/playwright:v1.22.2-focal ENV NODE_PATH="/usr/lib/node_modules" -RUN mkdir -p /aatp/CURRENT -WORKDIR /aatp/CURRENT -ADD ./aatp/infra ../infra -COPY ./aatp/infra/runner/package.json . -COPY ./aatp/infra/runner/yarn.lock . +RUN mkdir -p /ats/CURRENT +WORKDIR /ats/CURRENT +ADD ./ats/infra ../infra +COPY ./ats/infra/runner/package.json . +COPY ./ats/infra/runner/yarn.lock . RUN yarn install --frozen-lockfile CMD cp /suite/*.spec.ts . && npx playwright test ${PWARGS} diff --git a/aatp/infra/runner/package.json b/ats/infra/runner/package.json similarity index 100% rename from aatp/infra/runner/package.json rename to ats/infra/runner/package.json diff --git a/aatp/infra/runner/yarn.lock b/ats/infra/runner/yarn.lock similarity index 100% rename from aatp/infra/runner/yarn.lock rename to ats/infra/runner/yarn.lock diff --git a/aatp/run b/ats/run similarity index 91% rename from aatp/run rename to ats/run index d1ff704a101..317eed7cc2e 100755 --- a/aatp/run +++ b/ats/run @@ -15,7 +15,7 @@ build_n_run() { usage() { cat < @@ -32,7 +32,7 @@ exit_error() { usage exit 1 } -mkdir -p aatp/assets +mkdir -p ats/assets while getopts ":hnz" option; do echo "option " $option case $option in @@ -53,7 +53,7 @@ done shift $((OPTIND-1)) if [ $# -eq 0 ] then - for compose in `find aatp -name "lab.yaml"` + for compose in `find ats -name "lab.yaml"` do dir=$(dirname $compose) echo ">>> Setting a lab based on $dir" From 5f8f2adac1afe2fc5127655375566799e4bbc2aa Mon Sep 17 00:00:00 2001 From: Benny Daon Date: Mon, 25 Oct 2021 13:32:49 +0300 Subject: [PATCH 03/33] Use OnOpen handler for DataChannels Using an improvment of pion/datachannel, the channel opener can now set an event to be called when the DATA_CHANNEL_ACK message is recieved Resolves #1063 Relates to pion/datachannel#81 --- go.sum | 30 ++++++++++++++++++++++++++++++ sctptransport.go | 4 ++++ 2 files changed, 34 insertions(+) diff --git a/go.sum b/go.sum index 6989fe990b4..5bc98f25479 100644 --- a/go.sum +++ b/go.sum @@ -38,6 +38,7 @@ github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +<<<<<<< HEAD github.com/onsi/gomega v1.17.0 h1:9Luw4uT5HTjHTN8+aNcSThgH1vdXnmdJ8xIfZ4wyTRE= github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/pion/datachannel v1.5.2 h1:piB93s8LGmbECrpO84DnkIVWasRMk3IimbcXkTQLE6E= @@ -48,12 +49,26 @@ github.com/pion/ice/v2 v2.2.11 h1:wiAy7TSrVZ4KdyjC0CcNTkwltz9ywetbe4wbHLKUbIg= github.com/pion/ice/v2 v2.2.11/go.mod h1:NqUDUao6SjSs1+4jrqpexDmFlptlVhGxQjcymXLaVvE= github.com/pion/interceptor v0.1.11 h1:00U6OlqxA3FFB50HSg25J/8cWi7P6FbSzw4eFn24Bvs= github.com/pion/interceptor v0.1.11/go.mod h1:tbtKjZY14awXd7Bq0mmWvgtHB5MDaRN7HV3OZ/uy7s8= +======= +github.com/onsi/gomega v1.11.0 h1:+CqWgvj0OZycCaqclBD1pxKHAU+tOkHmQIWvDHq2aug= +github.com/onsi/gomega v1.11.0/go.mod h1:azGKhqFUon9Vuj0YmTfLSmx0FUwqXYSTl5re8lQLTUg= +github.com/pion/datachannel v1.5.0 h1:Jy6xWr9hysxet69qP23ibiJ6M0P30ZRnndHU+N6cpkY= +github.com/pion/datachannel v1.5.0/go.mod h1:TVbgWP+PVM9TlwL1IkG3JqXXfjGxLvsu9QUeFdpTegI= +github.com/pion/dtls/v2 v2.0.9/go.mod h1:O0Wr7si/Zj5/EBFlDzDd6UtVxx25CE1r7XM7BQKYQho= +github.com/pion/dtls/v2 v2.0.10 h1:wgys7gPR1NMbWjmjJ3CW7lkUGaun8djgH8nahpNLnxI= +github.com/pion/dtls/v2 v2.0.10/go.mod h1:00OxfeCRWHShcqT9jx8pKKmBWuTt0NCZoVPCaC4VKvU= +github.com/pion/ice/v2 v2.1.13 h1:/YNYcIw56LT/whwuzkTnrprcRnapj2ZNqUsR0W8elmo= +github.com/pion/ice/v2 v2.1.13/go.mod h1:ovgYHUmwYLlRvcCLI67PnQ5YGe+upXZbGgllBDG/ktU= +github.com/pion/interceptor v0.1.0 h1:SlXKaDlEvSl7cr4j8fJykzVz4UdH+7UDtcvx+u01wLU= +github.com/pion/interceptor v0.1.0/go.mod h1:j5NIl3tJJPB3u8+Z2Xz8MZs/VV6rc+If9mXEKNuFmEM= +>>>>>>> c5faa92 (Use OnOpen handler for DataChannels) github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY= github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms= github.com/pion/mdns v0.0.5 h1:Q2oj/JB3NqfzY9xGZ1fPzZzK7sDSD8rZPOvcIQ10BCw= github.com/pion/mdns v0.0.5/go.mod h1:UgssrvdD3mxpi8tMxAXbsppL3vJ4Jipw1mTCW+al01g= github.com/pion/randutil v0.1.0 h1:CFG1UdESneORglEsnimhUjf33Rwjubwj6xfiOXBa3mA= github.com/pion/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8= +<<<<<<< HEAD github.com/pion/rtcp v1.2.9/go.mod h1:qVPhiCzAm4D/rxb6XzKeyZiQK69yJpbUDJSF7TgrqNo= github.com/pion/rtcp v1.2.10 h1:nkr3uj+8Sp97zyItdN60tE/S6vk4al5CPRR6Gejsdjc= github.com/pion/rtcp v1.2.10/go.mod h1:ztfEwXZNLGyF1oQDttz/ZKIBaeeg/oWbRYqzBM9TL1I= @@ -66,6 +81,21 @@ github.com/pion/sdp/v3 v3.0.6 h1:WuDLhtuFUUVpTfus9ILC4HRyHsW6TdugjEX/QY9OiUw= github.com/pion/sdp/v3 v3.0.6/go.mod h1:iiFWFpQO8Fy3S5ldclBkpXqmWy02ns78NOKoLLL0YQw= github.com/pion/srtp/v2 v2.0.10 h1:b8ZvEuI+mrL8hbr/f1YiJFB34UMrOac3R3N1yq2UN0w= github.com/pion/srtp/v2 v2.0.10/go.mod h1:XEeSWaK9PfuMs7zxXyiN252AHPbH12NX5q/CFDWtUuA= +======= +github.com/pion/rtcp v1.2.6/go.mod h1:52rMNPWFsjr39z9B9MhnkqhPLoeHTv1aN63o/42bWE0= +github.com/pion/rtcp v1.2.8 h1:Cys8X6r0xxU65ESTmXkqr8eU1Q1Wx+lNkoZCUH4zD7E= +github.com/pion/rtcp v1.2.8/go.mod h1:qVPhiCzAm4D/rxb6XzKeyZiQK69yJpbUDJSF7TgrqNo= +github.com/pion/rtp v1.7.0/go.mod h1:bDb5n+BFZxXx0Ea7E5qe+klMuqiBrP+w8XSjiWtCUko= +github.com/pion/rtp v1.7.2/go.mod h1:bDb5n+BFZxXx0Ea7E5qe+klMuqiBrP+w8XSjiWtCUko= +github.com/pion/rtp v1.7.4 h1:4dMbjb1SuynU5OpA3kz1zHK+u+eOCQjW3MAeVHf1ODA= +github.com/pion/rtp v1.7.4/go.mod h1:bDb5n+BFZxXx0Ea7E5qe+klMuqiBrP+w8XSjiWtCUko= +github.com/pion/sctp v1.7.12 h1:GsatLufywVruXbZZT1CKg+Jr8ZTkwiPnmUC/oO9+uuY= +github.com/pion/sctp v1.7.12/go.mod h1:xFe9cLMZ5Vj6eOzpyiKjT9SwGM4KpK/8Jbw5//jc+0s= +github.com/pion/sdp/v3 v3.0.4 h1:2Kf+dgrzJflNCSw3TV5v2VLeI0s/qkzy2r5jlR0wzf8= +github.com/pion/sdp/v3 v3.0.4/go.mod h1:bNiSknmJE0HYBprTHXKPQ3+JjacTv5uap92ueJZKsRk= +github.com/pion/srtp/v2 v2.0.5 h1:ks3wcTvIUE/GHndO3FAvROQ9opy0uLELpwHJaQ1yqhQ= +github.com/pion/srtp/v2 v2.0.5/go.mod h1:8k6AJlal740mrZ6WYxc4Dg6qDqqhxoRG2GSjlUhDF0A= +>>>>>>> c5faa92 (Use OnOpen handler for DataChannels) github.com/pion/stun v0.3.5 h1:uLUCBCkQby4S1cf6CGuR9QrVOKcvUwFeemaC865QHDg= github.com/pion/stun v0.3.5/go.mod h1:gDMim+47EeEtfWogA37n6qXZS88L5V6LqFcf+DZA2UA= github.com/pion/transport v0.12.2/go.mod h1:N3+vZQD9HlDP5GWkZ85LohxNsDcNgofQmyL6ojX5d8Q= diff --git a/sctptransport.go b/sctptransport.go index db7b25256cb..f5a4071d90e 100644 --- a/sctptransport.go +++ b/sctptransport.go @@ -232,7 +232,11 @@ ACCEPT: } <-r.onDataChannel(rtcDC) +<<<<<<< HEAD rtcDC.handleOpen(dc, true, dc.Config.Negotiated) +======= + rtcDC.handleOpen(dc, true) +>>>>>>> c5faa92 (Use OnOpen handler for DataChannels) r.lock.Lock() r.dataChannelsOpened++ From 9c4a06af203a2561abe504e3314597f179eeee65 Mon Sep 17 00:00:00 2001 From: Benny Daon Date: Sun, 20 Nov 2022 11:56:04 +0200 Subject: [PATCH 04/33] Coding the dc example spec --- ats/datachannels/client | 2 +- ats/datachannels/example.spec.ts | 92 +++++++++-------------- ats/datachannels/lab.yaml | 6 +- ats/datachannels/pion_entrypoint.sh | 6 ++ ats/infra/pion/Dockerfile | 2 + examples/data-channels/jsfiddle/demo.html | 6 +- 6 files changed, 50 insertions(+), 64 deletions(-) create mode 100755 ats/datachannels/pion_entrypoint.sh diff --git a/ats/datachannels/client b/ats/datachannels/client index 9fb0a7dbebc..e71880f0478 120000 --- a/ats/datachannels/client +++ b/ats/datachannels/client @@ -1 +1 @@ -./examples/data-channels/jsfiddle \ No newline at end of file +../../examples/data-channels/jsfiddle \ No newline at end of file diff --git a/ats/datachannels/example.spec.ts b/ats/datachannels/example.spec.ts index 8e466efba95..0c3a3c12510 100644 --- a/ats/datachannels/example.spec.ts +++ b/ats/datachannels/example.spec.ts @@ -1,9 +1,6 @@ import { Buffer } from 'node:buffer'; import { test, expect, Page, BrowserContext } from '@playwright/test' import { Client } from 'ssh2' -import { getOffer } from '../infra/lib' -import * as fs from 'fs' -import waitPort from 'wait-port' test.describe("pion's data channels example", () => { @@ -19,16 +16,17 @@ test.describe("pion's data channels example", () => { page.on('pageerror', (err: Error) => console.log('PAGEERROR', err.message)) const response = await page.goto("http://client/demo.html") await expect(response.ok()).toBeTruthy() + await page.evaluate(() => { + var newScript = document.createElement('script'); + newScript.type = 'text/javascript'; + newScript.src = '/demo.js'; + document.getElementsByTagName('head')[0].appendChild(newScript); + }) }) test('can connect', async () => { - await sleep(2000) - const offer = await page.evalute(() => - document.getElementById('localSessionDescription').value - ) let cmdClosed = false let conn, stream - let sentCans = [] try { conn = await new Promise((resolve, reject) => { const conn = new Client() @@ -52,7 +50,7 @@ test.describe("pion's data channels example", () => { conn.on('keyboard-interactive', e => console.log("ssh interaction", e)) try { stream = await new Promise((resolve, reject) => { - conn.exec("webexec accept", { pty: true }, async (err, s) => { + conn.exec("/usr/local/go/bin/go run /source/examples/data-channels", { pty: true }, async (err, s) => { if (err) reject(err) else @@ -62,6 +60,8 @@ test.describe("pion's data channels example", () => { } catch(e) { expect(e).toBeNull() } let dataLines = 0 let webexecCan = "" + let finished = false + let lineCounter = 0 stream.on('close', (code, signal) => { console.log(`closed with ${signal}`) cmdClosed = true @@ -69,62 +69,38 @@ test.describe("pion's data channels example", () => { }).on('data', async (data) => { let s let b = new Buffer.from(data) - webexecCan += b.toString() + + console.log("got data from data-channels", b.toString()) // remove the CR & LF in the end - if (webexecCan.slice(-1) == "\n") - webexecCan = webexecCan.slice(0, -2) + // if (webexecCan.slice(-1) == "\n") + // webexecCan = webexecCan.slice(0, -2) // ignore the leading READY - if (webexecCan == "READY") { - webexecCan = "" - return - } - try { - s = JSON.parse(webexecCan) - } catch(e) { return } - let found = sentCans.indexOf(webexecCan) - webexecCan = "" - if (found >= 0) { - return + switch(lineCounter++) { + case 0: + await page.evaluate(async (answer) => + document.getElementById("remoteSessionDescription").value = answer, + b.toString()) + page.locator("data-test-id=start-session").click() + await sleep(3000) + await page.evaluate(async () => + document.getElementById("message").value = "BADFACE") + await page.locator("data-test-id=send-message").click() + break + case 1: + expect(b.toString()).toEqual("BADFACE") + finished = true + break } - await page.evaluate(async (can) => { - if (!can) - return - if (can.candidate) { - try { - await window.pc.addIceCandidate(can) - } catch(e) { expect(e).toBeNull() } - } else { - try { - await window.pc.setRemoteDescription(can) - } catch(e) { expect(e).toBeNull() } - } - - - }, s) }).stderr.on('data', (data) => { console.log("ERROR: " + data) }) - const offer = await getOffer(page) - sentCans.push(offer) + let offer + while (!offer) { + await sleep(200) + offer = await page.evaluate(() => document.getElementById('localSessionDescription').value) + } stream.write(offer + "\n") - let pcState = null - while (pcState != "connected") { - let cans = [] - try { - cans = await page.evaluate(() => { - ret = window.candidates - window.candidates = [] - return ret - }) - } catch(e) { expect(e).toBeNull() } - cans.forEach((c) => { - const s = JSON.stringify(c) - stream.write(s+"\n") - sentCans.push(s) - }) - try { - pcState = await page.evaluate(() => window.pc.connectionState) - } catch(e) { expect(e).toBeNull() } + while (!finished) { await sleep(500) } }) diff --git a/ats/datachannels/lab.yaml b/ats/datachannels/lab.yaml index 3f62939b2c1..953ffb17fd0 100644 --- a/ats/datachannels/lab.yaml +++ b/ats/datachannels/lab.yaml @@ -19,7 +19,7 @@ services: expose: - "80" volumes: - - ./ats/datachannels/client:/web + - ./examples/data-channels/jsfiddle:/web pion: build: context: . @@ -27,4 +27,6 @@ services: expose: - "22" volumes: - - ./ats/datachannels:/source + - .:/source + entrypoint: /source/ats/datachannels/pion_entrypoint.sh + diff --git a/ats/datachannels/pion_entrypoint.sh b/ats/datachannels/pion_entrypoint.sh new file mode 100755 index 00000000000..1017651d1d8 --- /dev/null +++ b/ats/datachannels/pion_entrypoint.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash +/etc/init.d/ssh start +while true +do + sleep 10 +done diff --git a/ats/infra/pion/Dockerfile b/ats/infra/pion/Dockerfile index 8a332b93f86..ea0c8b70681 100644 --- a/ats/infra/pion/Dockerfile +++ b/ats/infra/pion/Dockerfile @@ -5,5 +5,7 @@ COPY ./ats/infra/pion/ssh_config /etc/ssh/ COPY ./ats/infra/pion/docker_entry.sh /usr/local/bin RUN /etc/init.d/ssh start RUN useradd -s /bin/bash -d /home/pion -M -p '$y$j9T$6LsNr6MtK4Nt6NeECphjP1$Try0q9dVUdZGihzzxJZ0soO09wQhseYzyB/E2Jf4tO8' pion +RUN mkdir /home/pion +RUN chown pion /home/pion WORKDIR /source CMD go run . diff --git a/examples/data-channels/jsfiddle/demo.html b/examples/data-channels/jsfiddle/demo.html index b50aa880c4e..d1aab37c16e 100644 --- a/examples/data-channels/jsfiddle/demo.html +++ b/examples/data-channels/jsfiddle/demo.html @@ -8,14 +8,14 @@ Golang base64 Session Description

-
+

Message

-
+

Logs
-
\ No newline at end of file +
From aca9b46785693b439fb33c1dd07bf8a0cb461773 Mon Sep 17 00:00:00 2001 From: Benny Daon Date: Sun, 20 Nov 2022 20:59:19 +0200 Subject: [PATCH 05/33] Fixing the datchannel example test --- ats/datachannels/example.spec.ts | 51 ++++++++++++++--------------- ats/datachannels/pion_entrypoint.sh | 1 + examples/data-channels/main.go | 5 +-- 3 files changed, 28 insertions(+), 29 deletions(-) diff --git a/ats/datachannels/example.spec.ts b/ats/datachannels/example.spec.ts index 0c3a3c12510..f5cec1d8f86 100644 --- a/ats/datachannels/example.spec.ts +++ b/ats/datachannels/example.spec.ts @@ -48,9 +48,16 @@ test.describe("pion's data channels example", () => { }) conn.on('end', e => console.log("ssh ended", e)) conn.on('keyboard-interactive', e => console.log("ssh interaction", e)) + let offer + while (!offer) { + await sleep(200) + offer = await page.evaluate(() => document.getElementById('localSessionDescription').value) + } try { stream = await new Promise((resolve, reject) => { - conn.exec("/usr/local/go/bin/go run /source/examples/data-channels", { pty: true }, async (err, s) => { + + conn.exec(`bash -c 'cd /source; echo ${offer} | /go/bin/data-channels'`, + { pty: true }, async (err, s) => { if (err) reject(err) else @@ -66,40 +73,30 @@ test.describe("pion's data channels example", () => { console.log(`closed with ${signal}`) cmdClosed = true conn.end() - }).on('data', async (data) => { - let s - let b = new Buffer.from(data) - - console.log("got data from data-channels", b.toString()) - // remove the CR & LF in the end - // if (webexecCan.slice(-1) == "\n") - // webexecCan = webexecCan.slice(0, -2) - // ignore the leading READY - switch(lineCounter++) { - case 0: + }).on('data', lines => + new Buffer.from(lines).toString().split("\r\n").forEach(async line => { + if (!line) + return + lineCounter++ + if (lineCounter == 1) { await page.evaluate(async (answer) => - document.getElementById("remoteSessionDescription").value = answer, - b.toString()) + document.getElementById("remoteSessionDescription") + .value = answer, + line) page.locator("data-test-id=start-session").click() await sleep(3000) await page.evaluate(async () => document.getElementById("message").value = "BADFACE") await page.locator("data-test-id=send-message").click() - break - case 1: - expect(b.toString()).toEqual("BADFACE") - finished = true - break - } - }).stderr.on('data', (data) => { + return + } + if (line.includes("BADFACE")) + finished=true + }) + ).stderr.on('data', (data) => { console.log("ERROR: " + data) }) - let offer - while (!offer) { - await sleep(200) - offer = await page.evaluate(() => document.getElementById('localSessionDescription').value) - } - stream.write(offer + "\n") + expect(page.locator("#logs")).toHaveText(/Random messages will now be sent/) while (!finished) { await sleep(500) } diff --git a/ats/datachannels/pion_entrypoint.sh b/ats/datachannels/pion_entrypoint.sh index 1017651d1d8..a5c1067bf90 100755 --- a/ats/datachannels/pion_entrypoint.sh +++ b/ats/datachannels/pion_entrypoint.sh @@ -1,5 +1,6 @@ #!/usr/bin/env bash /etc/init.d/ssh start +go install ./examples/data-channels while true do sleep 10 diff --git a/examples/data-channels/main.go b/examples/data-channels/main.go index 902222eac22..c4f80c8850c 100644 --- a/examples/data-channels/main.go +++ b/examples/data-channels/main.go @@ -52,8 +52,9 @@ func main() { // Register channel opening handling d.OnOpen(func() { - fmt.Printf("Data channel '%s'-'%d' open. Random messages will now be sent to any connected DataChannels every 5 seconds\n", d.Label(), d.ID()) - + msg := fmt.Sprintf("Data channel '%s'-'%d' open. Random messages will now be sent to any connected DataChannels every 5 seconds\n", d.Label(), d.ID()) + fmt.Printf(msg) + d.SendText(msg) for range time.NewTicker(5 * time.Second).C { message := signal.RandSeq(15) fmt.Printf("Sending '%s'\n", message) From 1e6d3431f2e0fc11c87d26168b87fe370e706ba8 Mon Sep 17 00:00:00 2001 From: Benny Daon Date: Mon, 21 Nov 2022 16:11:18 +0200 Subject: [PATCH 06/33] Fixing the dta-channels example test --- ats/README.md | 74 ++++++++++++++--- ats/{datachannels => data-channels}/README.md | 0 ats/{datachannels => data-channels}/client | 0 .../example.spec.ts | 82 ++++++++++--------- ats/{datachannels => data-channels}/lab.yaml | 9 +- ats/{datachannels => data-channels}/main.go | 0 ats/data-channels/pion_entrypoint.sh | 9 ++ ats/datachannels/pion_entrypoint.sh | 7 -- ats/infra/pion/Dockerfile | 6 +- ats/infra/pion/docker_entry.sh | 13 --- ats/infra/playwright/Dockerfile | 8 ++ ats/infra/{runner => playwright}/package.json | 0 ats/infra/playwright/playwright.config.ts | 27 ++++++ ats/infra/{runner => playwright}/yarn.lock | 0 ats/infra/runner/Dockerfile | 9 -- ats/run | 8 +- 16 files changed, 159 insertions(+), 93 deletions(-) rename ats/{datachannels => data-channels}/README.md (100%) rename ats/{datachannels => data-channels}/client (100%) rename ats/{datachannels => data-channels}/example.spec.ts (59%) rename ats/{datachannels => data-channels}/lab.yaml (73%) rename ats/{datachannels => data-channels}/main.go (100%) create mode 100755 ats/data-channels/pion_entrypoint.sh delete mode 100755 ats/datachannels/pion_entrypoint.sh delete mode 100755 ats/infra/pion/docker_entry.sh create mode 100644 ats/infra/playwright/Dockerfile rename ats/infra/{runner => playwright}/package.json (100%) create mode 100644 ats/infra/playwright/playwright.config.ts rename ats/infra/{runner => playwright}/yarn.lock (100%) delete mode 100644 ats/infra/runner/Dockerfile diff --git a/ats/README.md b/ats/README.md index 269c5241947..c1d302a59f9 100644 --- a/ats/README.md +++ b/ats/README.md @@ -1,23 +1,71 @@ # Acceptance Test Specifications -TL:DR; From the project's root `./ats/test` +TL:DR; From the project's root `./ats/run` -This folder contains automated acceptance test specifications. -The tests are using docker-compose for lab setup and playwright -for end-to-end and browser testing. +This directory contains Acceptance Test Specifications AKA black box tests. +The tests are running over a lab managed by docker-compose and using playwright +for browser automation. -The script support some old style options, use `./ats/test -h` to see the -all the options. It also accepts one of more argument with a folder name. +The `ats` directory includes a special directory `infra` with the infrastructure +required by the tests. +For example, there's a `./infra/pion` directory with a Dockerfile and an SSH +config file. -## The runner +Unlike production containers, lab containers' entry point +often includes setup code usually found in the Dockerfile. +This is done for flexibility and speed as we want the lab to use the latest source -We use [playwright](https://playwright.dev) as the test runner and use -its syntax and expectations. To pass options to playwright use the -`PWARGS` enviornment variable. I use it to get the tests to stop -after the first failure and keep the logs short: +The script support some old style options, use `./ats/run -h` to see the +all the options. It also accepts one of more argument with a directory name. +## The setup + +We use [playwright](https://playwright.dev) as the test runner. +In addition to browser automation the runner uses SSH to control the services. +Thanks to compose, a name of a service is also its address so + +The runner supports one environment variable - `PWOPTS` - one can use to pass +options to playwright. The default is `-x` stopping the test on the first +failure. It's rigged this way becuase ATSs are usually complex scenarios. +Unlike unit tests, where each test function is independent, here each functions +is a step in one test specification. Once a step failed, `-x` makes playwright ignore +the rest of the file. + +To get help on playwright options run: + +```bash +docker compose -f ats/data-channels/lab.yaml --project-directory . run --entrypoint "npx playwright test --help" runner ``` -PWARGS=-x ./ats/test ./ats/accept + +The above command uses the lab from the data-channels tests to bring up a runner +and override its entrypoint. Instead of running the specs, get help on playwright. +We use `--project-directory .` in all the tests to ensure the relative paths are +relative to the project's root. + +## Adding a test + +To create the `fubar` test, create a new directory in `./ats/fubar` and start working +one your `lab.yaml`. If your tests include a browser client your runner is +best using the image from `infra/playwright`: + +```yaml +version: "3.9" +services: + runner: + build: + context: . + dockerfile: ./ats/infra/playwright/Dockerfile + volumes: + - ./ats/fubar:/specs + - ./ats/result:/result + environment: + PWOPTS: ${PWOPTS--x} ``` -Run `npx playwright test --help` for its list of options +Not that we are mapping `/specs` to `ats/fubar` as the first is where the image looks +for specs. Once you've added your specs file to `./ats/fubar` it will run whener you +`./ats/run`. In fact, all a sub-directory of ats needs is a `lab.yaml` file and the +run script will try to bring it up. + +If you want to run just fubar you can use `./ats/run ats/fubar`. +To run a clean build of fubar, ignoring all cache, use `-z`. diff --git a/ats/datachannels/README.md b/ats/data-channels/README.md similarity index 100% rename from ats/datachannels/README.md rename to ats/data-channels/README.md diff --git a/ats/datachannels/client b/ats/data-channels/client similarity index 100% rename from ats/datachannels/client rename to ats/data-channels/client diff --git a/ats/datachannels/example.spec.ts b/ats/data-channels/example.spec.ts similarity index 59% rename from ats/datachannels/example.spec.ts rename to ats/data-channels/example.spec.ts index f5cec1d8f86..5726c5a73fd 100644 --- a/ats/datachannels/example.spec.ts +++ b/ats/data-channels/example.spec.ts @@ -6,48 +6,55 @@ test.describe("pion's data channels example", () => { const sleep = (ms) => { return new Promise(r => setTimeout(r, ms)) } - let page: Page, - context: BrowserContext + let page: Page + let context: BrowserContext + let SSHconn: Client + let stream test.beforeAll(async ({ browser }) => { context = await browser.newContext() page = await context.newPage() page.on('console', (msg) => console.log('console log:', msg.text())) page.on('pageerror', (err: Error) => console.log('PAGEERROR', err.message)) + // Load the javascript file + page.on('load', () => page.evaluate(() => { + var newScript = document.createElement('script') + // newScript.type = 'text/javascript'; + newScript.src = '/demo.js' + console.log("loading demo.js") + document.head.appendChild(newScript) + }) + ) const response = await page.goto("http://client/demo.html") await expect(response.ok()).toBeTruthy() - await page.evaluate(() => { - var newScript = document.createElement('script'); - newScript.type = 'text/javascript'; - newScript.src = '/demo.js'; - document.getElementsByTagName('head')[0].appendChild(newScript); - }) + SSHconn = null }) - test('can connect', async () => { - let cmdClosed = false - let conn, stream - try { - conn = await new Promise((resolve, reject) => { - const conn = new Client() - conn.on('error', e => reject(e)) - conn.on('ready', () => resolve(conn)) - conn.connect({ - host: 'pion', - port: 22, - username: 'pion', - password: 'pion' + test('setup SSH', async () => { + while (SSHconn == null) { + try { + SSHconn = await new Promise((resolve, reject) => { + const SSHconn = new Client() + SSHconn.on('error', e => reject(e)) + SSHconn.on('ready', () => resolve(SSHconn)) + SSHconn.connect({ + host: 'pion', + port: 22, + username: 'pion', + password: 'pion' + }) }) - }) - } catch(e) { expect(e).toBeNull() } + } catch(e) { console.log("SSH connection failed, retrying", e) } + } // log key SSH events - conn.on('error', e => console.log("ssh error", e)) - conn.on('close', e => { - cmdClosed = true + SSHconn.on('error', e => console.log("ssh error", e)) + SSHconn.on('close', e => { console.log("ssh closed", e) }) - conn.on('end', e => console.log("ssh ended", e)) - conn.on('keyboard-interactive', e => console.log("ssh interaction", e)) + SSHconn.on('end', e => console.log("ssh ended", e)) + SSHconn.on('keyboard-interactive', e => console.log("ssh interaction", e)) + }) + test('open the command stream', async () => { let offer while (!offer) { await sleep(200) @@ -55,8 +62,7 @@ test.describe("pion's data channels example", () => { } try { stream = await new Promise((resolve, reject) => { - - conn.exec(`bash -c 'cd /source; echo ${offer} | /go/bin/data-channels'`, + SSHconn.exec(`bash -c 'cd /source; echo ${offer} | /go/bin/data-channels'`, { pty: true }, async (err, s) => { if (err) reject(err) @@ -65,16 +71,16 @@ test.describe("pion's data channels example", () => { }) }) } catch(e) { expect(e).toBeNull() } - let dataLines = 0 - let webexecCan = "" + stream.on('close', (code, signal) => { + console.log(`SSH closed with ${signal}`) + SSHconn.end() + }) + }) + test('transmit and receive data', async()=> { let finished = false let lineCounter = 0 - stream.on('close', (code, signal) => { - console.log(`closed with ${signal}`) - cmdClosed = true - conn.end() - }).on('data', lines => - new Buffer.from(lines).toString().split("\r\n").forEach(async line => { + stream.on('data', lines => + new Buffer.from(lines).toString().split("\r\n").forEach(async (line: string) => { if (!line) return lineCounter++ diff --git a/ats/datachannels/lab.yaml b/ats/data-channels/lab.yaml similarity index 73% rename from ats/datachannels/lab.yaml rename to ats/data-channels/lab.yaml index 953ffb17fd0..c487c6dc126 100644 --- a/ats/datachannels/lab.yaml +++ b/ats/data-channels/lab.yaml @@ -3,15 +3,15 @@ services: runner: build: context: . - dockerfile: ./ats/infra/runner/Dockerfile + dockerfile: ./ats/infra/playwright/Dockerfile volumes: - - ./ats/datachannels:/suite + - ./ats/data-channels:/specs - ./ats/result:/result depends_on: - client - pion environment: - PWARGS: ${PWARGS--x} + PWOPTS: ${PWOPTS--x} client: image: halverneus/static-file-server:latest environment: @@ -28,5 +28,4 @@ services: - "22" volumes: - .:/source - entrypoint: /source/ats/datachannels/pion_entrypoint.sh - + entrypoint: /source/ats/data-channels/pion_entrypoint.sh diff --git a/ats/datachannels/main.go b/ats/data-channels/main.go similarity index 100% rename from ats/datachannels/main.go rename to ats/data-channels/main.go diff --git a/ats/data-channels/pion_entrypoint.sh b/ats/data-channels/pion_entrypoint.sh new file mode 100755 index 00000000000..29255096e63 --- /dev/null +++ b/ats/data-channels/pion_entrypoint.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash +# The pion entry point for the data channel example +# First install the command, which can take a while, and only then open ssh server +go install ./examples/data-channels +/etc/init.d/ssh start +while true +do + sleep 10 +done diff --git a/ats/datachannels/pion_entrypoint.sh b/ats/datachannels/pion_entrypoint.sh deleted file mode 100755 index a5c1067bf90..00000000000 --- a/ats/datachannels/pion_entrypoint.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/env bash -/etc/init.d/ssh start -go install ./examples/data-channels -while true -do - sleep 10 -done diff --git a/ats/infra/pion/Dockerfile b/ats/infra/pion/Dockerfile index ea0c8b70681..b5c84d7c78a 100644 --- a/ats/infra/pion/Dockerfile +++ b/ats/infra/pion/Dockerfile @@ -1,11 +1,9 @@ FROM golang:bullseye -RUN apt update -RUN apt install -y git bash openssh-server +RUN apt-get update +RUN apt-get install -y git bash openssh-server COPY ./ats/infra/pion/ssh_config /etc/ssh/ -COPY ./ats/infra/pion/docker_entry.sh /usr/local/bin RUN /etc/init.d/ssh start RUN useradd -s /bin/bash -d /home/pion -M -p '$y$j9T$6LsNr6MtK4Nt6NeECphjP1$Try0q9dVUdZGihzzxJZ0soO09wQhseYzyB/E2Jf4tO8' pion RUN mkdir /home/pion RUN chown pion /home/pion WORKDIR /source -CMD go run . diff --git a/ats/infra/pion/docker_entry.sh b/ats/infra/pion/docker_entry.sh deleted file mode 100755 index 66867c3d11c..00000000000 --- a/ats/infra/pion/docker_entry.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/env bash - -set -x -EXE="/assets/webexec" -CONF="/config/webexec" - -/etc/init.d/ssh start -cp $EXE /usr/local/bin -rm -rf /home/runner/.local -mkdir -p /home/runner/.config/webexec -cp -r "$CONF" /home/runner/.config/ -chown -R runner /home/runner -su -c "$EXE start --debug" runner diff --git a/ats/infra/playwright/Dockerfile b/ats/infra/playwright/Dockerfile new file mode 100644 index 00000000000..131e61120fd --- /dev/null +++ b/ats/infra/playwright/Dockerfile @@ -0,0 +1,8 @@ +FROM mcr.microsoft.com/playwright:v1.26.0-focal +ENV NODE_PATH="/usr/lib/node_modules" +RUN mkdir -p /ats/CUT +WORKDIR /ats/CUT +ADD ./ats/infra ../infra +COPY ./ats/infra/playwright/* . +RUN yarn install --frozen-lockfile +CMD cp /specs/*.spec.ts . && npx playwright test ${PWOPTS} diff --git a/ats/infra/runner/package.json b/ats/infra/playwright/package.json similarity index 100% rename from ats/infra/runner/package.json rename to ats/infra/playwright/package.json diff --git a/ats/infra/playwright/playwright.config.ts b/ats/infra/playwright/playwright.config.ts new file mode 100644 index 00000000000..4f48e4e357a --- /dev/null +++ b/ats/infra/playwright/playwright.config.ts @@ -0,0 +1,27 @@ +// playwright.config.ts +import { PlaywrightTestConfig, devices } from '@playwright/test'; + +const config: PlaywrightTestConfig = { + headless: true, + forbidOnly: !!process.env.CI, + retries: process.env.CI ? 2 : 0, + outputDir: '/result', + use: { + trace: 'retain-on-failure', + }, + projects: [ + { + name: 'chromium', + use: { ...devices['Desktop Chrome'] }, + }, + { + name: 'firefox', + use: { ...devices['Desktop Firefox'] }, + }, + { + name: 'safari', + use: { ...devices['Desktop Safari'] }, + }, + ], +}; +export default config; diff --git a/ats/infra/runner/yarn.lock b/ats/infra/playwright/yarn.lock similarity index 100% rename from ats/infra/runner/yarn.lock rename to ats/infra/playwright/yarn.lock diff --git a/ats/infra/runner/Dockerfile b/ats/infra/runner/Dockerfile deleted file mode 100644 index ab4df06768c..00000000000 --- a/ats/infra/runner/Dockerfile +++ /dev/null @@ -1,9 +0,0 @@ -FROM mcr.microsoft.com/playwright:v1.22.2-focal -ENV NODE_PATH="/usr/lib/node_modules" -RUN mkdir -p /ats/CURRENT -WORKDIR /ats/CURRENT -ADD ./ats/infra ../infra -COPY ./ats/infra/runner/package.json . -COPY ./ats/infra/runner/yarn.lock . -RUN yarn install --frozen-lockfile -CMD cp /suite/*.spec.ts . && npx playwright test ${PWARGS} diff --git a/ats/run b/ats/run index 317eed7cc2e..bd4d1d7944c 100755 --- a/ats/run +++ b/ats/run @@ -14,11 +14,11 @@ build_n_run() { } usage() { cat < +Syntax: $0 [-h|z|n] [path] options: h Print this usage From 2c417cd2c88b0e77bec0170866958395eeef7c40 Mon Sep 17 00:00:00 2001 From: Benny Daon Date: Mon, 21 Nov 2022 16:58:40 +0200 Subject: [PATCH 07/33] Removing webkit from the tests and fixing args --- ats/infra/playwright/playwright.config.ts | 25 +++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/ats/infra/playwright/playwright.config.ts b/ats/infra/playwright/playwright.config.ts index 4f48e4e357a..a85ea0ec411 100644 --- a/ats/infra/playwright/playwright.config.ts +++ b/ats/infra/playwright/playwright.config.ts @@ -11,16 +11,25 @@ const config: PlaywrightTestConfig = { }, projects: [ { - name: 'chromium', - use: { ...devices['Desktop Chrome'] }, - }, - { - name: 'firefox', - use: { ...devices['Desktop Firefox'] }, + name: "chromium", + permissions:["camera", "microphone"], + + use:{ + browserName:"chromium", + launchOptions:{ + args: ['--use-fake-ui-for-media-stream', '--use-fake-device-for-media-stream'] + } + }, }, { - name: 'safari', - use: { ...devices['Desktop Safari'] }, + name: "firefox", + use: { + browserName:"firefox", + launchOptions: { + args:[ "--quiet", "--use-test-media-devices" ], + firefoxUserPrefs: { "media.navigator.streams.fake": true, "media.navigator.permission.disabled": true } + } + } }, ], }; From 616c0db8b7803651fbdc5e8f38ae79c7a89aaa7b Mon Sep 17 00:00:00 2001 From: Benny Daon Date: Tue, 22 Nov 2022 10:44:46 +0200 Subject: [PATCH 08/33] Cleaning up --- ats/data-channels/README.md | 37 --------- ats/data-channels/example.spec.ts | 15 ++-- ats/data-channels/main.go | 96 ----------------------- ats/infra/pion/ssh_config | 1 - ats/infra/playwright/Dockerfile | 4 +- ats/infra/playwright/package.json | 5 +- ats/infra/playwright/playwright.config.ts | 2 +- go.sum | 30 ------- sctptransport.go | 4 - 9 files changed, 14 insertions(+), 180 deletions(-) delete mode 100644 ats/data-channels/README.md delete mode 100644 ats/data-channels/main.go diff --git a/ats/data-channels/README.md b/ats/data-channels/README.md deleted file mode 100644 index aef47a7461b..00000000000 --- a/ats/data-channels/README.md +++ /dev/null @@ -1,37 +0,0 @@ -# data-channels - -data-channels is a Pion WebRTC application that shows how you can send/recv -DataChannel messages from a web browser - -## Testing suite - -The runner starts by - -### Download data-channels -``` -export GO111MODULE=on -go get github.com/pion/webrtc/v3/examples/data-channels -``` - -### Open data-channels example page -[jsfiddle.net](https://jsfiddle.net/9tsx15mg/90/) - -### Run data-channels, with your browsers SessionDescription as stdin -In the jsfiddle the top textarea is your browser's session description, copy that and: -#### Linux/macOS -Run `echo $BROWSER_SDP | data-channels` -#### Windows -1. Paste the SessionDescription into a file. -1. Run `data-channels < my_file` - -### Input data-channels's SessionDescription into your browser -Copy the text that `data-channels` just emitted and copy into second text area - -### Hit 'Start Session' in jsfiddle -Under Start Session you should see 'Checking' as it starts connecting. If everything worked you should see `New DataChannel foo 1` - -Now you can put whatever you want in the `Message` textarea, and when you hit `Send Message` it should appear in your terminal! - -Pion WebRTC will send random messages every 5 seconds that will appear in your browser. - -Congrats, you have used Pion WebRTC! Now start building something cool diff --git a/ats/data-channels/example.spec.ts b/ats/data-channels/example.spec.ts index 5726c5a73fd..300ad50ff84 100644 --- a/ats/data-channels/example.spec.ts +++ b/ats/data-channels/example.spec.ts @@ -19,8 +19,7 @@ test.describe("pion's data channels example", () => { // Load the javascript file page.on('load', () => page.evaluate(() => { var newScript = document.createElement('script') - // newScript.type = 'text/javascript'; - newScript.src = '/demo.js' + newScript.src = 'demo.js' console.log("loading demo.js") document.head.appendChild(newScript) }) @@ -44,7 +43,10 @@ test.describe("pion's data channels example", () => { password: 'pion' }) }) - } catch(e) { console.log("SSH connection failed, retrying", e) } + } catch(e) { + console.log("SSH connection failed, retrying") + await sleep(3000) + } } // log key SSH events SSHconn.on('error', e => console.log("ssh error", e)) @@ -58,7 +60,9 @@ test.describe("pion's data channels example", () => { let offer while (!offer) { await sleep(200) - offer = await page.evaluate(() => document.getElementById('localSessionDescription').value) + offer = await page.evaluate(() => + document.getElementById('localSessionDescription').value + ) } try { stream = await new Promise((resolve, reject) => { @@ -80,7 +84,8 @@ test.describe("pion's data channels example", () => { let finished = false let lineCounter = 0 stream.on('data', lines => - new Buffer.from(lines).toString().split("\r\n").forEach(async (line: string) => { + new Buffer.from(lines).toString().split("\r\n") + .forEach(async (line: string) => { if (!line) return lineCounter++ diff --git a/ats/data-channels/main.go b/ats/data-channels/main.go deleted file mode 100644 index 89f74002cee..00000000000 --- a/ats/data-channels/main.go +++ /dev/null @@ -1,96 +0,0 @@ -package main - -import ( - "fmt" - "time" - - "github.com/pion/webrtc/v3" - "github.com/pion/webrtc/v3/examples/internal/signal" -) - -func main() { - // Everything below is the Pion WebRTC API! Thanks for using it ❤️. - - // Prepare the configuration - config := webrtc.Configuration{ - ICEServers: []webrtc.ICEServer{ - { - URLs: []string{"stun:stun.l.google.com:19302"}, - }, - }, - } - - // Create a new RTCPeerConnection - peerConnection, err := webrtc.NewPeerConnection(config) - if err != nil { - panic(err) - } - - // Set the handler for ICE connection state - // This will notify you when the peer has connected/disconnected - peerConnection.OnICEConnectionStateChange(func(connectionState webrtc.ICEConnectionState) { - fmt.Printf("ICE Connection State has changed: %s\n", connectionState.String()) - }) - - // Register data channel creation handling - peerConnection.OnDataChannel(func(d *webrtc.DataChannel) { - fmt.Printf("New DataChannel %s %d\n", d.Label(), d.ID()) - - // Register channel opening handling - d.OnOpen(func() { - fmt.Printf("Data channel '%s'-'%d' open. Random messages will now be sent to any connected DataChannels every 5 seconds\n", d.Label(), d.ID()) - - for range time.NewTicker(5 * time.Second).C { - message := signal.RandSeq(15) - fmt.Printf("Sending '%s'\n", message) - - // Send the message as text - sendErr := d.SendText(message) - if sendErr != nil { - panic(sendErr) - } - } - }) - - // Register text message handling - d.OnMessage(func(msg webrtc.DataChannelMessage) { - fmt.Printf("Message from DataChannel '%s': '%s'\n", d.Label(), string(msg.Data)) - }) - }) - - // Wait for the offer to be pasted - offer := webrtc.SessionDescription{} - signal.Decode(signal.MustReadStdin(), &offer) - - // Set the remote SessionDescription - err = peerConnection.SetRemoteDescription(offer) - if err != nil { - panic(err) - } - - // Create an answer - answer, err := peerConnection.CreateAnswer(nil) - if err != nil { - panic(err) - } - - // Create channel that is blocked until ICE Gathering is complete - gatherComplete := webrtc.GatheringCompletePromise(peerConnection) - - // Sets the LocalDescription, and starts our UDP listeners - err = peerConnection.SetLocalDescription(answer) - if err != nil { - panic(err) - } - - // Block until ICE Gathering is complete, disabling trickle ICE - // we do this because we only can exchange one signaling message - // in a production application you should exchange ICE Candidates via OnICECandidate - <-gatherComplete - - // Output the answer in base64 so we can paste it in browser - fmt.Println(signal.Encode(*peerConnection.LocalDescription())) - - // Block forever - select {} -} diff --git a/ats/infra/pion/ssh_config b/ats/infra/pion/ssh_config index 5626c673f76..bddde6f778b 100644 --- a/ats/infra/pion/ssh_config +++ b/ats/infra/pion/ssh_config @@ -1,5 +1,4 @@ Include /etc/ssh/ssh_config.d/*.conf - Host * PasswordAuthentication yes SendEnv LANG LC_* diff --git a/ats/infra/playwright/Dockerfile b/ats/infra/playwright/Dockerfile index 131e61120fd..e5f86670d1f 100644 --- a/ats/infra/playwright/Dockerfile +++ b/ats/infra/playwright/Dockerfile @@ -1,8 +1,6 @@ FROM mcr.microsoft.com/playwright:v1.26.0-focal ENV NODE_PATH="/usr/lib/node_modules" -RUN mkdir -p /ats/CUT -WORKDIR /ats/CUT -ADD ./ats/infra ../infra COPY ./ats/infra/playwright/* . RUN yarn install --frozen-lockfile +# /specs is set by the lab, so we only copy the specs on run CMD cp /specs/*.spec.ts . && npx playwright test ${PWOPTS} diff --git a/ats/infra/playwright/package.json b/ats/infra/playwright/package.json index 6f039b28336..cb02e217580 100644 --- a/ats/infra/playwright/package.json +++ b/ats/infra/playwright/package.json @@ -1,8 +1,7 @@ { - "name": "terminal7-tester", + "name": "pion-playwroght", "version": "0.1.0", - "description": "A playwright based box testing for Terminal7", - "main": "runner.js", + "description": "A playwright based box testing for pion", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, diff --git a/ats/infra/playwright/playwright.config.ts b/ats/infra/playwright/playwright.config.ts index a85ea0ec411..4f502dd9eda 100644 --- a/ats/infra/playwright/playwright.config.ts +++ b/ats/infra/playwright/playwright.config.ts @@ -4,7 +4,7 @@ import { PlaywrightTestConfig, devices } from '@playwright/test'; const config: PlaywrightTestConfig = { headless: true, forbidOnly: !!process.env.CI, - retries: process.env.CI ? 2 : 0, + retries: 2, outputDir: '/result', use: { trace: 'retain-on-failure', diff --git a/go.sum b/go.sum index 5bc98f25479..6989fe990b4 100644 --- a/go.sum +++ b/go.sum @@ -38,7 +38,6 @@ github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -<<<<<<< HEAD github.com/onsi/gomega v1.17.0 h1:9Luw4uT5HTjHTN8+aNcSThgH1vdXnmdJ8xIfZ4wyTRE= github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/pion/datachannel v1.5.2 h1:piB93s8LGmbECrpO84DnkIVWasRMk3IimbcXkTQLE6E= @@ -49,26 +48,12 @@ github.com/pion/ice/v2 v2.2.11 h1:wiAy7TSrVZ4KdyjC0CcNTkwltz9ywetbe4wbHLKUbIg= github.com/pion/ice/v2 v2.2.11/go.mod h1:NqUDUao6SjSs1+4jrqpexDmFlptlVhGxQjcymXLaVvE= github.com/pion/interceptor v0.1.11 h1:00U6OlqxA3FFB50HSg25J/8cWi7P6FbSzw4eFn24Bvs= github.com/pion/interceptor v0.1.11/go.mod h1:tbtKjZY14awXd7Bq0mmWvgtHB5MDaRN7HV3OZ/uy7s8= -======= -github.com/onsi/gomega v1.11.0 h1:+CqWgvj0OZycCaqclBD1pxKHAU+tOkHmQIWvDHq2aug= -github.com/onsi/gomega v1.11.0/go.mod h1:azGKhqFUon9Vuj0YmTfLSmx0FUwqXYSTl5re8lQLTUg= -github.com/pion/datachannel v1.5.0 h1:Jy6xWr9hysxet69qP23ibiJ6M0P30ZRnndHU+N6cpkY= -github.com/pion/datachannel v1.5.0/go.mod h1:TVbgWP+PVM9TlwL1IkG3JqXXfjGxLvsu9QUeFdpTegI= -github.com/pion/dtls/v2 v2.0.9/go.mod h1:O0Wr7si/Zj5/EBFlDzDd6UtVxx25CE1r7XM7BQKYQho= -github.com/pion/dtls/v2 v2.0.10 h1:wgys7gPR1NMbWjmjJ3CW7lkUGaun8djgH8nahpNLnxI= -github.com/pion/dtls/v2 v2.0.10/go.mod h1:00OxfeCRWHShcqT9jx8pKKmBWuTt0NCZoVPCaC4VKvU= -github.com/pion/ice/v2 v2.1.13 h1:/YNYcIw56LT/whwuzkTnrprcRnapj2ZNqUsR0W8elmo= -github.com/pion/ice/v2 v2.1.13/go.mod h1:ovgYHUmwYLlRvcCLI67PnQ5YGe+upXZbGgllBDG/ktU= -github.com/pion/interceptor v0.1.0 h1:SlXKaDlEvSl7cr4j8fJykzVz4UdH+7UDtcvx+u01wLU= -github.com/pion/interceptor v0.1.0/go.mod h1:j5NIl3tJJPB3u8+Z2Xz8MZs/VV6rc+If9mXEKNuFmEM= ->>>>>>> c5faa92 (Use OnOpen handler for DataChannels) github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY= github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms= github.com/pion/mdns v0.0.5 h1:Q2oj/JB3NqfzY9xGZ1fPzZzK7sDSD8rZPOvcIQ10BCw= github.com/pion/mdns v0.0.5/go.mod h1:UgssrvdD3mxpi8tMxAXbsppL3vJ4Jipw1mTCW+al01g= github.com/pion/randutil v0.1.0 h1:CFG1UdESneORglEsnimhUjf33Rwjubwj6xfiOXBa3mA= github.com/pion/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8= -<<<<<<< HEAD github.com/pion/rtcp v1.2.9/go.mod h1:qVPhiCzAm4D/rxb6XzKeyZiQK69yJpbUDJSF7TgrqNo= github.com/pion/rtcp v1.2.10 h1:nkr3uj+8Sp97zyItdN60tE/S6vk4al5CPRR6Gejsdjc= github.com/pion/rtcp v1.2.10/go.mod h1:ztfEwXZNLGyF1oQDttz/ZKIBaeeg/oWbRYqzBM9TL1I= @@ -81,21 +66,6 @@ github.com/pion/sdp/v3 v3.0.6 h1:WuDLhtuFUUVpTfus9ILC4HRyHsW6TdugjEX/QY9OiUw= github.com/pion/sdp/v3 v3.0.6/go.mod h1:iiFWFpQO8Fy3S5ldclBkpXqmWy02ns78NOKoLLL0YQw= github.com/pion/srtp/v2 v2.0.10 h1:b8ZvEuI+mrL8hbr/f1YiJFB34UMrOac3R3N1yq2UN0w= github.com/pion/srtp/v2 v2.0.10/go.mod h1:XEeSWaK9PfuMs7zxXyiN252AHPbH12NX5q/CFDWtUuA= -======= -github.com/pion/rtcp v1.2.6/go.mod h1:52rMNPWFsjr39z9B9MhnkqhPLoeHTv1aN63o/42bWE0= -github.com/pion/rtcp v1.2.8 h1:Cys8X6r0xxU65ESTmXkqr8eU1Q1Wx+lNkoZCUH4zD7E= -github.com/pion/rtcp v1.2.8/go.mod h1:qVPhiCzAm4D/rxb6XzKeyZiQK69yJpbUDJSF7TgrqNo= -github.com/pion/rtp v1.7.0/go.mod h1:bDb5n+BFZxXx0Ea7E5qe+klMuqiBrP+w8XSjiWtCUko= -github.com/pion/rtp v1.7.2/go.mod h1:bDb5n+BFZxXx0Ea7E5qe+klMuqiBrP+w8XSjiWtCUko= -github.com/pion/rtp v1.7.4 h1:4dMbjb1SuynU5OpA3kz1zHK+u+eOCQjW3MAeVHf1ODA= -github.com/pion/rtp v1.7.4/go.mod h1:bDb5n+BFZxXx0Ea7E5qe+klMuqiBrP+w8XSjiWtCUko= -github.com/pion/sctp v1.7.12 h1:GsatLufywVruXbZZT1CKg+Jr8ZTkwiPnmUC/oO9+uuY= -github.com/pion/sctp v1.7.12/go.mod h1:xFe9cLMZ5Vj6eOzpyiKjT9SwGM4KpK/8Jbw5//jc+0s= -github.com/pion/sdp/v3 v3.0.4 h1:2Kf+dgrzJflNCSw3TV5v2VLeI0s/qkzy2r5jlR0wzf8= -github.com/pion/sdp/v3 v3.0.4/go.mod h1:bNiSknmJE0HYBprTHXKPQ3+JjacTv5uap92ueJZKsRk= -github.com/pion/srtp/v2 v2.0.5 h1:ks3wcTvIUE/GHndO3FAvROQ9opy0uLELpwHJaQ1yqhQ= -github.com/pion/srtp/v2 v2.0.5/go.mod h1:8k6AJlal740mrZ6WYxc4Dg6qDqqhxoRG2GSjlUhDF0A= ->>>>>>> c5faa92 (Use OnOpen handler for DataChannels) github.com/pion/stun v0.3.5 h1:uLUCBCkQby4S1cf6CGuR9QrVOKcvUwFeemaC865QHDg= github.com/pion/stun v0.3.5/go.mod h1:gDMim+47EeEtfWogA37n6qXZS88L5V6LqFcf+DZA2UA= github.com/pion/transport v0.12.2/go.mod h1:N3+vZQD9HlDP5GWkZ85LohxNsDcNgofQmyL6ojX5d8Q= diff --git a/sctptransport.go b/sctptransport.go index f5a4071d90e..db7b25256cb 100644 --- a/sctptransport.go +++ b/sctptransport.go @@ -232,11 +232,7 @@ ACCEPT: } <-r.onDataChannel(rtcDC) -<<<<<<< HEAD rtcDC.handleOpen(dc, true, dc.Config.Negotiated) -======= - rtcDC.handleOpen(dc, true) ->>>>>>> c5faa92 (Use OnOpen handler for DataChannels) r.lock.Lock() r.dataChannelsOpened++ From 63150a814d21fdc0627c5e3effe25fc14adb9669 Mon Sep 17 00:00:00 2001 From: Benny Daon Date: Thu, 22 Dec 2022 18:15:00 +0200 Subject: [PATCH 09/33] Add the e2e test to ats --- .github/workflows/{browser-e2e.yaml => ats.yaml} | 6 ++---- {e2e => ats/e2e}/Dockerfile | 3 +-- {e2e => ats/e2e}/e2e_test.go | 0 ats/e2e/lab.yaml | 8 ++++++++ {e2e => ats/e2e}/test.html | 0 5 files changed, 11 insertions(+), 6 deletions(-) rename .github/workflows/{browser-e2e.yaml => ats.yaml} (62%) rename {e2e => ats/e2e}/Dockerfile (65%) rename {e2e => ats/e2e}/e2e_test.go (100%) create mode 100644 ats/e2e/lab.yaml rename {e2e => ats/e2e}/test.html (100%) diff --git a/.github/workflows/browser-e2e.yaml b/.github/workflows/ats.yaml similarity index 62% rename from .github/workflows/browser-e2e.yaml rename to .github/workflows/ats.yaml index b45f63710c1..5e4269e24d2 100644 --- a/.github/workflows/browser-e2e.yaml +++ b/.github/workflows/ats.yaml @@ -1,4 +1,4 @@ -name: Browser E2E +name: Acceptance Tests on: pull_request: branches: @@ -15,6 +15,4 @@ jobs: - name: checkout uses: actions/checkout@v3 - name: test - run: | - docker build -t pion-webrtc-e2e -f e2e/Dockerfile . - docker run -i --rm pion-webrtc-e2e + run: ats/run diff --git a/e2e/Dockerfile b/ats/e2e/Dockerfile similarity index 65% rename from e2e/Dockerfile rename to ats/e2e/Dockerfile index c871222afb7..9883251327f 100644 --- a/e2e/Dockerfile +++ b/ats/e2e/Dockerfile @@ -6,7 +6,6 @@ RUN apk add --no-cache \ ENV CGO_ENABLED=0 -COPY . /go/src/github.com/pion/webrtc -WORKDIR /go/src/github.com/pion/webrtc/e2e +WORKDIR /go/src/github.com/pion/webrtc/ats/e2e CMD ["go", "test", "-tags=e2e", "-v", "."] diff --git a/e2e/e2e_test.go b/ats/e2e/e2e_test.go similarity index 100% rename from e2e/e2e_test.go rename to ats/e2e/e2e_test.go diff --git a/ats/e2e/lab.yaml b/ats/e2e/lab.yaml new file mode 100644 index 00000000000..7506b33028e --- /dev/null +++ b/ats/e2e/lab.yaml @@ -0,0 +1,8 @@ +version: "3.9" +services: + runner: + build: + context: . + dockerfile: ./ats/e2e/Dockerfile + volumes: + - .:/go/src/github.com/pion/webrtc diff --git a/e2e/test.html b/ats/e2e/test.html similarity index 100% rename from e2e/test.html rename to ats/e2e/test.html From 8317e2f514d5c943b3b2fcdc8e8318c0bf4c4bc3 Mon Sep 17 00:00:00 2001 From: Benny Daon Date: Fri, 23 Dec 2022 16:47:34 +0200 Subject: [PATCH 10/33] Automate the pion-to-pion example The offer side of the example now includes a -count and -wait options so the test will eventually end and run faster. It also ends sending and receiving EOF for clean "answer" exit. --- ats/pion-to-pion/lab.yaml | 17 ++++++++++ examples/pion-to-pion/README.md | 6 ++-- examples/pion-to-pion/answer/Dockerfile | 8 ----- examples/pion-to-pion/answer/main.go | 4 +++ examples/pion-to-pion/docker-compose.yml | 13 -------- examples/pion-to-pion/offer/Dockerfile | 6 ---- examples/pion-to-pion/offer/main.go | 41 +++++++++++++++++++----- examples/pion-to-pion/test.sh | 14 -------- 8 files changed, 56 insertions(+), 53 deletions(-) create mode 100644 ats/pion-to-pion/lab.yaml delete mode 100644 examples/pion-to-pion/answer/Dockerfile delete mode 100644 examples/pion-to-pion/docker-compose.yml delete mode 100644 examples/pion-to-pion/offer/Dockerfile delete mode 100755 examples/pion-to-pion/test.sh diff --git a/ats/pion-to-pion/lab.yaml b/ats/pion-to-pion/lab.yaml new file mode 100644 index 00000000000..90221e1f8df --- /dev/null +++ b/ats/pion-to-pion/lab.yaml @@ -0,0 +1,17 @@ +version: '3' +services: + answer: + image: golang:1.19 + volumes: + - .:/go/src/github.com/pion/webrtc + working_dir: /go/src/github.com/pion/webrtc/examples/pion-to-pion/answer + command: go run . -offer-address runner:50000 + + runner: + depends_on: + - answer + image: golang:1.19 + volumes: + - .:/go/src/github.com/pion/webrtc + working_dir: /go/src/github.com/pion/webrtc/examples/pion-to-pion/offer + command: go run . -answer-address answer:60000 -count 3 -wait 1 diff --git a/examples/pion-to-pion/README.md b/examples/pion-to-pion/README.md index 7bf909bb760..970ef971c32 100644 --- a/examples/pion-to-pion/README.md +++ b/examples/pion-to-pion/README.md @@ -19,9 +19,7 @@ offer You should see them connect and start to exchange messages. -## You can use Docker-compose to start this example: +## Running as a test ```sh -docker-compose up -d +./ats/run ats/pion-to-pion ``` - -Now, you can see message exchanging, using `docker logs`. diff --git a/examples/pion-to-pion/answer/Dockerfile b/examples/pion-to-pion/answer/Dockerfile deleted file mode 100644 index 5897317578a..00000000000 --- a/examples/pion-to-pion/answer/Dockerfile +++ /dev/null @@ -1,8 +0,0 @@ -FROM golang:1.19 - -ENV GO111MODULE=on -RUN go install github.com/pion/webrtc/v3/examples/pion-to-pion/answer@latest - -CMD ["answer"] - -EXPOSE 50000 diff --git a/examples/pion-to-pion/answer/main.go b/examples/pion-to-pion/answer/main.go index 84cd39d77ff..79bb1b00d43 100644 --- a/examples/pion-to-pion/answer/main.go +++ b/examples/pion-to-pion/answer/main.go @@ -172,6 +172,10 @@ func main() { // nolint:gocognit // Register text message handling d.OnMessage(func(msg webrtc.DataChannelMessage) { fmt.Printf("Message from DataChannel '%s': '%s'\n", d.Label(), string(msg.Data)) + // make a clean exit on EOF + if string(msg.Data) == "EOF" { + os.Exit(0) + } }) }) diff --git a/examples/pion-to-pion/docker-compose.yml b/examples/pion-to-pion/docker-compose.yml deleted file mode 100644 index fff78574fe0..00000000000 --- a/examples/pion-to-pion/docker-compose.yml +++ /dev/null @@ -1,13 +0,0 @@ -version: '3' -services: - answer: - container_name: answer - build: ./answer - command: answer -offer-address offer:50000 - - offer: - container_name: offer - depends_on: - - answer - build: ./offer - command: offer -answer-address answer:60000 diff --git a/examples/pion-to-pion/offer/Dockerfile b/examples/pion-to-pion/offer/Dockerfile deleted file mode 100644 index a8f0f08e42a..00000000000 --- a/examples/pion-to-pion/offer/Dockerfile +++ /dev/null @@ -1,6 +0,0 @@ -FROM golang:1.19 - -ENV GO111MODULE=on -RUN go install github.com/pion/webrtc/v3/examples/pion-to-pion/offer@latest - -CMD ["offer"] diff --git a/examples/pion-to-pion/offer/main.go b/examples/pion-to-pion/offer/main.go index ef845c9f763..ab60d0d0d53 100644 --- a/examples/pion-to-pion/offer/main.go +++ b/examples/pion-to-pion/offer/main.go @@ -6,6 +6,7 @@ import ( "flag" "fmt" "io/ioutil" + "math" "net/http" "os" "sync" @@ -32,6 +33,8 @@ func signalCandidate(addr string, c *webrtc.ICECandidate) error { func main() { //nolint:gocognit offerAddr := flag.String("offer-address", ":50000", "Address that the Offer HTTP server is hosted on.") answerAddr := flag.String("answer-address", "127.0.0.1:60000", "Address that the Answer HTTP server is hosted on.") + count := flag.Int("count", math.MaxInt, "Number of messages to send") + wait := flag.Int("wait", 5, "How long to wait between messages") flag.Parse() var candidatesMux sync.Mutex @@ -133,13 +136,28 @@ func main() { //nolint:gocognit } }) + done := make(chan bool) + messagesSent := 0 + // Register channel opening handling dataChannel.OnOpen(func() { - fmt.Printf("Data channel '%s'-'%d' open. Random messages will now be sent to any connected DataChannels every 5 seconds\n", dataChannel.Label(), dataChannel.ID()) + fmt.Printf("Data channel '%s'-'%d' open. Random messages will now be sent to any connected DataChannels every %d seconds\n", dataChannel.Label(), dataChannel.ID(), *wait) + waitDuration := time.Duration(*wait) * time.Second + + for range time.NewTicker(waitDuration).C { + // send EOF for orderly teardown of the session + if messagesSent == *count { + err = dataChannel.SendText("EOF") + if err != nil { + panic(err) + } + done <- true + break + } - for range time.NewTicker(5 * time.Second).C { message := signal.RandSeq(15) fmt.Printf("Sending '%s'\n", message) + messagesSent++ // Send the message as text sendTextErr := dataChannel.SendText(message) @@ -171,13 +189,20 @@ func main() { //nolint:gocognit if err != nil { panic(err) } - resp, err := http.Post(fmt.Sprintf("http://%s/sdp", *answerAddr), "application/json; charset=utf-8", bytes.NewReader(payload)) // nolint:noctx + // retry in case the other side is not yet ready + for i := 0; i < 10; i++ { + resp, postErr := http.Post(fmt.Sprintf("http://%s/sdp", *answerAddr), "application/json; charset=utf-8", bytes.NewReader(payload)) // nolint:noctx + if err = resp.Body.Close(); err != nil { + panic(err) + } + if postErr == nil { + break + } + time.Sleep(time.Second) + } if err != nil { panic(err) - } else if err := resp.Body.Close(); err != nil { - panic(err) } - - // Block forever - select {} + // wait for all sent messages to be received + <-done } diff --git a/examples/pion-to-pion/test.sh b/examples/pion-to-pion/test.sh deleted file mode 100755 index 0ae41c3ddfb..00000000000 --- a/examples/pion-to-pion/test.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/bash -eu - -docker compose up -d - -function on_exit { - docker compose logs - docker compose rm -fsv -} - -trap on_exit EXIT - -TIMEOUT=10 -timeout $TIMEOUT docker compose logs -f | grep -q "answer | Message from DataChannel" -timeout $TIMEOUT docker compose logs -f | grep -q "offer | Message from DataChannel" From ce25aec743be234a05314a86a51f1cb88ff14218 Mon Sep 17 00:00:00 2001 From: Benny Daon Date: Sat, 24 Dec 2022 21:46:54 +0200 Subject: [PATCH 11/33] Extend an example timeout a test passes on my machine and fails as part of the workflow. this change triples the time the offer is side is waiting for a reply --- examples/pion-to-pion/offer/main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/pion-to-pion/offer/main.go b/examples/pion-to-pion/offer/main.go index ab60d0d0d53..500f2996d4e 100644 --- a/examples/pion-to-pion/offer/main.go +++ b/examples/pion-to-pion/offer/main.go @@ -198,7 +198,7 @@ func main() { //nolint:gocognit if postErr == nil { break } - time.Sleep(time.Second) + time.Sleep(3 * time.Second) } if err != nil { panic(err) From 38c8a836e3985fcd911ffd87cd4b78fa9cf6fe51 Mon Sep 17 00:00:00 2001 From: Benny Daon Date: Sat, 24 Dec 2022 22:18:52 +0200 Subject: [PATCH 12/33] Remove the examples test workflow as it's now part of the acceptance tests --- .github/workflows/examples-tests.yaml | 19 ------------------- 1 file changed, 19 deletions(-) delete mode 100644 .github/workflows/examples-tests.yaml diff --git a/.github/workflows/examples-tests.yaml b/.github/workflows/examples-tests.yaml deleted file mode 100644 index 1791be42e49..00000000000 --- a/.github/workflows/examples-tests.yaml +++ /dev/null @@ -1,19 +0,0 @@ -name: Examples Tests -on: - pull_request: - branches: - - master - push: - branches: - - master - -jobs: - pion-to-pion-test: - name: Test - runs-on: ubuntu-latest - steps: - - name: checkout - uses: actions/checkout@v3 - - name: test - run: cd examples/pion-to-pion && ./test.sh - From 66dc3e48cb59fcc49d62b88caba1d947c3ec47e2 Mon Sep 17 00:00:00 2001 From: Benny Daon Date: Sat, 24 Dec 2022 22:19:23 +0200 Subject: [PATCH 13/33] Simplify the data channels tests restoring the xample to it's original code and adjusting the test spec --- ats/data-channels/example.spec.ts | 5 ++--- examples/data-channels/main.go | 5 ++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/ats/data-channels/example.spec.ts b/ats/data-channels/example.spec.ts index 300ad50ff84..79c9bfff7fd 100644 --- a/ats/data-channels/example.spec.ts +++ b/ats/data-channels/example.spec.ts @@ -97,17 +97,16 @@ test.describe("pion's data channels example", () => { page.locator("data-test-id=start-session").click() await sleep(3000) await page.evaluate(async () => - document.getElementById("message").value = "BADFACE") + document.getElementById("message").value = "EOF") await page.locator("data-test-id=send-message").click() return } - if (line.includes("BADFACE")) + if (line.includes("EOF")) finished=true }) ).stderr.on('data', (data) => { console.log("ERROR: " + data) }) - expect(page.locator("#logs")).toHaveText(/Random messages will now be sent/) while (!finished) { await sleep(500) } diff --git a/examples/data-channels/main.go b/examples/data-channels/main.go index c4f80c8850c..902222eac22 100644 --- a/examples/data-channels/main.go +++ b/examples/data-channels/main.go @@ -52,9 +52,8 @@ func main() { // Register channel opening handling d.OnOpen(func() { - msg := fmt.Sprintf("Data channel '%s'-'%d' open. Random messages will now be sent to any connected DataChannels every 5 seconds\n", d.Label(), d.ID()) - fmt.Printf(msg) - d.SendText(msg) + fmt.Printf("Data channel '%s'-'%d' open. Random messages will now be sent to any connected DataChannels every 5 seconds\n", d.Label(), d.ID()) + for range time.NewTicker(5 * time.Second).C { message := signal.RandSeq(15) fmt.Printf("Sending '%s'\n", message) From 9f03fb7245e6092c99945e42463b908ca4828268 Mon Sep 17 00:00:00 2001 From: Benny Daon Date: Sat, 28 Jan 2023 16:14:58 +0200 Subject: [PATCH 14/33] Simplify the data channel example test with this change the data-channels pion docker works similar to the other tests and mapping the source directly to /go/src --- ats/data-channels/example.spec.ts | 5 ++++- ats/data-channels/lab.yaml | 3 +-- ats/data-channels/pion_entrypoint.sh | 9 --------- ats/infra/pion/Dockerfile | 3 ++- 4 files changed, 7 insertions(+), 13 deletions(-) delete mode 100755 ats/data-channels/pion_entrypoint.sh diff --git a/ats/data-channels/example.spec.ts b/ats/data-channels/example.spec.ts index 79c9bfff7fd..9bd1163026f 100644 --- a/ats/data-channels/example.spec.ts +++ b/ats/data-channels/example.spec.ts @@ -2,6 +2,8 @@ import { Buffer } from 'node:buffer'; import { test, expect, Page, BrowserContext } from '@playwright/test' import { Client } from 'ssh2' +const GOBIN = "/usr/local/go/bin/go" + test.describe("pion's data channels example", () => { const sleep = (ms) => { return new Promise(r => setTimeout(r, ms)) } @@ -66,7 +68,8 @@ test.describe("pion's data channels example", () => { } try { stream = await new Promise((resolve, reject) => { - SSHconn.exec(`bash -c 'cd /source; echo ${offer} | /go/bin/data-channels'`, + const dir = "/go/src/github.com/pion/webrtc/examples/data-channels" + SSHconn.exec(`bash -c 'cd ${dir}; echo ${offer} | ${GOBIN} run .'`, { pty: true }, async (err, s) => { if (err) reject(err) diff --git a/ats/data-channels/lab.yaml b/ats/data-channels/lab.yaml index c487c6dc126..a9807d5158b 100644 --- a/ats/data-channels/lab.yaml +++ b/ats/data-channels/lab.yaml @@ -27,5 +27,4 @@ services: expose: - "22" volumes: - - .:/source - entrypoint: /source/ats/data-channels/pion_entrypoint.sh + - .:/go/src/github.com/pion/webrtc diff --git a/ats/data-channels/pion_entrypoint.sh b/ats/data-channels/pion_entrypoint.sh deleted file mode 100755 index 29255096e63..00000000000 --- a/ats/data-channels/pion_entrypoint.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/usr/bin/env bash -# The pion entry point for the data channel example -# First install the command, which can take a while, and only then open ssh server -go install ./examples/data-channels -/etc/init.d/ssh start -while true -do - sleep 10 -done diff --git a/ats/infra/pion/Dockerfile b/ats/infra/pion/Dockerfile index b5c84d7c78a..2f0877a650d 100644 --- a/ats/infra/pion/Dockerfile +++ b/ats/infra/pion/Dockerfile @@ -3,7 +3,8 @@ RUN apt-get update RUN apt-get install -y git bash openssh-server COPY ./ats/infra/pion/ssh_config /etc/ssh/ RUN /etc/init.d/ssh start +# pion user with pion password to be used by clients' ssh connections RUN useradd -s /bin/bash -d /home/pion -M -p '$y$j9T$6LsNr6MtK4Nt6NeECphjP1$Try0q9dVUdZGihzzxJZ0soO09wQhseYzyB/E2Jf4tO8' pion RUN mkdir /home/pion RUN chown pion /home/pion -WORKDIR /source +CMD /etc/init.d/ssh start && tail -f /dev/null From 5c3d9365310d02a4c9a55f415db8542df5c21840 Mon Sep 17 00:00:00 2001 From: Benny Daon Date: Sun, 29 Jan 2023 12:17:41 +0200 Subject: [PATCH 15/33] Improve names in aceptance tests workflow improve names in the ats workflow --- .github/workflows/ats.yaml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ats.yaml b/.github/workflows/ats.yaml index 5e4269e24d2..7973682f687 100644 --- a/.github/workflows/ats.yaml +++ b/.github/workflows/ats.yaml @@ -8,11 +8,10 @@ on: - master jobs: - e2e-test: - name: Test + acceptance-tests: runs-on: ubuntu-latest steps: - name: checkout uses: actions/checkout@v3 - - name: test + - name: run tests run: ats/run From 55e83b50e2828ce92fe284e3a3781c22dc3eb048 Mon Sep 17 00:00:00 2001 From: Benny Daon Date: Mon, 30 Jan 2023 12:12:06 +0200 Subject: [PATCH 16/33] Improve the data-channel example resiliancy by making sure the DOM is there before try to access it. Hoping it will make a flaky test stable. --- examples/data-channels/jsfiddle/demo.js | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/examples/data-channels/jsfiddle/demo.js b/examples/data-channels/jsfiddle/demo.js index 5dc394dcb4e..16d9b3ffc0d 100644 --- a/examples/data-channels/jsfiddle/demo.js +++ b/examples/data-channels/jsfiddle/demo.js @@ -17,9 +17,19 @@ sendChannel.onopen = () => console.log('sendChannel has opened') sendChannel.onmessage = e => log(`Message from DataChannel '${sendChannel.label}' payload '${e.data}'`) pc.oniceconnectionstatechange = e => log(pc.iceConnectionState) +// after dom is loaded get the candidate pc.onicecandidate = event => { if (event.candidate === null) { - document.getElementById('localSessionDescription').value = btoa(JSON.stringify(pc.localDescription)) + const offer = btoa(JSON.stringify(pc.localDescription)) + // make sure the DOM is ready + if (document.readyState === 'complete') { + const browserSDP = document.getElementById('localSessionDescription') + browserSDP.value = offer + } else + document.addEventListener('DOMContentLoaded', () => { + const browserSDP = document.getElementById('localSessionDescription') + browserSDP.value = offer + }) } } From 29c8c06140b54456262a544ab8f924b410776918 Mon Sep 17 00:00:00 2001 From: Jerko Steiner Date: Fri, 27 Jan 2023 15:24:07 +0100 Subject: [PATCH 17/33] Revert "Add currentDirection to RTPTransceiver" This reverts commit 045df4c4bfd47ae0d657af98053f18e9a707ac34. --- peerconnection.go | 56 +-------------------------- peerconnection_renegotiation_test.go | 57 +++------------------------- rtptransceiver.go | 22 ++--------- 3 files changed, 10 insertions(+), 125 deletions(-) diff --git a/peerconnection.go b/peerconnection.go index 900dae1a8af..e15424ddac5 100644 --- a/peerconnection.go +++ b/peerconnection.go @@ -991,7 +991,6 @@ func (pc *PeerConnection) SetLocalDescription(desc SessionDescription) error { weAnswer := desc.Type == SDPTypeAnswer remoteDesc := pc.RemoteDescription() if weAnswer && remoteDesc != nil { - _ = setRTPTransceiverCurrentDirection(&desc, currentTransceivers, false) if err := pc.startRTPSenders(currentTransceivers); err != nil { return err } @@ -1151,7 +1150,6 @@ func (pc *PeerConnection) SetRemoteDescription(desc SessionDescription) error { if isRenegotation { if weOffer { - _ = setRTPTransceiverCurrentDirection(&desc, currentTransceivers, true) if err = pc.startRTPSenders(currentTransceivers); err != nil { return err } @@ -1181,7 +1179,6 @@ func (pc *PeerConnection) SetRemoteDescription(desc SessionDescription) error { // Start the networking in a new routine since it will block until // the connection is actually established. if weOffer { - _ = setRTPTransceiverCurrentDirection(&desc, currentTransceivers, true) if err := pc.startRTPSenders(currentTransceivers); err != nil { return err } @@ -1240,51 +1237,6 @@ func (pc *PeerConnection) startReceiver(incoming trackDetails, receiver *RTPRece } } -func setRTPTransceiverCurrentDirection(answer *SessionDescription, currentTransceivers []*RTPTransceiver, weOffer bool) error { - currentTransceivers = append([]*RTPTransceiver{}, currentTransceivers...) - for _, media := range answer.parsed.MediaDescriptions { - midValue := getMidValue(media) - if midValue == "" { - return errPeerConnRemoteDescriptionWithoutMidValue - } - - if media.MediaName.Media == mediaSectionApplication { - continue - } - - var t *RTPTransceiver - t, currentTransceivers = findByMid(midValue, currentTransceivers) - - if t == nil { - return fmt.Errorf("%w: %q", errPeerConnTranscieverMidNil, midValue) - } - - direction := getPeerDirection(media) - if direction == RTPTransceiverDirection(Unknown) { - continue - } - - // reverse direction if it was a remote answer - if weOffer { - switch direction { - case RTPTransceiverDirectionSendonly: - direction = RTPTransceiverDirectionRecvonly - case RTPTransceiverDirectionRecvonly: - // Pion will answer recvonly with a offer recvonly transceiver, so we should - // not change the direction to sendonly if we are the offerer, otherwise this - // tranceiver can't be reuse for AddTrack - if t.Direction() != RTPTransceiverDirectionRecvonly { - direction = RTPTransceiverDirectionSendonly - } - default: - } - } - - t.setCurrentDirection(direction) - } - return nil -} - func runIfNewReceiver( incomingTrack trackDetails, transceivers []*RTPTransceiver, @@ -1771,13 +1723,7 @@ func (pc *PeerConnection) AddTrack(track TrackLocal) (*RTPSender, error) { pc.mu.Lock() defer pc.mu.Unlock() for _, t := range pc.rtpTransceivers { - currentDirection := t.getCurrentDirection() - // According to https://www.w3.org/TR/webrtc/#dom-rtcpeerconnection-addtrack, if the - // transceiver can be reused only if it's currentDirection never be sendrecv or sendonly. - // But that will cause sdp inflate. So we only check currentDirection's current value, - // that's worked for all browsers. - if !t.stopped && t.kind == track.Kind() && t.Sender() == nil && - !(currentDirection == RTPTransceiverDirectionSendrecv || currentDirection == RTPTransceiverDirectionSendonly) { + if !t.stopped && t.kind == track.Kind() && t.Sender() == nil { sender, err := pc.api.NewRTPSender(track, pc.dtlsTransport) if err == nil { err = t.SetSender(sender, track) diff --git a/peerconnection_renegotiation_test.go b/peerconnection_renegotiation_test.go index e5382ff0c94..2034c288cff 100644 --- a/peerconnection_renegotiation_test.go +++ b/peerconnection_renegotiation_test.go @@ -128,14 +128,14 @@ func TestPeerConnection_Renegotiation_AddRecvonlyTransceiver(t *testing.T) { pcOffer.OnTrack(func(track *TrackRemote, r *RTPReceiver) { onTrackFiredFunc() }) - assert.NoError(t, signalPair(pcAnswer, pcOffer)) } else { pcAnswer.OnTrack(func(track *TrackRemote, r *RTPReceiver) { onTrackFiredFunc() }) - assert.NoError(t, signalPair(pcOffer, pcAnswer)) } + assert.NoError(t, signalPair(pcOffer, pcAnswer)) + sendVideoUntilDone(onTrackFired.Done(), t, []*TrackLocalStaticSample{localTrack}) closePairNow(t, pcOffer, pcAnswer) @@ -380,7 +380,6 @@ func TestPeerConnection_Transceiver_Mid(t *testing.T) { offer, err = pcOffer.CreateOffer(nil) assert.NoError(t, err) - assert.NoError(t, pcOffer.SetLocalDescription(offer)) assert.Equal(t, len(offer.parsed.MediaDescriptions), 2) @@ -392,11 +391,6 @@ func TestPeerConnection_Transceiver_Mid(t *testing.T) { pcOffer.ops.Done() pcAnswer.ops.Done() - assert.NoError(t, pcAnswer.SetRemoteDescription(offer)) - answer, err = pcAnswer.CreateAnswer(nil) - assert.NoError(t, err) - assert.NoError(t, pcOffer.SetRemoteDescription(answer)) - track3, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8}, "video", "pion3") require.NoError(t, err) @@ -474,12 +468,12 @@ func TestPeerConnection_Renegotiation_CodecChange(t *testing.T) { require.NoError(t, pcOffer.RemoveTrack(sender1)) - require.NoError(t, signalPair(pcOffer, pcAnswer)) - <-tracksClosed - sender2, err := pcOffer.AddTrack(track2) require.NoError(t, err) + require.NoError(t, signalPair(pcOffer, pcAnswer)) + <-tracksClosed + transceivers = pcOffer.GetTransceivers() require.Equal(t, 1, len(transceivers)) require.Equal(t, "0", transceivers[0].Mid()) @@ -1152,47 +1146,6 @@ func TestPeerConnection_Renegotiation_Simulcast(t *testing.T) { }) } -func TestPeerConnection_Regegotiation_ReuseTransceiver(t *testing.T) { - lim := test.TimeOut(time.Second * 30) - defer lim.Stop() - - report := test.CheckRoutines(t) - defer report() - - pcOffer, pcAnswer, err := newPair() - if err != nil { - t.Fatal(err) - } - - vp8Track, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8}, "foo", "bar") - assert.NoError(t, err) - sender, err := pcOffer.AddTrack(vp8Track) - assert.NoError(t, err) - assert.NoError(t, signalPair(pcOffer, pcAnswer)) - - assert.Equal(t, len(pcOffer.GetTransceivers()), 1) - assert.Equal(t, pcOffer.GetTransceivers()[0].getCurrentDirection(), RTPTransceiverDirectionSendonly) - assert.NoError(t, pcOffer.RemoveTrack(sender)) - assert.Equal(t, pcOffer.GetTransceivers()[0].getCurrentDirection(), RTPTransceiverDirectionSendonly) - - // should not reuse tranceiver - vp8Track2, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8}, "foo", "bar") - assert.NoError(t, err) - sender2, err := pcOffer.AddTrack(vp8Track2) - assert.NoError(t, err) - assert.Equal(t, len(pcOffer.GetTransceivers()), 2) - assert.NoError(t, signalPair(pcOffer, pcAnswer)) - assert.True(t, sender2.rtpTransceiver == pcOffer.GetTransceivers()[1]) - - // should reuse first transceiver - sender, err = pcOffer.AddTrack(vp8Track) - assert.NoError(t, err) - assert.Equal(t, len(pcOffer.GetTransceivers()), 2) - assert.True(t, sender.rtpTransceiver == pcOffer.GetTransceivers()[0]) - - closePairNow(t, pcOffer, pcAnswer) -} - func TestPeerConnection_Renegotiation_MidConflict(t *testing.T) { lim := test.TimeOut(time.Second * 30) defer lim.Stop() diff --git a/rtptransceiver.go b/rtptransceiver.go index f94b9ed70aa..776e0108ca0 100644 --- a/rtptransceiver.go +++ b/rtptransceiver.go @@ -13,11 +13,10 @@ import ( // RTPTransceiver represents a combination of an RTPSender and an RTPReceiver that share a common mid. type RTPTransceiver struct { - mid atomic.Value // string - sender atomic.Value // *RTPSender - receiver atomic.Value // *RTPReceiver - direction atomic.Value // RTPTransceiverDirection - currentDirection atomic.Value // RTPTransceiverDirection + mid atomic.Value // string + sender atomic.Value // *RTPSender + receiver atomic.Value // *RTPReceiver + direction atomic.Value // RTPTransceiverDirection codecs []RTPCodecParameters // User provided codecs via SetCodecPreferences @@ -39,7 +38,6 @@ func newRTPTransceiver( t.setReceiver(receiver) t.setSender(sender) t.setDirection(direction) - t.setCurrentDirection(RTPTransceiverDirection(Unknown)) return t } @@ -162,7 +160,6 @@ func (t *RTPTransceiver) Stop() error { } t.setDirection(RTPTransceiverDirectionInactive) - t.setCurrentDirection(RTPTransceiverDirectionInactive) return nil } @@ -182,17 +179,6 @@ func (t *RTPTransceiver) setDirection(d RTPTransceiverDirection) { t.direction.Store(d) } -func (t *RTPTransceiver) setCurrentDirection(d RTPTransceiverDirection) { - t.currentDirection.Store(d) -} - -func (t *RTPTransceiver) getCurrentDirection() RTPTransceiverDirection { - if v, ok := t.currentDirection.Load().(RTPTransceiverDirection); ok { - return v - } - return RTPTransceiverDirection(Unknown) -} - func (t *RTPTransceiver) setSendingTrack(track TrackLocal) error { if err := t.Sender().ReplaceTrack(track); err != nil { return err From 068dfd61d112e72a33e1d89c00b876c7f116f2c5 Mon Sep 17 00:00:00 2001 From: Jerko Steiner Date: Sat, 28 Jan 2023 13:39:58 +0100 Subject: [PATCH 18/33] Revert "Revert "Add currentDirection to RTPTransceiver"" This reverts commit a92c400e5ab794536d64072b32e0c05aa330dddb. --- peerconnection.go | 56 ++++++++++++++++++++++++++- peerconnection_renegotiation_test.go | 57 +++++++++++++++++++++++++--- rtptransceiver.go | 22 +++++++++-- 3 files changed, 125 insertions(+), 10 deletions(-) diff --git a/peerconnection.go b/peerconnection.go index e15424ddac5..900dae1a8af 100644 --- a/peerconnection.go +++ b/peerconnection.go @@ -991,6 +991,7 @@ func (pc *PeerConnection) SetLocalDescription(desc SessionDescription) error { weAnswer := desc.Type == SDPTypeAnswer remoteDesc := pc.RemoteDescription() if weAnswer && remoteDesc != nil { + _ = setRTPTransceiverCurrentDirection(&desc, currentTransceivers, false) if err := pc.startRTPSenders(currentTransceivers); err != nil { return err } @@ -1150,6 +1151,7 @@ func (pc *PeerConnection) SetRemoteDescription(desc SessionDescription) error { if isRenegotation { if weOffer { + _ = setRTPTransceiverCurrentDirection(&desc, currentTransceivers, true) if err = pc.startRTPSenders(currentTransceivers); err != nil { return err } @@ -1179,6 +1181,7 @@ func (pc *PeerConnection) SetRemoteDescription(desc SessionDescription) error { // Start the networking in a new routine since it will block until // the connection is actually established. if weOffer { + _ = setRTPTransceiverCurrentDirection(&desc, currentTransceivers, true) if err := pc.startRTPSenders(currentTransceivers); err != nil { return err } @@ -1237,6 +1240,51 @@ func (pc *PeerConnection) startReceiver(incoming trackDetails, receiver *RTPRece } } +func setRTPTransceiverCurrentDirection(answer *SessionDescription, currentTransceivers []*RTPTransceiver, weOffer bool) error { + currentTransceivers = append([]*RTPTransceiver{}, currentTransceivers...) + for _, media := range answer.parsed.MediaDescriptions { + midValue := getMidValue(media) + if midValue == "" { + return errPeerConnRemoteDescriptionWithoutMidValue + } + + if media.MediaName.Media == mediaSectionApplication { + continue + } + + var t *RTPTransceiver + t, currentTransceivers = findByMid(midValue, currentTransceivers) + + if t == nil { + return fmt.Errorf("%w: %q", errPeerConnTranscieverMidNil, midValue) + } + + direction := getPeerDirection(media) + if direction == RTPTransceiverDirection(Unknown) { + continue + } + + // reverse direction if it was a remote answer + if weOffer { + switch direction { + case RTPTransceiverDirectionSendonly: + direction = RTPTransceiverDirectionRecvonly + case RTPTransceiverDirectionRecvonly: + // Pion will answer recvonly with a offer recvonly transceiver, so we should + // not change the direction to sendonly if we are the offerer, otherwise this + // tranceiver can't be reuse for AddTrack + if t.Direction() != RTPTransceiverDirectionRecvonly { + direction = RTPTransceiverDirectionSendonly + } + default: + } + } + + t.setCurrentDirection(direction) + } + return nil +} + func runIfNewReceiver( incomingTrack trackDetails, transceivers []*RTPTransceiver, @@ -1723,7 +1771,13 @@ func (pc *PeerConnection) AddTrack(track TrackLocal) (*RTPSender, error) { pc.mu.Lock() defer pc.mu.Unlock() for _, t := range pc.rtpTransceivers { - if !t.stopped && t.kind == track.Kind() && t.Sender() == nil { + currentDirection := t.getCurrentDirection() + // According to https://www.w3.org/TR/webrtc/#dom-rtcpeerconnection-addtrack, if the + // transceiver can be reused only if it's currentDirection never be sendrecv or sendonly. + // But that will cause sdp inflate. So we only check currentDirection's current value, + // that's worked for all browsers. + if !t.stopped && t.kind == track.Kind() && t.Sender() == nil && + !(currentDirection == RTPTransceiverDirectionSendrecv || currentDirection == RTPTransceiverDirectionSendonly) { sender, err := pc.api.NewRTPSender(track, pc.dtlsTransport) if err == nil { err = t.SetSender(sender, track) diff --git a/peerconnection_renegotiation_test.go b/peerconnection_renegotiation_test.go index 2034c288cff..e5382ff0c94 100644 --- a/peerconnection_renegotiation_test.go +++ b/peerconnection_renegotiation_test.go @@ -128,14 +128,14 @@ func TestPeerConnection_Renegotiation_AddRecvonlyTransceiver(t *testing.T) { pcOffer.OnTrack(func(track *TrackRemote, r *RTPReceiver) { onTrackFiredFunc() }) + assert.NoError(t, signalPair(pcAnswer, pcOffer)) } else { pcAnswer.OnTrack(func(track *TrackRemote, r *RTPReceiver) { onTrackFiredFunc() }) + assert.NoError(t, signalPair(pcOffer, pcAnswer)) } - assert.NoError(t, signalPair(pcOffer, pcAnswer)) - sendVideoUntilDone(onTrackFired.Done(), t, []*TrackLocalStaticSample{localTrack}) closePairNow(t, pcOffer, pcAnswer) @@ -380,6 +380,7 @@ func TestPeerConnection_Transceiver_Mid(t *testing.T) { offer, err = pcOffer.CreateOffer(nil) assert.NoError(t, err) + assert.NoError(t, pcOffer.SetLocalDescription(offer)) assert.Equal(t, len(offer.parsed.MediaDescriptions), 2) @@ -391,6 +392,11 @@ func TestPeerConnection_Transceiver_Mid(t *testing.T) { pcOffer.ops.Done() pcAnswer.ops.Done() + assert.NoError(t, pcAnswer.SetRemoteDescription(offer)) + answer, err = pcAnswer.CreateAnswer(nil) + assert.NoError(t, err) + assert.NoError(t, pcOffer.SetRemoteDescription(answer)) + track3, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8}, "video", "pion3") require.NoError(t, err) @@ -468,12 +474,12 @@ func TestPeerConnection_Renegotiation_CodecChange(t *testing.T) { require.NoError(t, pcOffer.RemoveTrack(sender1)) - sender2, err := pcOffer.AddTrack(track2) - require.NoError(t, err) - require.NoError(t, signalPair(pcOffer, pcAnswer)) <-tracksClosed + sender2, err := pcOffer.AddTrack(track2) + require.NoError(t, err) + require.NoError(t, signalPair(pcOffer, pcAnswer)) transceivers = pcOffer.GetTransceivers() require.Equal(t, 1, len(transceivers)) require.Equal(t, "0", transceivers[0].Mid()) @@ -1146,6 +1152,47 @@ func TestPeerConnection_Renegotiation_Simulcast(t *testing.T) { }) } +func TestPeerConnection_Regegotiation_ReuseTransceiver(t *testing.T) { + lim := test.TimeOut(time.Second * 30) + defer lim.Stop() + + report := test.CheckRoutines(t) + defer report() + + pcOffer, pcAnswer, err := newPair() + if err != nil { + t.Fatal(err) + } + + vp8Track, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8}, "foo", "bar") + assert.NoError(t, err) + sender, err := pcOffer.AddTrack(vp8Track) + assert.NoError(t, err) + assert.NoError(t, signalPair(pcOffer, pcAnswer)) + + assert.Equal(t, len(pcOffer.GetTransceivers()), 1) + assert.Equal(t, pcOffer.GetTransceivers()[0].getCurrentDirection(), RTPTransceiverDirectionSendonly) + assert.NoError(t, pcOffer.RemoveTrack(sender)) + assert.Equal(t, pcOffer.GetTransceivers()[0].getCurrentDirection(), RTPTransceiverDirectionSendonly) + + // should not reuse tranceiver + vp8Track2, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8}, "foo", "bar") + assert.NoError(t, err) + sender2, err := pcOffer.AddTrack(vp8Track2) + assert.NoError(t, err) + assert.Equal(t, len(pcOffer.GetTransceivers()), 2) + assert.NoError(t, signalPair(pcOffer, pcAnswer)) + assert.True(t, sender2.rtpTransceiver == pcOffer.GetTransceivers()[1]) + + // should reuse first transceiver + sender, err = pcOffer.AddTrack(vp8Track) + assert.NoError(t, err) + assert.Equal(t, len(pcOffer.GetTransceivers()), 2) + assert.True(t, sender.rtpTransceiver == pcOffer.GetTransceivers()[0]) + + closePairNow(t, pcOffer, pcAnswer) +} + func TestPeerConnection_Renegotiation_MidConflict(t *testing.T) { lim := test.TimeOut(time.Second * 30) defer lim.Stop() diff --git a/rtptransceiver.go b/rtptransceiver.go index 776e0108ca0..f94b9ed70aa 100644 --- a/rtptransceiver.go +++ b/rtptransceiver.go @@ -13,10 +13,11 @@ import ( // RTPTransceiver represents a combination of an RTPSender and an RTPReceiver that share a common mid. type RTPTransceiver struct { - mid atomic.Value // string - sender atomic.Value // *RTPSender - receiver atomic.Value // *RTPReceiver - direction atomic.Value // RTPTransceiverDirection + mid atomic.Value // string + sender atomic.Value // *RTPSender + receiver atomic.Value // *RTPReceiver + direction atomic.Value // RTPTransceiverDirection + currentDirection atomic.Value // RTPTransceiverDirection codecs []RTPCodecParameters // User provided codecs via SetCodecPreferences @@ -38,6 +39,7 @@ func newRTPTransceiver( t.setReceiver(receiver) t.setSender(sender) t.setDirection(direction) + t.setCurrentDirection(RTPTransceiverDirection(Unknown)) return t } @@ -160,6 +162,7 @@ func (t *RTPTransceiver) Stop() error { } t.setDirection(RTPTransceiverDirectionInactive) + t.setCurrentDirection(RTPTransceiverDirectionInactive) return nil } @@ -179,6 +182,17 @@ func (t *RTPTransceiver) setDirection(d RTPTransceiverDirection) { t.direction.Store(d) } +func (t *RTPTransceiver) setCurrentDirection(d RTPTransceiverDirection) { + t.currentDirection.Store(d) +} + +func (t *RTPTransceiver) getCurrentDirection() RTPTransceiverDirection { + if v, ok := t.currentDirection.Load().(RTPTransceiverDirection); ok { + return v + } + return RTPTransceiverDirection(Unknown) +} + func (t *RTPTransceiver) setSendingTrack(track TrackLocal) error { if err := t.Sender().ReplaceTrack(track); err != nil { return err From 1050a6d9f72a850bd38e730c89b62a022e045907 Mon Sep 17 00:00:00 2001 From: Benny Daon Date: Mon, 25 Oct 2021 13:32:49 +0300 Subject: [PATCH 19/33] Use OnOpen handler for DataChannels Using an improvment of pion/datachannel, the channel opener can now set an event to be called when the DATA_CHANNEL_ACK message is recieved Resolves #1063 Relates to pion/datachannel#81 --- sctptransport.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sctptransport.go b/sctptransport.go index db7b25256cb..f5a4071d90e 100644 --- a/sctptransport.go +++ b/sctptransport.go @@ -232,7 +232,11 @@ ACCEPT: } <-r.onDataChannel(rtcDC) +<<<<<<< HEAD rtcDC.handleOpen(dc, true, dc.Config.Negotiated) +======= + rtcDC.handleOpen(dc, true) +>>>>>>> c5faa92 (Use OnOpen handler for DataChannels) r.lock.Lock() r.dataChannelsOpened++ From fb4de655b465aa912732920cd64e66b8d63e374a Mon Sep 17 00:00:00 2001 From: Benny Daon Date: Tue, 22 Nov 2022 10:44:46 +0200 Subject: [PATCH 20/33] Cleaning up --- sctptransport.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/sctptransport.go b/sctptransport.go index f5a4071d90e..db7b25256cb 100644 --- a/sctptransport.go +++ b/sctptransport.go @@ -232,11 +232,7 @@ ACCEPT: } <-r.onDataChannel(rtcDC) -<<<<<<< HEAD rtcDC.handleOpen(dc, true, dc.Config.Negotiated) -======= - rtcDC.handleOpen(dc, true) ->>>>>>> c5faa92 (Use OnOpen handler for DataChannels) r.lock.Lock() r.dataChannelsOpened++ From 125f2ddecd55621cdb5d7aacc335112efff6f584 Mon Sep 17 00:00:00 2001 From: Benny Daon Date: Mon, 30 Jan 2023 15:29:22 +0200 Subject: [PATCH 21/33] Fix failed test of the data channel example added a wait loop that checks the ensures the sendChanel is open before hitting send --- ats/data-channels/example.spec.ts | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/ats/data-channels/example.spec.ts b/ats/data-channels/example.spec.ts index 9bd1163026f..bad85fc64b1 100644 --- a/ats/data-channels/example.spec.ts +++ b/ats/data-channels/example.spec.ts @@ -22,7 +22,6 @@ test.describe("pion's data channels example", () => { page.on('load', () => page.evaluate(() => { var newScript = document.createElement('script') newScript.src = 'demo.js' - console.log("loading demo.js") document.head.appendChild(newScript) }) ) @@ -84,7 +83,7 @@ test.describe("pion's data channels example", () => { }) }) test('transmit and receive data', async()=> { - let finished = false + let eof = false let lineCounter = 0 stream.on('data', lines => new Buffer.from(lines).toString().split("\r\n") @@ -93,25 +92,35 @@ test.describe("pion's data channels example", () => { return lineCounter++ if (lineCounter == 1) { + // copy the answer to the page await page.evaluate(async (answer) => document.getElementById("remoteSessionDescription") .value = answer, line) page.locator("data-test-id=start-session").click() - await sleep(3000) + // set the message to EOF await page.evaluate(async () => document.getElementById("message").value = "EOF") + // wait for the send channel to open + let connected = false + while (!connected) { + await sleep(200) + connected = await page.evaluate(() => sendChannel.readyState == "open") + } + // send the message await page.locator("data-test-id=send-message").click() return } + // exit the test when EOF was received from the server if (line.includes("EOF")) - finished=true + eof = true }) ).stderr.on('data', (data) => { console.log("ERROR: " + data) }) - while (!finished) { - await sleep(500) + // wait for the EOF message + while (!eof) { + await sleep(200) } }) }) From 5e799bb93f307e4e60de168e3a2c5cebe6bb1239 Mon Sep 17 00:00:00 2001 From: Benny Daon Date: Mon, 30 Jan 2023 15:53:35 +0200 Subject: [PATCH 22/33] Remove a wrong direction the code was to protected against a situation where ice gathering finished before the DOM is loaded. it never happens. --- examples/data-channels/jsfiddle/demo.js | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/examples/data-channels/jsfiddle/demo.js b/examples/data-channels/jsfiddle/demo.js index 16d9b3ffc0d..fd92a754326 100644 --- a/examples/data-channels/jsfiddle/demo.js +++ b/examples/data-channels/jsfiddle/demo.js @@ -20,16 +20,7 @@ pc.oniceconnectionstatechange = e => log(pc.iceConnectionState) // after dom is loaded get the candidate pc.onicecandidate = event => { if (event.candidate === null) { - const offer = btoa(JSON.stringify(pc.localDescription)) - // make sure the DOM is ready - if (document.readyState === 'complete') { - const browserSDP = document.getElementById('localSessionDescription') - browserSDP.value = offer - } else - document.addEventListener('DOMContentLoaded', () => { - const browserSDP = document.getElementById('localSessionDescription') - browserSDP.value = offer - }) + document.getElementById('localSessionDescription').value = btoa(JSON.stringify(pc.localDescription)) } } From a93de838d5103780a2c7cd8128a81cb9a0cbe733 Mon Sep 17 00:00:00 2001 From: Benny Daon Date: Mon, 30 Jan 2023 16:06:49 +0200 Subject: [PATCH 23/33] Save test result for failed tests the files will be available in the action's page, and could be open using playwright trace app. --- .github/workflows/ats.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/ats.yaml b/.github/workflows/ats.yaml index 7973682f687..b997bffcf82 100644 --- a/.github/workflows/ats.yaml +++ b/.github/workflows/ats.yaml @@ -15,3 +15,9 @@ jobs: uses: actions/checkout@v3 - name: run tests run: ats/run + - name: Upload test results + if: ${{ failure() }} + uses: actions/upload-artifact@v2 + with: + name: playwright-report + path: ats/result From fe566f8d1aa91edc4c821862f0e96485b0dfa985 Mon Sep 17 00:00:00 2001 From: Benny Daon Date: Mon, 30 Jan 2023 16:40:37 +0200 Subject: [PATCH 24/33] Cleanup server output adding a script to help ensure only the answer will be printed --- ats/data-channels/example.spec.ts | 5 ++--- ats/data-channels/start_server.bash | 4 ++++ 2 files changed, 6 insertions(+), 3 deletions(-) create mode 100644 ats/data-channels/start_server.bash diff --git a/ats/data-channels/example.spec.ts b/ats/data-channels/example.spec.ts index bad85fc64b1..dedbeacbb6a 100644 --- a/ats/data-channels/example.spec.ts +++ b/ats/data-channels/example.spec.ts @@ -2,7 +2,6 @@ import { Buffer } from 'node:buffer'; import { test, expect, Page, BrowserContext } from '@playwright/test' import { Client } from 'ssh2' -const GOBIN = "/usr/local/go/bin/go" test.describe("pion's data channels example", () => { @@ -67,8 +66,8 @@ test.describe("pion's data channels example", () => { } try { stream = await new Promise((resolve, reject) => { - const dir = "/go/src/github.com/pion/webrtc/examples/data-channels" - SSHconn.exec(`bash -c 'cd ${dir}; echo ${offer} | ${GOBIN} run .'`, + const path = "/go/src/github.com/pion/webrtc/ats/data-channels/start_server.bash" + SSHconn.exec(`bash ${path} ${offer}`, { pty: true }, async (err, s) => { if (err) reject(err) diff --git a/ats/data-channels/start_server.bash b/ats/data-channels/start_server.bash new file mode 100644 index 00000000000..ddd9a196302 --- /dev/null +++ b/ats/data-channels/start_server.bash @@ -0,0 +1,4 @@ +GO=/usr/local/go/bin/go +cd "/go/src/github.com/pion/webrtc/examples/data-channels" +$GO build . > /dev/null 2>&1 +echo $1 | ./data-channels From 47c06893d0536136d1ab02fa15fc8804e36ddbbf Mon Sep 17 00:00:00 2001 From: Benny Daon Date: Mon, 30 Jan 2023 17:04:08 +0200 Subject: [PATCH 25/33] Add more detailed error when build fails problem is, it's all get squeezed in the answer field.. --- ats/data-channels/start_server.bash | 11 +++++++++-- ats/infra/pion/Dockerfile | 1 - 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/ats/data-channels/start_server.bash b/ats/data-channels/start_server.bash index ddd9a196302..75400c4014d 100644 --- a/ats/data-channels/start_server.bash +++ b/ats/data-channels/start_server.bash @@ -1,4 +1,11 @@ GO=/usr/local/go/bin/go cd "/go/src/github.com/pion/webrtc/examples/data-channels" -$GO build . > /dev/null 2>&1 -echo $1 | ./data-channels +TMP=`mktemp` +$GO build . > $TMP 2>&1 + +if [ $? -eq 0 ]; then + echo $1 | ./data-channels +else + cat $TMP +fi +rm $TMP diff --git a/ats/infra/pion/Dockerfile b/ats/infra/pion/Dockerfile index 2f0877a650d..27831d1832e 100644 --- a/ats/infra/pion/Dockerfile +++ b/ats/infra/pion/Dockerfile @@ -2,7 +2,6 @@ FROM golang:bullseye RUN apt-get update RUN apt-get install -y git bash openssh-server COPY ./ats/infra/pion/ssh_config /etc/ssh/ -RUN /etc/init.d/ssh start # pion user with pion password to be used by clients' ssh connections RUN useradd -s /bin/bash -d /home/pion -M -p '$y$j9T$6LsNr6MtK4Nt6NeECphjP1$Try0q9dVUdZGihzzxJZ0soO09wQhseYzyB/E2Jf4tO8' pion RUN mkdir /home/pion From 72dc52e1c4d48a3c302fb6b8eaa6a8e12b467a06 Mon Sep 17 00:00:00 2001 From: Benny Daon Date: Mon, 30 Jan 2023 17:24:32 +0200 Subject: [PATCH 26/33] Get last 5 lines of error in a single line that way I have a chance of figuring out what the error is --- ats/data-channels/start_server.bash | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ats/data-channels/start_server.bash b/ats/data-channels/start_server.bash index 75400c4014d..3d8ebf66574 100644 --- a/ats/data-channels/start_server.bash +++ b/ats/data-channels/start_server.bash @@ -6,6 +6,6 @@ $GO build . > $TMP 2>&1 if [ $? -eq 0 ]; then echo $1 | ./data-channels else - cat $TMP + tail -5 $TMP | tr '\n' ':' fi rm $TMP From 9d98f238b5a4ad6f851ce04fa9ab7380cbe8f2cd Mon Sep 17 00:00:00 2001 From: Benny Daon Date: Mon, 30 Jan 2023 17:31:10 +0200 Subject: [PATCH 27/33] fix mising vcs information when buildign the data channel example --- ats/data-channels/start_server.bash | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ats/data-channels/start_server.bash b/ats/data-channels/start_server.bash index 3d8ebf66574..ca98290617a 100644 --- a/ats/data-channels/start_server.bash +++ b/ats/data-channels/start_server.bash @@ -1,7 +1,7 @@ GO=/usr/local/go/bin/go cd "/go/src/github.com/pion/webrtc/examples/data-channels" TMP=`mktemp` -$GO build . > $TMP 2>&1 +$GO build -buildvcs=false . > $TMP 2>&1 if [ $? -eq 0 ]; then echo $1 | ./data-channels From 9832bc62f16b20b09d6b354967feaae06ef44cc2 Mon Sep 17 00:00:00 2001 From: Benny Daon Date: Mon, 30 Jan 2023 17:38:56 +0200 Subject: [PATCH 28/33] When building an example, use home dir otherwise we get a permission error --- ats/data-channels/start_server.bash | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ats/data-channels/start_server.bash b/ats/data-channels/start_server.bash index ca98290617a..712e9495e6e 100644 --- a/ats/data-channels/start_server.bash +++ b/ats/data-channels/start_server.bash @@ -1,10 +1,10 @@ GO=/usr/local/go/bin/go cd "/go/src/github.com/pion/webrtc/examples/data-channels" TMP=`mktemp` -$GO build -buildvcs=false . > $TMP 2>&1 +$GO build -buildvcs=false -o $HOME/datachannels . > $TMP 2>&1 if [ $? -eq 0 ]; then - echo $1 | ./data-channels + echo $1 | $HOME/datachannels else tail -5 $TMP | tr '\n' ':' fi From 84be954ed64e065c9d6bbd356ae163dc60b23718 Mon Sep 17 00:00:00 2001 From: Benny Daon Date: Sun, 5 Feb 2023 10:23:12 +0200 Subject: [PATCH 29/33] Rename the new folder to acceptance_tests --- .../{ats.yaml => acceptance_tests.yaml} | 2 +- {ats => acceptance_tests}/.gitignore | 0 {ats => acceptance_tests}/README.md | 34 ++++++++++--------- .../data-channels/client | 0 .../data-channels/example.spec.ts | 0 .../data-channels/lab.yaml | 8 ++--- {ats => acceptance_tests}/e2e/Dockerfile | 2 +- {ats => acceptance_tests}/e2e/e2e_test.go | 0 {ats => acceptance_tests}/e2e/lab.yaml | 2 +- {ats => acceptance_tests}/e2e/test.html | 0 .../infra/pion/Dockerfile | 2 +- .../infra/pion/ssh_config | 0 .../infra/playwright/Dockerfile | 2 +- .../infra/playwright/package.json | 0 .../infra/playwright/playwright.config.ts | 0 .../infra/playwright/yarn.lock | 0 .../pion-to-pion/lab.yaml | 0 {ats => acceptance_tests}/run | 8 ++--- examples/pion-to-pion/README.md | 2 +- 19 files changed, 32 insertions(+), 30 deletions(-) rename .github/workflows/{ats.yaml => acceptance_tests.yaml} (88%) rename {ats => acceptance_tests}/.gitignore (100%) rename {ats => acceptance_tests}/README.md (57%) rename {ats => acceptance_tests}/data-channels/client (100%) rename {ats => acceptance_tests}/data-channels/example.spec.ts (100%) rename {ats => acceptance_tests}/data-channels/lab.yaml (68%) rename {ats => acceptance_tests}/e2e/Dockerfile (72%) rename {ats => acceptance_tests}/e2e/e2e_test.go (100%) rename {ats => acceptance_tests}/e2e/lab.yaml (69%) rename {ats => acceptance_tests}/e2e/test.html (100%) rename {ats => acceptance_tests}/infra/pion/Dockerfile (87%) rename {ats => acceptance_tests}/infra/pion/ssh_config (100%) rename {ats => acceptance_tests}/infra/playwright/Dockerfile (84%) rename {ats => acceptance_tests}/infra/playwright/package.json (100%) rename {ats => acceptance_tests}/infra/playwright/playwright.config.ts (100%) rename {ats => acceptance_tests}/infra/playwright/yarn.lock (100%) rename {ats => acceptance_tests}/pion-to-pion/lab.yaml (100%) rename {ats => acceptance_tests}/run (87%) diff --git a/.github/workflows/ats.yaml b/.github/workflows/acceptance_tests.yaml similarity index 88% rename from .github/workflows/ats.yaml rename to .github/workflows/acceptance_tests.yaml index 7973682f687..dd35c774f76 100644 --- a/.github/workflows/ats.yaml +++ b/.github/workflows/acceptance_tests.yaml @@ -14,4 +14,4 @@ jobs: - name: checkout uses: actions/checkout@v3 - name: run tests - run: ats/run + run: acceptance_tests/run diff --git a/ats/.gitignore b/acceptance_tests/.gitignore similarity index 100% rename from ats/.gitignore rename to acceptance_tests/.gitignore diff --git a/ats/README.md b/acceptance_tests/README.md similarity index 57% rename from ats/README.md rename to acceptance_tests/README.md index c1d302a59f9..34d18375c63 100644 --- a/ats/README.md +++ b/acceptance_tests/README.md @@ -1,12 +1,12 @@ -# Acceptance Test Specifications +# Acceptance Test Procedure -TL:DR; From the project's root `./ats/run` +TL:DR; From the project's root `./acceptance_tests/run` -This directory contains Acceptance Test Specifications AKA black box tests. +This directory contains Acceptance Test Procedure AKA black box tests. The tests are running over a lab managed by docker-compose and using playwright for browser automation. -The `ats` directory includes a special directory `infra` with the infrastructure +The `acceptance_tests` directory includes a special directory `infra` with the infrastructure required by the tests. For example, there's a `./infra/pion` directory with a Dockerfile and an SSH config file. @@ -15,7 +15,7 @@ Unlike production containers, lab containers' entry point often includes setup code usually found in the Dockerfile. This is done for flexibility and speed as we want the lab to use the latest source -The script support some old style options, use `./ats/run -h` to see the +The script support some old style options, use `./acceptance_tests/run -h` to see the all the options. It also accepts one of more argument with a directory name. ## The setup @@ -26,15 +26,15 @@ Thanks to compose, a name of a service is also its address so The runner supports one environment variable - `PWOPTS` - one can use to pass options to playwright. The default is `-x` stopping the test on the first -failure. It's rigged this way becuase ATSs are usually complex scenarios. +failure. It's rigged this way becuase ATPs are usually complex scenarios. Unlike unit tests, where each test function is independent, here each functions -is a step in one test specification. Once a step failed, `-x` makes playwright ignore +is a step in one test procedure. Once a step failed, `-x` makes playwright ignore the rest of the file. To get help on playwright options run: ```bash -docker compose -f ats/data-channels/lab.yaml --project-directory . run --entrypoint "npx playwright test --help" runner +docker compose -f acceptance_tests/data-channels/lab.yaml --project-directory . run --entrypoint "npx playwright test --help" runner ``` The above command uses the lab from the data-channels tests to bring up a runner @@ -44,7 +44,7 @@ relative to the project's root. ## Adding a test -To create the `fubar` test, create a new directory in `./ats/fubar` and start working +To create the `fubar` test, create a new directory in `./acceptance_tests/fubar` and start working one your `lab.yaml`. If your tests include a browser client your runner is best using the image from `infra/playwright`: @@ -54,18 +54,20 @@ services: runner: build: context: . - dockerfile: ./ats/infra/playwright/Dockerfile + dockerfile: ./acceptance_tests/infra/playwright/Dockerfile volumes: - - ./ats/fubar:/specs - - ./ats/result:/result + - ./acceptance_tests/fubar:/specs + - ./acceptance_tests/result:/result environment: PWOPTS: ${PWOPTS--x} ``` -Not that we are mapping `/specs` to `ats/fubar` as the first is where the image looks -for specs. Once you've added your specs file to `./ats/fubar` it will run whener you -`./ats/run`. In fact, all a sub-directory of ats needs is a `lab.yaml` file and the +Not that we are mapping `/specs` to `acceptance_tests/fubar` as the first is where the image looks +for specs. Once you've added your specs file to `./acceptance_tests/fubar` it will run whener you +`./acceptance_tests/run`. In fact, all a sub-directory of acceptance_tests needs is a `lab.yaml` file and the run script will try to bring it up. -If you want to run just fubar you can use `./ats/run ats/fubar`. +If you want to run just fubar you can use `./acceptance_tests/run acceptance_tests/fubar`. To run a clean build of fubar, ignoring all cache, use `-z`. + + diff --git a/ats/data-channels/client b/acceptance_tests/data-channels/client similarity index 100% rename from ats/data-channels/client rename to acceptance_tests/data-channels/client diff --git a/ats/data-channels/example.spec.ts b/acceptance_tests/data-channels/example.spec.ts similarity index 100% rename from ats/data-channels/example.spec.ts rename to acceptance_tests/data-channels/example.spec.ts diff --git a/ats/data-channels/lab.yaml b/acceptance_tests/data-channels/lab.yaml similarity index 68% rename from ats/data-channels/lab.yaml rename to acceptance_tests/data-channels/lab.yaml index a9807d5158b..c260b2b2f78 100644 --- a/ats/data-channels/lab.yaml +++ b/acceptance_tests/data-channels/lab.yaml @@ -3,10 +3,10 @@ services: runner: build: context: . - dockerfile: ./ats/infra/playwright/Dockerfile + dockerfile: ./acceptance_tests/infra/playwright/Dockerfile volumes: - - ./ats/data-channels:/specs - - ./ats/result:/result + - ./acceptance_tests/data-channels:/specs + - ./acceptance_tests/result:/result depends_on: - client - pion @@ -23,7 +23,7 @@ services: pion: build: context: . - dockerfile: ./ats/infra/pion/Dockerfile + dockerfile: ./acceptance_tests/infra/pion/Dockerfile expose: - "22" volumes: diff --git a/ats/e2e/Dockerfile b/acceptance_tests/e2e/Dockerfile similarity index 72% rename from ats/e2e/Dockerfile rename to acceptance_tests/e2e/Dockerfile index 9883251327f..ff58d3a48c6 100644 --- a/ats/e2e/Dockerfile +++ b/acceptance_tests/e2e/Dockerfile @@ -6,6 +6,6 @@ RUN apk add --no-cache \ ENV CGO_ENABLED=0 -WORKDIR /go/src/github.com/pion/webrtc/ats/e2e +WORKDIR /go/src/github.com/pion/webrtc/acceptance_tests/e2e CMD ["go", "test", "-tags=e2e", "-v", "."] diff --git a/ats/e2e/e2e_test.go b/acceptance_tests/e2e/e2e_test.go similarity index 100% rename from ats/e2e/e2e_test.go rename to acceptance_tests/e2e/e2e_test.go diff --git a/ats/e2e/lab.yaml b/acceptance_tests/e2e/lab.yaml similarity index 69% rename from ats/e2e/lab.yaml rename to acceptance_tests/e2e/lab.yaml index 7506b33028e..406bb43e5d1 100644 --- a/ats/e2e/lab.yaml +++ b/acceptance_tests/e2e/lab.yaml @@ -3,6 +3,6 @@ services: runner: build: context: . - dockerfile: ./ats/e2e/Dockerfile + dockerfile: ./acceptance_tests/e2e/Dockerfile volumes: - .:/go/src/github.com/pion/webrtc diff --git a/ats/e2e/test.html b/acceptance_tests/e2e/test.html similarity index 100% rename from ats/e2e/test.html rename to acceptance_tests/e2e/test.html diff --git a/ats/infra/pion/Dockerfile b/acceptance_tests/infra/pion/Dockerfile similarity index 87% rename from ats/infra/pion/Dockerfile rename to acceptance_tests/infra/pion/Dockerfile index 2f0877a650d..f305eb9a662 100644 --- a/ats/infra/pion/Dockerfile +++ b/acceptance_tests/infra/pion/Dockerfile @@ -1,7 +1,7 @@ FROM golang:bullseye RUN apt-get update RUN apt-get install -y git bash openssh-server -COPY ./ats/infra/pion/ssh_config /etc/ssh/ +COPY ./acceptance_tests/infra/pion/ssh_config /etc/ssh/ RUN /etc/init.d/ssh start # pion user with pion password to be used by clients' ssh connections RUN useradd -s /bin/bash -d /home/pion -M -p '$y$j9T$6LsNr6MtK4Nt6NeECphjP1$Try0q9dVUdZGihzzxJZ0soO09wQhseYzyB/E2Jf4tO8' pion diff --git a/ats/infra/pion/ssh_config b/acceptance_tests/infra/pion/ssh_config similarity index 100% rename from ats/infra/pion/ssh_config rename to acceptance_tests/infra/pion/ssh_config diff --git a/ats/infra/playwright/Dockerfile b/acceptance_tests/infra/playwright/Dockerfile similarity index 84% rename from ats/infra/playwright/Dockerfile rename to acceptance_tests/infra/playwright/Dockerfile index e5f86670d1f..fa7caf0e8a6 100644 --- a/ats/infra/playwright/Dockerfile +++ b/acceptance_tests/infra/playwright/Dockerfile @@ -1,6 +1,6 @@ FROM mcr.microsoft.com/playwright:v1.26.0-focal ENV NODE_PATH="/usr/lib/node_modules" -COPY ./ats/infra/playwright/* . +COPY ./acceptance_tests/infra/playwright/* . RUN yarn install --frozen-lockfile # /specs is set by the lab, so we only copy the specs on run CMD cp /specs/*.spec.ts . && npx playwright test ${PWOPTS} diff --git a/ats/infra/playwright/package.json b/acceptance_tests/infra/playwright/package.json similarity index 100% rename from ats/infra/playwright/package.json rename to acceptance_tests/infra/playwright/package.json diff --git a/ats/infra/playwright/playwright.config.ts b/acceptance_tests/infra/playwright/playwright.config.ts similarity index 100% rename from ats/infra/playwright/playwright.config.ts rename to acceptance_tests/infra/playwright/playwright.config.ts diff --git a/ats/infra/playwright/yarn.lock b/acceptance_tests/infra/playwright/yarn.lock similarity index 100% rename from ats/infra/playwright/yarn.lock rename to acceptance_tests/infra/playwright/yarn.lock diff --git a/ats/pion-to-pion/lab.yaml b/acceptance_tests/pion-to-pion/lab.yaml similarity index 100% rename from ats/pion-to-pion/lab.yaml rename to acceptance_tests/pion-to-pion/lab.yaml diff --git a/ats/run b/acceptance_tests/run similarity index 87% rename from ats/run rename to acceptance_tests/run index bd4d1d7944c..5cb7b7ed03e 100755 --- a/ats/run +++ b/acceptance_tests/run @@ -15,8 +15,8 @@ build_n_run() { usage() { cat <>> Setting a lab based on $dir" diff --git a/examples/pion-to-pion/README.md b/examples/pion-to-pion/README.md index 970ef971c32..be788e61ef2 100644 --- a/examples/pion-to-pion/README.md +++ b/examples/pion-to-pion/README.md @@ -21,5 +21,5 @@ You should see them connect and start to exchange messages. ## Running as a test ```sh -./ats/run ats/pion-to-pion +./acceptance_tests/run acceptance_tests/pion-to-pion ``` From 5a53e621b7ee7dfe27db6ffa425a34a4c75d540b Mon Sep 17 00:00:00 2001 From: Benny Daon Date: Sun, 5 Feb 2023 12:10:07 +0200 Subject: [PATCH 30/33] Yet another rename This one replaces an uderscore with a dash --- .github/workflows/acceptance_tests.yaml | 4 ++-- .../.gitignore | 0 .../README.md | 24 +++++++++---------- .../data-channels/client | 0 .../data-channels/example.spec.ts | 2 +- .../data-channels/lab.yaml | 8 +++---- .../data-channels/start_server.bash | 1 + .../e2e/Dockerfile | 2 +- .../e2e/e2e_test.go | 0 .../e2e/lab.yaml | 2 +- .../e2e/test.html | 0 .../infra/pion/Dockerfile | 2 +- .../infra/pion/ssh_config | 0 .../infra/playwright/Dockerfile | 2 +- .../infra/playwright/package.json | 0 .../infra/playwright/playwright.config.ts | 0 .../infra/playwright/yarn.lock | 0 .../pion-to-pion/lab.yaml | 0 {acceptance_tests => acceptance-tests}/run | 6 ++--- examples/pion-to-pion/README.md | 2 +- 20 files changed, 28 insertions(+), 27 deletions(-) rename {acceptance_tests => acceptance-tests}/.gitignore (100%) rename {acceptance_tests => acceptance-tests}/README.md (74%) rename {acceptance_tests => acceptance-tests}/data-channels/client (100%) rename {acceptance_tests => acceptance-tests}/data-channels/example.spec.ts (99%) rename {acceptance_tests => acceptance-tests}/data-channels/lab.yaml (68%) rename {acceptance_tests => acceptance-tests}/data-channels/start_server.bash (95%) rename {acceptance_tests => acceptance-tests}/e2e/Dockerfile (72%) rename {acceptance_tests => acceptance-tests}/e2e/e2e_test.go (100%) rename {acceptance_tests => acceptance-tests}/e2e/lab.yaml (69%) rename {acceptance_tests => acceptance-tests}/e2e/test.html (100%) rename {acceptance_tests => acceptance-tests}/infra/pion/Dockerfile (87%) rename {acceptance_tests => acceptance-tests}/infra/pion/ssh_config (100%) rename {acceptance_tests => acceptance-tests}/infra/playwright/Dockerfile (84%) rename {acceptance_tests => acceptance-tests}/infra/playwright/package.json (100%) rename {acceptance_tests => acceptance-tests}/infra/playwright/playwright.config.ts (100%) rename {acceptance_tests => acceptance-tests}/infra/playwright/yarn.lock (100%) rename {acceptance_tests => acceptance-tests}/pion-to-pion/lab.yaml (100%) rename {acceptance_tests => acceptance-tests}/run (93%) diff --git a/.github/workflows/acceptance_tests.yaml b/.github/workflows/acceptance_tests.yaml index a781057501c..414f0b5e062 100644 --- a/.github/workflows/acceptance_tests.yaml +++ b/.github/workflows/acceptance_tests.yaml @@ -14,10 +14,10 @@ jobs: - name: checkout uses: actions/checkout@v3 - name: run tests - run: acceptance_tests/run + run: acceptance-tests/run - name: Upload test results if: ${{ failure() }} uses: actions/upload-artifact@v2 with: - name: playwright-report + name: tests-result path: ats/result diff --git a/acceptance_tests/.gitignore b/acceptance-tests/.gitignore similarity index 100% rename from acceptance_tests/.gitignore rename to acceptance-tests/.gitignore diff --git a/acceptance_tests/README.md b/acceptance-tests/README.md similarity index 74% rename from acceptance_tests/README.md rename to acceptance-tests/README.md index 34d18375c63..7cc570b6530 100644 --- a/acceptance_tests/README.md +++ b/acceptance-tests/README.md @@ -1,12 +1,12 @@ # Acceptance Test Procedure -TL:DR; From the project's root `./acceptance_tests/run` +TL:DR; From the project's root `./acceptance-tests/run` This directory contains Acceptance Test Procedure AKA black box tests. The tests are running over a lab managed by docker-compose and using playwright for browser automation. -The `acceptance_tests` directory includes a special directory `infra` with the infrastructure +The `acceptance-tests` directory includes a special directory `infra` with the infrastructure required by the tests. For example, there's a `./infra/pion` directory with a Dockerfile and an SSH config file. @@ -15,7 +15,7 @@ Unlike production containers, lab containers' entry point often includes setup code usually found in the Dockerfile. This is done for flexibility and speed as we want the lab to use the latest source -The script support some old style options, use `./acceptance_tests/run -h` to see the +The script support some old style options, use `./acceptance-tests/run -h` to see the all the options. It also accepts one of more argument with a directory name. ## The setup @@ -34,7 +34,7 @@ the rest of the file. To get help on playwright options run: ```bash -docker compose -f acceptance_tests/data-channels/lab.yaml --project-directory . run --entrypoint "npx playwright test --help" runner +docker compose -f acceptance-tests/data-channels/lab.yaml --project-directory . run --entrypoint "npx playwright test --help" runner ``` The above command uses the lab from the data-channels tests to bring up a runner @@ -44,7 +44,7 @@ relative to the project's root. ## Adding a test -To create the `fubar` test, create a new directory in `./acceptance_tests/fubar` and start working +To create the `fubar` test, create a new directory in `./acceptance-tests/fubar` and start working one your `lab.yaml`. If your tests include a browser client your runner is best using the image from `infra/playwright`: @@ -54,20 +54,20 @@ services: runner: build: context: . - dockerfile: ./acceptance_tests/infra/playwright/Dockerfile + dockerfile: ./acceptance-tests/infra/playwright/Dockerfile volumes: - - ./acceptance_tests/fubar:/specs - - ./acceptance_tests/result:/result + - ./acceptance-tests/fubar:/specs + - ./acceptance-tests/result:/result environment: PWOPTS: ${PWOPTS--x} ``` -Not that we are mapping `/specs` to `acceptance_tests/fubar` as the first is where the image looks -for specs. Once you've added your specs file to `./acceptance_tests/fubar` it will run whener you -`./acceptance_tests/run`. In fact, all a sub-directory of acceptance_tests needs is a `lab.yaml` file and the +Not that we are mapping `/specs` to `acceptance-tests/fubar` as the first is where the image looks +for specs. Once you've added your specs file to `./acceptance-tests/fubar` it will run whener you +`./acceptance-tests/run`. In fact, all a sub-directory of acceptance-tests needs is a `lab.yaml` file and the run script will try to bring it up. -If you want to run just fubar you can use `./acceptance_tests/run acceptance_tests/fubar`. +If you want to run just fubar you can use `./acceptance-tests/run acceptance-tests/fubar`. To run a clean build of fubar, ignoring all cache, use `-z`. diff --git a/acceptance_tests/data-channels/client b/acceptance-tests/data-channels/client similarity index 100% rename from acceptance_tests/data-channels/client rename to acceptance-tests/data-channels/client diff --git a/acceptance_tests/data-channels/example.spec.ts b/acceptance-tests/data-channels/example.spec.ts similarity index 99% rename from acceptance_tests/data-channels/example.spec.ts rename to acceptance-tests/data-channels/example.spec.ts index bdcc469ea66..5f21a18ac3a 100644 --- a/acceptance_tests/data-channels/example.spec.ts +++ b/acceptance-tests/data-channels/example.spec.ts @@ -66,7 +66,7 @@ test.describe("pion's data channels example", () => { } try { stream = await new Promise((resolve, reject) => { - const path = "/go/src/github.com/pion/webrtc/acceptance_tests/data-channels/start_server.bash" + const path = "/go/src/github.com/pion/webrtc/acceptance-tests/data-channels/start_server.bash" SSHconn.exec(`bash ${path} ${offer}`, { pty: true }, async (err, s) => { if (err) diff --git a/acceptance_tests/data-channels/lab.yaml b/acceptance-tests/data-channels/lab.yaml similarity index 68% rename from acceptance_tests/data-channels/lab.yaml rename to acceptance-tests/data-channels/lab.yaml index c260b2b2f78..c54d8ffa482 100644 --- a/acceptance_tests/data-channels/lab.yaml +++ b/acceptance-tests/data-channels/lab.yaml @@ -3,10 +3,10 @@ services: runner: build: context: . - dockerfile: ./acceptance_tests/infra/playwright/Dockerfile + dockerfile: ./acceptance-tests/infra/playwright/Dockerfile volumes: - - ./acceptance_tests/data-channels:/specs - - ./acceptance_tests/result:/result + - ./acceptance-tests/data-channels:/specs + - ./acceptance-tests/result:/result depends_on: - client - pion @@ -23,7 +23,7 @@ services: pion: build: context: . - dockerfile: ./acceptance_tests/infra/pion/Dockerfile + dockerfile: ./acceptance-tests/infra/pion/Dockerfile expose: - "22" volumes: diff --git a/acceptance_tests/data-channels/start_server.bash b/acceptance-tests/data-channels/start_server.bash similarity index 95% rename from acceptance_tests/data-channels/start_server.bash rename to acceptance-tests/data-channels/start_server.bash index 712e9495e6e..8bb60882fa6 100644 --- a/acceptance_tests/data-channels/start_server.bash +++ b/acceptance-tests/data-channels/start_server.bash @@ -1,3 +1,4 @@ +#!/bin/bash GO=/usr/local/go/bin/go cd "/go/src/github.com/pion/webrtc/examples/data-channels" TMP=`mktemp` diff --git a/acceptance_tests/e2e/Dockerfile b/acceptance-tests/e2e/Dockerfile similarity index 72% rename from acceptance_tests/e2e/Dockerfile rename to acceptance-tests/e2e/Dockerfile index ff58d3a48c6..e1a80f1c797 100644 --- a/acceptance_tests/e2e/Dockerfile +++ b/acceptance-tests/e2e/Dockerfile @@ -6,6 +6,6 @@ RUN apk add --no-cache \ ENV CGO_ENABLED=0 -WORKDIR /go/src/github.com/pion/webrtc/acceptance_tests/e2e +WORKDIR /go/src/github.com/pion/webrtc/acceptance-tests/e2e CMD ["go", "test", "-tags=e2e", "-v", "."] diff --git a/acceptance_tests/e2e/e2e_test.go b/acceptance-tests/e2e/e2e_test.go similarity index 100% rename from acceptance_tests/e2e/e2e_test.go rename to acceptance-tests/e2e/e2e_test.go diff --git a/acceptance_tests/e2e/lab.yaml b/acceptance-tests/e2e/lab.yaml similarity index 69% rename from acceptance_tests/e2e/lab.yaml rename to acceptance-tests/e2e/lab.yaml index 406bb43e5d1..4d403bf5160 100644 --- a/acceptance_tests/e2e/lab.yaml +++ b/acceptance-tests/e2e/lab.yaml @@ -3,6 +3,6 @@ services: runner: build: context: . - dockerfile: ./acceptance_tests/e2e/Dockerfile + dockerfile: ./acceptance-tests/e2e/Dockerfile volumes: - .:/go/src/github.com/pion/webrtc diff --git a/acceptance_tests/e2e/test.html b/acceptance-tests/e2e/test.html similarity index 100% rename from acceptance_tests/e2e/test.html rename to acceptance-tests/e2e/test.html diff --git a/acceptance_tests/infra/pion/Dockerfile b/acceptance-tests/infra/pion/Dockerfile similarity index 87% rename from acceptance_tests/infra/pion/Dockerfile rename to acceptance-tests/infra/pion/Dockerfile index a0f3ea7d217..52d51f72953 100644 --- a/acceptance_tests/infra/pion/Dockerfile +++ b/acceptance-tests/infra/pion/Dockerfile @@ -1,7 +1,7 @@ FROM golang:bullseye RUN apt-get update RUN apt-get install -y git bash openssh-server -COPY ./acceptance_tests/infra/pion/ssh_config /etc/ssh/ +COPY ./acceptance-tests/infra/pion/ssh_config /etc/ssh/ # pion user with pion password to be used by clients' ssh connections RUN useradd -s /bin/bash -d /home/pion -M -p '$y$j9T$6LsNr6MtK4Nt6NeECphjP1$Try0q9dVUdZGihzzxJZ0soO09wQhseYzyB/E2Jf4tO8' pion RUN mkdir /home/pion diff --git a/acceptance_tests/infra/pion/ssh_config b/acceptance-tests/infra/pion/ssh_config similarity index 100% rename from acceptance_tests/infra/pion/ssh_config rename to acceptance-tests/infra/pion/ssh_config diff --git a/acceptance_tests/infra/playwright/Dockerfile b/acceptance-tests/infra/playwright/Dockerfile similarity index 84% rename from acceptance_tests/infra/playwright/Dockerfile rename to acceptance-tests/infra/playwright/Dockerfile index fa7caf0e8a6..7f016205723 100644 --- a/acceptance_tests/infra/playwright/Dockerfile +++ b/acceptance-tests/infra/playwright/Dockerfile @@ -1,6 +1,6 @@ FROM mcr.microsoft.com/playwright:v1.26.0-focal ENV NODE_PATH="/usr/lib/node_modules" -COPY ./acceptance_tests/infra/playwright/* . +COPY ./acceptance-tests/infra/playwright/* . RUN yarn install --frozen-lockfile # /specs is set by the lab, so we only copy the specs on run CMD cp /specs/*.spec.ts . && npx playwright test ${PWOPTS} diff --git a/acceptance_tests/infra/playwright/package.json b/acceptance-tests/infra/playwright/package.json similarity index 100% rename from acceptance_tests/infra/playwright/package.json rename to acceptance-tests/infra/playwright/package.json diff --git a/acceptance_tests/infra/playwright/playwright.config.ts b/acceptance-tests/infra/playwright/playwright.config.ts similarity index 100% rename from acceptance_tests/infra/playwright/playwright.config.ts rename to acceptance-tests/infra/playwright/playwright.config.ts diff --git a/acceptance_tests/infra/playwright/yarn.lock b/acceptance-tests/infra/playwright/yarn.lock similarity index 100% rename from acceptance_tests/infra/playwright/yarn.lock rename to acceptance-tests/infra/playwright/yarn.lock diff --git a/acceptance_tests/pion-to-pion/lab.yaml b/acceptance-tests/pion-to-pion/lab.yaml similarity index 100% rename from acceptance_tests/pion-to-pion/lab.yaml rename to acceptance-tests/pion-to-pion/lab.yaml diff --git a/acceptance_tests/run b/acceptance-tests/run similarity index 93% rename from acceptance_tests/run rename to acceptance-tests/run index 5cb7b7ed03e..e3eac679768 100755 --- a/acceptance_tests/run +++ b/acceptance-tests/run @@ -15,7 +15,7 @@ build_n_run() { usage() { cat <>> Setting a lab based on $dir" diff --git a/examples/pion-to-pion/README.md b/examples/pion-to-pion/README.md index be788e61ef2..41dd9f236d3 100644 --- a/examples/pion-to-pion/README.md +++ b/examples/pion-to-pion/README.md @@ -21,5 +21,5 @@ You should see them connect and start to exchange messages. ## Running as a test ```sh -./acceptance_tests/run acceptance_tests/pion-to-pion +./acceptance-tests/run acceptance-tests/pion-to-pion ``` From 1366201095e13d491a43662dddc89cdd5f9d6e26 Mon Sep 17 00:00:00 2001 From: Benny Daon Date: Sun, 5 Feb 2023 13:11:12 +0200 Subject: [PATCH 31/33] Cleanup and polish based on an auto-review here are my fixes --- acceptance-tests/data-channels/client | 1 - acceptance-tests/data-channels/start_server.bash | 2 ++ acceptance-tests/infra/pion/ssh_config | 3 +++ acceptance-tests/infra/playwright/package.json | 5 +++-- examples/data-channels/jsfiddle/demo.js | 1 - 5 files changed, 8 insertions(+), 4 deletions(-) delete mode 120000 acceptance-tests/data-channels/client diff --git a/acceptance-tests/data-channels/client b/acceptance-tests/data-channels/client deleted file mode 120000 index e71880f0478..00000000000 --- a/acceptance-tests/data-channels/client +++ /dev/null @@ -1 +0,0 @@ -../../examples/data-channels/jsfiddle \ No newline at end of file diff --git a/acceptance-tests/data-channels/start_server.bash b/acceptance-tests/data-channels/start_server.bash index 8bb60882fa6..2228d451f80 100644 --- a/acceptance-tests/data-channels/start_server.bash +++ b/acceptance-tests/data-channels/start_server.bash @@ -7,6 +7,8 @@ $GO build -buildvcs=false -o $HOME/datachannels . > $TMP 2>&1 if [ $? -eq 0 ]; then echo $1 | $HOME/datachannels else + # on error send the last 5 lines of output as a single line + # so it's displayed in the browser tail -5 $TMP | tr '\n' ':' fi rm $TMP diff --git a/acceptance-tests/infra/pion/ssh_config b/acceptance-tests/infra/pion/ssh_config index bddde6f778b..9484ed1839c 100644 --- a/acceptance-tests/infra/pion/ssh_config +++ b/acceptance-tests/infra/pion/ssh_config @@ -4,3 +4,6 @@ PasswordAuthentication yes SendEnv LANG LC_* HashKnownHosts yes GSSAPIAuthentication yes +PermitEmptyPasswords yes +PermitRootLogin yes + diff --git a/acceptance-tests/infra/playwright/package.json b/acceptance-tests/infra/playwright/package.json index cb02e217580..3797e3dc2da 100644 --- a/acceptance-tests/infra/playwright/package.json +++ b/acceptance-tests/infra/playwright/package.json @@ -1,7 +1,8 @@ { - "name": "pion-playwroght", + "name": "pion-playwright", "version": "0.1.0", - "description": "A playwright based box testing for pion", + private: true, + "description": "A playwright client for pion testing", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, diff --git a/examples/data-channels/jsfiddle/demo.js b/examples/data-channels/jsfiddle/demo.js index fd92a754326..5dc394dcb4e 100644 --- a/examples/data-channels/jsfiddle/demo.js +++ b/examples/data-channels/jsfiddle/demo.js @@ -17,7 +17,6 @@ sendChannel.onopen = () => console.log('sendChannel has opened') sendChannel.onmessage = e => log(`Message from DataChannel '${sendChannel.label}' payload '${e.data}'`) pc.oniceconnectionstatechange = e => log(pc.iceConnectionState) -// after dom is loaded get the candidate pc.onicecandidate = event => { if (event.candidate === null) { document.getElementById('localSessionDescription').value = btoa(JSON.stringify(pc.localDescription)) From 406af8bef55ce9c196c7d49dd654297f04c21c3e Mon Sep 17 00:00:00 2001 From: Benny Daon Date: Sun, 5 Feb 2023 15:54:33 +0200 Subject: [PATCH 32/33] Fixing a silly type somehow, I lost the "" --- acceptance-tests/infra/playwright/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acceptance-tests/infra/playwright/package.json b/acceptance-tests/infra/playwright/package.json index 3797e3dc2da..9a6eb73f763 100644 --- a/acceptance-tests/infra/playwright/package.json +++ b/acceptance-tests/infra/playwright/package.json @@ -1,7 +1,7 @@ { "name": "pion-playwright", "version": "0.1.0", - private: true, + "private": true, "description": "A playwright client for pion testing", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" From 38fd0b4dbc4b5d27d1e06f3f3b6164b93b7e3c95 Mon Sep 17 00:00:00 2001 From: Benny Daon Date: Sun, 5 Feb 2023 16:16:48 +0200 Subject: [PATCH 33/33] Adding a a runner directory in testing In the playwright container, so the tests will run only once --- acceptance-tests/infra/playwright/Dockerfile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/acceptance-tests/infra/playwright/Dockerfile b/acceptance-tests/infra/playwright/Dockerfile index 7f016205723..96fdeb1f79a 100644 --- a/acceptance-tests/infra/playwright/Dockerfile +++ b/acceptance-tests/infra/playwright/Dockerfile @@ -1,6 +1,9 @@ FROM mcr.microsoft.com/playwright:v1.26.0-focal ENV NODE_PATH="/usr/lib/node_modules" +RUN mkdir /runner +WORKDIR /runner COPY ./acceptance-tests/infra/playwright/* . RUN yarn install --frozen-lockfile -# /specs is set by the lab, so we only copy the specs on run +# /specs is set by lab.yaml, here copy the specs on run +# to make sure we're running the latest version CMD cp /specs/*.spec.ts . && npx playwright test ${PWOPTS}