Skip to content

Commit

Permalink
feat: Adds option to open multiple tabs in a single driver/window.
Browse files Browse the repository at this point in the history
  • Loading branch information
damencho committed Nov 4, 2022
1 parent 401223b commit fa98e34
Show file tree
Hide file tree
Showing 5 changed files with 184 additions and 58 deletions.
8 changes: 7 additions & 1 deletion scripts/malleus.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ if [ -n "$DEBUG" ]; then
fi

usage() {
echo "Usage: $0 [--conferences=MALLEUS_CONFERENCES] [--participants=MALLEUS_PARTICIPANTS] [--senders=MALLEUS_SENDERS] [--audio-senders=MALLEUS_AUDIO_SENDERS] [--senders-per-tab=MALLEUS_SENDERS_PER_NODE] [--receivers-per-tab=MALLEUS_RECEIVERS_PER_NODE] [--senders-per-node=MALLEUS_SENDERS_PER_NODE] [--receivers-per-node=MALLEUS_RECEIVERS_PER_NODE] [--duration=MALLEUS_DURATION (s)] [--join-delay=MALLEUS_JOIN_DELAY (ms)] [--room-name-prefix=MALLEUS_ROOM_NAME_PREFIX] [--hub-url=MALLEUS_HUB_URL] [--instance-url=MALLEUS_INSTANCE_URL] [--regions=MALLEUS_REGIONS] [--use-node-types] [--use-load-test] [--use-lite-mode] [--max-disrupted-bridges-pct=MALLEUS_MAX_DISRUPTED_BRIDGES_PCT] [--extra-sender-params=EXTRA_SENDER_PARAMS] [--extra-receiver-params=EXTRA_RECEIVER_PARAMS] [--debug] [--switch-speakers] [--use-stage-view] [--headless]" >&2
echo "Usage: $0 [--conferences=MALLEUS_CONFERENCES] [--participants=MALLEUS_PARTICIPANTS] [--senders=MALLEUS_SENDERS] [--audio-senders=MALLEUS_AUDIO_SENDERS] [--senders-per-tab=MALLEUS_SENDERS_PER_NODE] [--receivers-per-tab=MALLEUS_RECEIVERS_PER_NODE] [--tabs-per-node=MALLEUS_TABS_PER_NODE] [--senders-per-node=MALLEUS_SENDERS_PER_NODE] [--receivers-per-node=MALLEUS_RECEIVERS_PER_NODE] [--duration=MALLEUS_DURATION (s)] [--join-delay=MALLEUS_JOIN_DELAY (ms)] [--room-name-prefix=MALLEUS_ROOM_NAME_PREFIX] [--hub-url=MALLEUS_HUB_URL] [--instance-url=MALLEUS_INSTANCE_URL] [--regions=MALLEUS_REGIONS] [--use-node-types] [--use-load-test] [--use-lite-mode] [--max-disrupted-bridges-pct=MALLEUS_MAX_DISRUPTED_BRIDGES_PCT] [--extra-sender-params=EXTRA_SENDER_PARAMS] [--extra-receiver-params=EXTRA_RECEIVER_PARAMS] [--debug] [--switch-speakers] [--use-stage-view] [--headless]" >&2
exit 1
}

Expand Down Expand Up @@ -46,6 +46,10 @@ set_defaults() {
MALLEUS_RECEIVERS_PER_NODE=1
fi

if [ -z "$MALLEUS_TABS_PER_NODE" ]; then
MALLEUS_TABS_PER_NODE=1
fi

if [ -z "$MALLEUS_DURATION" ]; then
MALLEUS_DURATION=60
fi
Expand Down Expand Up @@ -113,6 +117,7 @@ case $1 in
--receivers-per-tab) MALLEUS_RECEIVERS_PER_TAB=$optvalue;;
--senders-per-node) MALLEUS_SENDERS_PER_NODE=$optvalue; MALLEUS_USE_NODE_TYPES=true;;
--receivers-per-node) MALLEUS_RECEIVERS_PER_NODE=$optvalue; MALLEUS_USE_NODE_TYPES=true;;
--tabs-per-node) MALLEUS_TABS_PER_NODE=$optvalue; MALLEUS_TABS_PER_NODE=$optvalue;;
--duration) MALLEUS_DURATION=$optvalue;;
--join-delay) MALLEUS_JOIN_DELAY=$optvalue;;
--room-name-prefix) MALLEUS_ROOM_NAME_PREFIX=$optvalue;;
Expand Down Expand Up @@ -203,6 +208,7 @@ mvn \
-Dorg.jitsi.malleus.use_node_types=$MALLEUS_USE_NODE_TYPES \
-Dorg.jitsi.malleus.senders_per_tab=$MALLEUS_SENDERS_PER_TAB \
-Dorg.jitsi.malleus.receivers_per_tab=$MALLEUS_RECEIVERS_PER_TAB \
-Dorg.jitsi.malleus.tabs_per_node=$MALLEUS_TABS_PER_NODE \
-Dorg.jitsi.meet.test.util.blip_script=$MALLEUS_BLIP_SCRIPT \
-Dorg.jitsi.malleus.use_load_test=$MALLEUS_USE_LOAD_TEST \
-Dorg.jitsi.malleus.use_lite_mode=$MALLEUS_USE_LITE_MODE \
Expand Down
195 changes: 140 additions & 55 deletions src/test/java/org/jitsi/meet/test/MalleusJitsificus.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import org.jitsi.meet.test.base.*;
import org.jitsi.meet.test.util.*;
import org.jitsi.meet.test.web.*;
import org.openqa.selenium.*;
import org.testng.*;
import org.testng.annotations.*;

Expand Down Expand Up @@ -73,6 +74,7 @@ public class MalleusJitsificus
= "org.jitsi.malleus.senders_per_tab";
public static final String RECEIVERS_PER_TAB
= "org.jitsi.malleus.receivers_per_tab";
public static final String TABS_PER_NODE = "org.jitsi.malleus.tabs_per_node";
public static final String EXTRA_SENDER_PARAMS
= "org.jitsi.malleus.extra_sender_params";
public static final String EXTRA_RECEIVER_PARAMS
Expand Down Expand Up @@ -121,6 +123,10 @@ public Object[][] createData(ITestContext context)
? 1
: Integer.parseInt(receiversPerTabStr);

// cannot be used with switch speakers or disturb bridges
String tabsPerNodeStr = System.getProperty(TABS_PER_NODE);
int tabsPerNode = tabsPerNodeStr == null ? 1: Integer.parseInt(tabsPerNodeStr);

int durationMs = 1000 * Integer.parseInt(System.getProperty(DURATION_PNAME));

int joinDelayMs = Integer.parseInt(System.getProperty(JOIN_DELAY_PNAME));
Expand Down Expand Up @@ -207,7 +213,8 @@ public Object[][] createData(ITestContext context)
switchSpeakers,
sendersPerTab, receiversPerTab,
extraSenderParams, extraReceiverParams,
useLiteMode
useLiteMode,
tabsPerNode
};
}

Expand All @@ -221,7 +228,8 @@ public void testMain(
String[] regions, float blipMaxDisruptedPct, boolean switchSpeakers,
int sendersPerTab, int receiversPerTab,
String extraSenderParams, String extraReceiverParams,
boolean useLiteMode)
boolean useLiteMode,
int numberOfTabsPerNode)
throws Exception
{
List<MalleusTask> malleusTasks = new ArrayList<>(numberOfParticipants);
Expand Down Expand Up @@ -259,7 +267,7 @@ public void testMain(
else
{
urlCopy.appendConfig(extraReceiverParams);
numClients = receiversPerTab;
numClients = receiversPerTab*numberOfTabsPerNode;

if (useLiteMode)
{
Expand Down Expand Up @@ -287,7 +295,8 @@ public void testMain(
switchSpeakers || !audioSender /* no audio */,
regions == null ? null : regions[i % regions.length],
numClients,
disruptBridges
disruptBridges,
numberOfTabsPerNode
);
malleusTasks.add(task);
task.start(pool);
Expand Down Expand Up @@ -377,23 +386,32 @@ private class MalleusTask
private Future<?> complete;
private ScheduledFuture<?> checking;

WebParticipant participant;
List<WebParticipant> taskParticipants = new ArrayList<>();

private String bridge;

private int numberOfTabs;
private int numClients;

private long clientInterval;

private ScheduledExecutorService pool;

public MalleusTask(
int i, JitsiMeetUrl url, long durationMs, long joinDelayMs, long totalJoinDelayMs,
boolean muteVideo, boolean muteAudio, String region, int numClients,
boolean enableFailureDetection)
boolean enableFailureDetection, int numberOfTabs)
{
this.i = i;
this._url = url;
this.durationMs = durationMs;
this.clientInterval = joinDelayMs;
this.joinDelayMs = totalJoinDelayMs;
this.muteVideo = muteVideo;
this.muteAudio = muteAudio;
this.enableFailureDetection = enableFailureDetection;
this.numberOfTabs = numberOfTabs;
this.numClients = numClients;

if (muteVideo)
{
Expand All @@ -405,7 +423,6 @@ public MalleusTask(
}
if (numClients != 1)
{
_url.appendConfig("numClients=" + numClients);
_url.appendConfig("clientInterval=" + joinDelayMs);
}

Expand Down Expand Up @@ -456,11 +473,45 @@ private void join()
}
}

participant = participants.createParticipant("web.participant" + (i + 1), ops);
allHungUp.register();
try
{
participant.joinConference(_url);

int clientPerTab = numClients/numberOfTabs;
int rem = numClients%numberOfTabs;

for(int i = 0; i < numberOfTabs; i++)
{
int currentClients = clientPerTab;
if (rem > 0)
{
currentClients += rem;
rem = 0;
}
int participantCount = (this.i + 1) + (i * clientPerTab);
WebParticipant participant = participants.createParticipant(
"web.participant" + participantCount, ops);
WebDriver driver = participant.getDriver();

// to re-use the same driver/chrome instance
ops.setDriver(driver);

JitsiMeetUrl u = _url.copy().appendConfig("numClients=" + currentClients);
participant.joinConference(u);

// let's create new tab and switch to it, so we prepare for the next execution
// skips the last one
if (i < numberOfTabs - 1)
{
// wait, give time for thos in the tab to join
TestUtils.waitMillis(currentClients * this.clientInterval);
((JavascriptExecutor) driver).executeScript("window.open()");
ArrayList<String> tabs = new ArrayList<>(driver.getWindowHandles());
driver.switchTo().window(tabs.get(i + 1));
}
// the index should be also the tab index
taskParticipants.add(participant);
}
allHungUp.register();
}
catch (Exception e)
{
Expand All @@ -476,8 +527,16 @@ private void join()
{
if (enableFailureDetection)
{
bridge = participant.getBridgeIp();
bridgeSelection.add(bridge);
for(int i =0; i < taskParticipants.size(); i++)
{
WebParticipant participant = taskParticipants.get(i);
WebDriver driver = participant.getDriver();
ArrayList<String> tabs = new ArrayList<> (driver.getWindowHandles());
driver.switchTo().window(tabs.get(i));

bridge = participant.getBridgeIp();
bridgeSelection.add(bridge);
}
}
}
catch (Exception e)
Expand Down Expand Up @@ -507,28 +566,38 @@ private void finish()
checking.cancel(true);
}

try
{
participant.hangUp();
}
catch (Exception e)
{
TestUtils.print("Exception hanging up " + participant.getName());
e.printStackTrace();
}
try
{
/* There seems to be a Selenium or chrome webdriver bug where closing one parallel
* Chrome session can cause another one to close too. So wait for all sessions
* to hang up before we close any of them.
*/
allHungUp.arriveAndAwaitAdvance();
MalleusJitsificus.this.closeParticipant(participant);
}
catch (Exception e)
// we need to start closing from the last one
for(int i = taskParticipants.size() - 1; i >= 0; i--)
{
TestUtils.print("Exception closing " + participant.getName());
e.printStackTrace();
WebParticipant participant = taskParticipants.get(i);
WebDriver driver = participant.getDriver();
ArrayList<String> tabs = new ArrayList<> (driver.getWindowHandles());
driver.switchTo().window(tabs.get(i));

try
{

participant.hangUp();
}
catch (Exception e)
{
TestUtils.print("Exception hanging up " + participant.getName());
e.printStackTrace();
}
try
{
/* There seems to be a Selenium or chrome webdriver bug where closing one parallel
* Chrome session can cause another one to close too. So wait for all sessions
* to hang up before we close any of them.
*/
allHungUp.arriveAndAwaitAdvance();
MalleusJitsificus.this.closeParticipant(participant);
}
catch (Exception e)
{
TestUtils.print("Exception closing " + participant.getName());
e.printStackTrace();
}
}
}

Expand All @@ -540,22 +609,30 @@ public void waitUntilComplete() throws ExecutionException, InterruptedException

private void check()
{
try
for(int i =0; i < taskParticipants.size(); i++)
{
participant.waitForIceConnected(0 /* no timeout */);
}
catch (Exception ex)
{
TestUtils.print("Participant " + i + " is NOT connected.");
if (!bridgesToFail.contains(bridge))
WebParticipant participant = taskParticipants.get(i);
WebDriver driver = participant.getDriver();
ArrayList<String> tabs = new ArrayList<>(driver.getWindowHandles());
driver.switchTo().window(tabs.get(i));

try
{
throw ex;
participant.waitForIceConnected(0 /* no timeout */);
}
else
catch (Exception ex)
{
// wait for reconnect
participant.waitForIceConnected(20);
TestUtils.print("Participant " + i + " reconnected.");
TestUtils.print("Participant " + i + " is NOT connected.");
if (!bridgesToFail.contains(bridge))
{
throw ex;
}
else
{
// wait for reconnect
participant.waitForIceConnected(20);
TestUtils.print("Participant " + i + " reconnected.");
}
}
}
}
Expand All @@ -567,18 +644,26 @@ public void muteAudio(boolean mute)

private void doMuteAudio(boolean mute)
{
if (mute != muteAudio)
for(int i =0; i < taskParticipants.size(); i++)
{
participant.muteAudio(mute);
muteAudio = mute;
if (mute)
{
TestUtils.print("Muted participant " + i);
}
else
WebParticipant participant = taskParticipants.get(i);
WebDriver driver = participant.getDriver();
ArrayList<String> tabs = new ArrayList<>(driver.getWindowHandles());
driver.switchTo().window(tabs.get(i));

if (mute != muteAudio)
{
TestUtils.print("Unmuted participant " + i);
spoken = true;
participant.muteAudio(mute);
muteAudio = mute;
if (mute)
{
TestUtils.print("Muted participant " + i);
}
else
{
TestUtils.print("Unmuted participant " + i);
spoken = true;
}
}
}
}
Expand Down
11 changes: 10 additions & 1 deletion src/test/java/org/jitsi/meet/test/base/Participant.java
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,16 @@ public void close()

cancelKeepAlive();

driver.quit();
ArrayList<String> tabs = new ArrayList<> (driver.getWindowHandles());
if (tabs.size() > 1)
{
driver.close();
driver.switchTo().window(tabs.get(tabs.size() - 2));
}
else
{
driver.quit();
}

// FIXME missing comment on why this is necessary ? (if it really is...)
TestUtils.waitMillis(500);
Expand Down
Loading

0 comments on commit fa98e34

Please sign in to comment.