io.nosqlbench.driver.webdriver.WebDriverActivity Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of driver-web Show documentation
Show all versions of driver-web Show documentation
A nosqlbench driver module;
Provides the ability to drive steps through the webdriver API.
The newest version!
package io.nosqlbench.driver.webdriver;
/*
* Copyright (c) 2022 nosqlbench
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import io.nosqlbench.driver.webdriver.side.Command;
import io.nosqlbench.driver.webdriver.side.SideConfig;
import io.nosqlbench.driver.webdriver.side.Test;
import io.nosqlbench.engine.api.activityapi.planning.OpSequence;
import io.nosqlbench.engine.api.activityapi.planning.SequencePlanner;
import io.nosqlbench.engine.api.activityapi.planning.SequencerType;
import io.nosqlbench.engine.api.activityconfig.StatementsLoader;
import io.nosqlbench.engine.api.activityconfig.yaml.OpTemplate;
import io.nosqlbench.engine.api.activityconfig.yaml.StmtsDocList;
import io.nosqlbench.engine.api.activityimpl.ActivityDef;
import io.nosqlbench.engine.api.activityimpl.SimpleActivity;
import io.nosqlbench.engine.api.templating.CommandTemplate;
import io.nosqlbench.engine.api.templating.StrInterpolator;
import io.nosqlbench.nb.api.content.NBIO;
import io.nosqlbench.nb.api.errors.BasicError;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
public class WebDriverActivity extends SimpleActivity {
private final static Logger logger = LogManager.getLogger(WebDriverActivity.class);
// private final StmtsDocList stmtsDocList;
private OpSequence opSequence;
private final ConcurrentHashMap contexts = new ConcurrentHashMap<>();
// private static ThreadLocal TL_WebContext = new ThreadLocal<>();
public WebDriverActivity(ActivityDef activityDef) {
super(activityDef);
}
@Override
public void initActivity() {
super.initActivity();
this.opSequence = initOpSequence();
onActivityDefUpdate(activityDef);
setDefaultsFromOpSequence(opSequence);
int threads = getActivityDef().getThreads();
logger.info("pre-initializing web browsers");
for (int i = 0; i < threads; i++) {
getWebContext(i);
}
}
private OpSequence initOpSequence() {
OpSequence sequence;
String yaml_loc = getParams().getOptionalString("yaml","workload").orElse(null);
String side_loc = getParams().getOptionalString("side").orElse(null);
if (yaml_loc == null && side_loc == null) {
throw new BasicError("You must provide yaml= or side=, but neither was found");
}
if (yaml_loc != null && side_loc != null) {
throw new BasicError("You must provide either yaml= or side=, but not both.");
}
if (yaml_loc != null) {
sequence=initOpSequenceFromYaml();
} else {
sequence=initOpSequenceFromSide();
}
if (sequence.getSequence().length==0) {
logger.warn("The sequence contains zero operations.");
}
return sequence;
}
private OpSequence initOpSequenceFromSide() {
Optional sideFile = activityDef.getParams().getOptionalString("side");
String sideToImport = sideFile.get();
String side = NBIO.all().name(sideToImport).extension("side").one().asString();
Gson gson = new GsonBuilder().setPrettyPrinting().create();
SideConfig sc = gson.fromJson(side, SideConfig.class);
String sideName = sc.getName();
String sideUrl = sc.getUrl();
LinkedHashMap commands = new LinkedHashMap<>();
for (Test test : sc.getTests()) {
int idx=0;
StringBuilder testBuilder = new StringBuilder();
for (Command command : test.getCommands()) {
StringBuilder cmdBuilder = new StringBuilder();
String cmd = command.getCommand();
cmdBuilder.append(cmd);
if (command.getCommand().equals("open")) {
cmdBuilder.append(" url='").append(sideUrl.replaceAll("'","\\\\'")).append("'");
}
if (command.getTarget() != null && !command.getTarget().isEmpty()) {
String tg=null;
if (command.getTargets().size()>0) {
for (int i = 0; i < command.getTargets().size(); i++) {
List strings = command.getTargets().get(i);
if (strings.get(1).equals("xpath:idRelative")) {
logger.debug("favoring xpath form of selector:" + strings.get(0));
tg=strings.get(0);
}
}
}
if (tg==null) {
tg = command.getTarget();
}
cmdBuilder.append(" target='").append(tg.replaceAll("'","\\\\'")).append("'");
}
if (command.getValue() != null && !command.getValue().isEmpty()) {
cmdBuilder.append(" value='").append(command.getValue().replaceAll("'","\\\\'")).append("'");
}
cmdBuilder.append("\n");
logger.debug("build cmd: '" + testBuilder + "'");
String cmdName = sideName+"_"+String.format("%s_%03d", sideName, ++idx);
commands.put(cmdName,cmdBuilder.toString());
}
}
String export = activityDef.getParams().getOptionalString("export").orElse(null);
if (export!=null) {
Path exportTo = Path.of(export);
if (Files.exists(exportTo)) {
throw new BasicError("File exists: " + exportTo + ", remove it first.");
}
try {
StringBuilder stmts = new StringBuilder();
stmts.append("statements:\n");
commands.forEach((name, cmd)-> {
System.out.println("name: " + name);
System.out.println("cmd: " + cmd);
stmts.append(" - ").append(name).append(": ").append(cmd);
});
Files.writeString(exportTo,stmts.toString());
} catch (IOException e) {
throw new RuntimeException(e);
}
logger.info("completed importing from " + sideFile + " to " + exportTo);
System.exit(0);
}
SequencerType sequencerType = getParams()
.getOptionalString("seq")
.map(SequencerType::valueOf)
.orElse(SequencerType.bucket);
SequencePlanner planner = new SequencePlanner<>(sequencerType);
commands.forEach((name,cmd) -> {
CommandTemplate commandTemplate = new CommandTemplate(name, cmd, Map.of(), Map.of(),List.of());
planner.addOp(commandTemplate,(c) -> 1L);
});
OpSequence sequence = planner.resolve();
return sequence;
}
private OpSequence initOpSequenceFromYaml() {
StrInterpolator interp = new StrInterpolator(activityDef);
String yaml_loc = activityDef.getParams().getOptionalString("yaml", "workload").orElse("default");
StmtsDocList stmtsDocList = StatementsLoader.loadPath(logger, yaml_loc, activityDef.getParams(), "activities");
SequencerType sequencerType = getParams()
.getOptionalString("seq")
.map(SequencerType::valueOf)
.orElse(SequencerType.bucket);
SequencePlanner planner = new SequencePlanner<>(sequencerType);
String tagfilter = activityDef.getParams().getOptionalString("tags").orElse("");
List stmts = stmtsDocList.getStmts(tagfilter);
if (stmts.size() == 0) {
throw new BasicError("There were no active statements with tag filter '" + tagfilter + "'");
}
for (OpTemplate optpl : stmts) {
long ratio = optpl.getParamOrDefault("ratio", 1);
CommandTemplate cmd = new CommandTemplate(optpl);
planner.addOp(cmd, ratio);
}
return planner.resolve();
}
public OpSequence getOpSequence() {
return opSequence;
}
public synchronized WebContext getWebContext(int slot) {
try {
WebContext context = contexts.get(slot);
if (context == null) {
logger.info("initializing chromedriver for thread " + slot);
System.setProperty("webdriver.http.factory", "okhttp");
ChromeOptions chromeOptions = new ChromeOptions();
chromeOptions.setHeadless(activityDef.getParams().getOptionalBoolean("headless").orElse(false));
WebDriver webdriver = new ChromeDriver(chromeOptions);
context = new WebContext(webdriver);
contexts.put(slot, context);
} else {
logger.info("using cached chromedriver for thread " + slot);
}
return context;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@Override
public void shutdownActivity() {
contexts.forEach((s, d) -> {
logger.debug("closing driver for thread " + s);
d.driver().close();
});
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy