https://github.com/web-platform-tests/wpt
Raw File
Tip revision: dc95d6e03b834edb8aef5b1c9f63187625197117 authored by Dong-hee Na on 10 October 2018, 08:14:18 UTC
Convert blocks.dat to html5lib_blocks.html
Tip revision: dc95d6e
RTCIceTransport-extension.https.html
<!doctype html>
<meta charset=utf-8>
<title>RTCIceTransport-extensions.https.html</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="RTCIceTransport-extension-helper.js"></script>
<script>
'use strict';

// These tests are based on the following extension specification:
// https://w3c.github.io/webrtc-ice/

// The following helper functions are called from
// RTCIceTransport-extension-helper.js:
//   makeIceTransport
//   makeGatherAndStartTwoIceTransports

test(() => {
  const iceTransport = new RTCIceTransport();
}, 'RTCIceTransport constructor does not throw');

test(() => {
  const iceTransport = new RTCIceTransport();
  assert_equals(iceTransport.role, null, 'Expect role to be null');
  assert_equals(iceTransport.state, 'new', `Expect state to be 'new'`);
  assert_equals(iceTransport.gatheringState, 'new',
    `Expect gatheringState to be 'new'`);
  assert_array_equals(iceTransport.getLocalCandidates(), [],
    'Expect no local candidates');
  assert_array_equals(iceTransport.getRemoteCandidates(), [],
    'Expect no remote candidates');
  assert_equals(iceTransport.getSelectedCandidatePair(), null,
    'Expect no selected candidate pair');
  assert_not_equals(iceTransport.getLocalParameters(), null,
    'Expect local parameters generated');
  assert_equals(iceTransport.getRemoteParameters(), null,
    'Expect no remote parameters');
}, 'RTCIceTransport initial properties are set');

test(t => {
  const iceTransport = makeIceTransport(t);
  assert_throws(new TypeError(), () =>
    iceTransport.gather({ iceServers: null }));
}, 'gather() with { iceServers: null } should throw TypeError');

test(t => {
  const iceTransport = makeIceTransport(t);
  iceTransport.gather({ iceServers: undefined });
}, 'gather() with { iceServers: undefined } should succeed');

test(t => {
  const iceTransport = makeIceTransport(t);
  iceTransport.gather({ iceServers: [{
    urls: ['turns:turn.example.org', 'turn:turn.example.net'],
    username: 'user',
    credential: 'cred',
  }] });
}, 'gather() with one turns server, one turn server, username, credential' +
    ' should succeed');

test(t => {
  const iceTransport = makeIceTransport(t);
  iceTransport.gather({ iceServers: [{
    urls: ['stun:stun1.example.net', 'stun:stun2.example.net'],
  }] });
}, 'gather() with 2 stun servers should succeed');

test(t => {
  const iceTransport = makeIceTransport(t);
  iceTransport.stop();
  assert_throws('InvalidStateError', () => iceTransport.gather({}));
}, 'gather() throws if closed');

test(t => {
  const iceTransport = makeIceTransport(t);
  iceTransport.gather({});
  assert_equals(iceTransport.gatheringState, 'gathering');
}, `gather() transitions gatheringState to 'gathering'`);

test(t => {
  const iceTransport = makeIceTransport(t);
  iceTransport.gather({});
  assert_throws('InvalidStateError', () => iceTransport.gather({}));
}, 'gather() throws if called twice');

promise_test(async t => {
  const iceTransport = makeIceTransport(t);
  const watcher = new EventWatcher(t, iceTransport, 'gatheringstatechange');
  iceTransport.gather({});
  await watcher.wait_for('gatheringstatechange');
  assert_equals(iceTransport.gatheringState, 'complete');
}, `eventually transition gatheringState to 'complete'`);

promise_test(async t => {
  const iceTransport = makeIceTransport(t);
  const watcher = new EventWatcher(t, iceTransport,
      [ 'icecandidate', 'gatheringstatechange' ]);
  iceTransport.gather({});
  let candidate;
  do {
    ({ candidate } = await watcher.wait_for('icecandidate'));
  } while (candidate !== null);
  assert_equals(iceTransport.gatheringState, 'gathering');
  await watcher.wait_for('gatheringstatechange');
  assert_equals(iceTransport.gatheringState, 'complete');
}, 'onicecandidate fires with null candidate before gatheringState' +
    ` transitions to 'complete'`);

promise_test(async t => {
  const iceTransport = makeIceTransport(t);
  const watcher = new EventWatcher(t, iceTransport, 'icecandidate');
  iceTransport.gather({});
  const { candidate } = await watcher.wait_for('icecandidate');
  assert_not_equals(candidate.candidate, '');
  assert_array_equals(iceTransport.getLocalCandidates(), [candidate]);
}, 'gather() returns at least one host candidate');

promise_test(async t => {
  const iceTransport = makeIceTransport(t);
  const watcher = new EventWatcher(t, iceTransport, 'icecandidate');
  iceTransport.gather({ gatherPolicy: 'relay' });
  const { candidate } = await watcher.wait_for('icecandidate');
  assert_equals(candidate, null);
  assert_array_equals(iceTransport.getLocalCandidates(), []);
}, `gather() returns no candidates with { gatherPolicy: 'relay'} and no turn` +
    ' servers');

const dummyRemoteParameters = {
  usernameFragment: 'dummyUsernameFragment',
  password: 'dummyPassword',
};

test(() => {
  const iceTransport = new RTCIceTransport();
  iceTransport.stop();
  assert_throws('InvalidStateError',
    () => iceTransport.start(dummyRemoteParameters));
  assert_equals(iceTransport.getRemoteParameters(), null);
}, `start() throws if closed`);

test(() => {
  const iceTransport = new RTCIceTransport();
  assert_throws(new TypeError(), () => iceTransport.start({}));
  assert_throws(new TypeError(),
    () => iceTransport.start({ usernameFragment: 'dummy' }));
  assert_throws(new TypeError(),
    () => iceTransport.start({ password: 'dummy' }));
  assert_equals(iceTransport.getRemoteParameters(), null);
}, 'start() throws if usernameFragment or password not set');

const assert_ice_parameters_equals = (a, b) => {
  assert_equals(a.usernameFragment, b.usernameFragment,
      'usernameFragments are equal');
  assert_equals(a.password, b.password, 'passwords are equal');
};

test(t => {
  const iceTransport = makeIceTransport(t);
  iceTransport.start(dummyRemoteParameters);
  assert_equals(iceTransport.state, 'new');
  assert_ice_parameters_equals(iceTransport.getRemoteParameters(),
      dummyRemoteParameters);
}, `start() does not transition state to 'checking' if no remote candidates ` +
    'added');

test(t => {
  const iceTransport = makeIceTransport(t);
  iceTransport.start(dummyRemoteParameters);
  assert_equals(iceTransport.role, 'controlled');
}, `start() with default role sets role attribute to 'controlled'`);

test(t => {
  const iceTransport = makeIceTransport(t);
  iceTransport.start(dummyRemoteParameters, 'controlling');
  assert_equals(iceTransport.role, 'controlling');
}, `start() sets role attribute to 'controlling'`);

const candidate1 = new RTCIceCandidate({
  candidate: 'candidate:1 1 udp 2113929471 203.0.113.100 10100 typ host',
});

test(() => {
  const iceTransport = new RTCIceTransport();
  iceTransport.stop();
  assert_throws('InvalidStateError',
    () => iceTransport.addRemoteCandidate(candidate1));
  assert_array_equals(iceTransport.getRemoteCandidates(), []);
}, 'addRemoteCandidate() throws if closed');

test(() => {
  const iceTransport = new RTCIceTransport();
  assert_throws('OperationError',
    () => iceTransport.addRemoteCandidate(
      new RTCIceCandidate({ candidate: 'invalid' })));
  assert_array_equals(iceTransport.getRemoteCandidates(), []);
}, 'addRemoteCandidate() throws on invalid candidate');

test(t => {
  const iceTransport = makeIceTransport(t);
  iceTransport.addRemoteCandidate(candidate1);
  iceTransport.start(dummyRemoteParameters);
  assert_equals(iceTransport.state, 'checking');
  assert_array_equals(iceTransport.getRemoteCandidates(), [candidate1]);
}, `start() transitions state to 'checking' if one remote candidate had been ` +
    'added');

test(t => {
  const iceTransport = makeIceTransport(t);
  iceTransport.start(dummyRemoteParameters);
  iceTransport.addRemoteCandidate(candidate1);
  assert_equals(iceTransport.state, 'checking');
  assert_array_equals(iceTransport.getRemoteCandidates(), [candidate1]);
}, `addRemoteCandidate() transitions state to 'checking' if start() had been ` +
    'called before');

test(t => {
  const iceTransport = makeIceTransport(t);
  iceTransport.start(dummyRemoteParameters);
  assert_throws('InvalidStateError',
    () => iceTransport.start(dummyRemoteParameters, 'controlling'));
}, 'start() throws if later called with a different role');

test(t => {
  const iceTransport = makeIceTransport(t);
  iceTransport.start({
    usernameFragment: 'user',
    password: 'pass',
  });
  iceTransport.addRemoteCandidate(candidate1);
  const changedRemoteParameters = {
    usernameFragment: 'user2',
    password: 'pass',
  };
  iceTransport.start(changedRemoteParameters);
  assert_equals(iceTransport.state, 'new');
  assert_array_equals(iceTransport.getRemoteCandidates(), []);
  assert_ice_parameters_equals(iceTransport.getRemoteParameters(),
      changedRemoteParameters);
}, `start() flushes remote candidates and transitions state to 'new' if ` +
   'later called with different remote parameters');

promise_test(async t => {
  const [ localTransport, remoteTransport ] =
      makeGatherAndStartTwoIceTransports(t);
  const localWatcher = new EventWatcher(t, localTransport, 'statechange');
  const remoteWatcher = new EventWatcher(t, remoteTransport, 'statechange');
  await Promise.all([
    localWatcher.wait_for('statechange').then(() => {
      assert_equals(localTransport.state, 'connected');
    }),
    remoteWatcher.wait_for('statechange').then(() => {
      assert_equals(remoteTransport.state, 'connected');
    }),
  ]);
}, 'Two RTCIceTransports connect to each other');

promise_test(async t => {
  async function waitForConnectedThenSelectedCandidatePairChange(t, transport,
      transportName) {
    const watcher = new EventWatcher(t, transport,
        [ 'statechange', 'selectedcandidatepairchange' ]);
    await watcher.wait_for('statechange');
    assert_equals(transport.state, 'connected',
        `${transportName} state should be 'connected'`);
    await watcher.wait_for('selectedcandidatepairchange');
    const selectedCandidatePair = transport.getSelectedCandidatePair();
    assert_not_equals(selectedCandidatePair, null,
        `${transportName} selected candidate pair should not be null once ` +
        'the selectedcandidatepairchange event fires');
    assert_true(
        transport.getLocalCandidates().some(
            ({ candidate }) =>
                candidate === selectedCandidatePair.local.candidate),
        `${transportName} selected candidate pair local should be in the ` +
        'list of local candidates');
    assert_true(
        transport.getRemoteCandidates().some(
            ({ candidate }) =>
                candidate === selectedCandidatePair.remote.candidate),
        `${transportName} selected candidate pair local should be in the ` +
        'list of remote candidates');
  }
  const [ localTransport, remoteTransport ] =
      makeGatherAndStartTwoIceTransports(t);
  await Promise.all([
    waitForConnectedThenSelectedCandidatePairChange(t, localTransport,
        'local transport'),
    waitForConnectedThenSelectedCandidatePairChange(t, remoteTransport,
        'remote transport'),
  ]);
}, 'Selected candidate pair changes once the RTCIceTransports connect.');

promise_test(async t => {
  const [ transport, ] = makeGatherAndStartTwoIceTransports(t);
  const watcher = new EventWatcher(t, transport, 'selectedcandidatepairchange');
  await watcher.wait_for('selectedcandidatepairchange');
  transport.stop();
  assert_equals(transport.getSelectedCandidatePair(), null);
}, 'getSelectedCandidatePair() returns null once the RTCIceTransport is ' +
    'stopped.');

</script>
back to top