Skip to content

Commit

Permalink
CLDR-17287 API performance test for the back end
Browse files Browse the repository at this point in the history
- refactor VoteAPIHelper to be callable from unit tests outside of a web server
- improve error results from ST
  • Loading branch information
srl295 committed Dec 14, 2023
1 parent 92e53d8 commit ff320de
Show file tree
Hide file tree
Showing 7 changed files with 179 additions and 46 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ public enum ErrorCode {
E_BAD_VALUE,
E_BAD_XPATH,
E_NO_OLD_VOTES,
E_PERMANENT_VOTE_NO_FORUM;
E_PERMANENT_VOTE_NO_FORUM,
E_VOTE_NOT_ACCEPTED;
}

private final ErrorCode err_code;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package org.unicode.cldr.web.api;

import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;

import org.eclipse.microprofile.openapi.annotations.media.Schema;
import org.unicode.cldr.web.SurveyException;
import org.unicode.cldr.web.SurveyException.ErrorCode;
Expand Down Expand Up @@ -64,7 +66,27 @@ public void setMessage(String message) {
* @return
*/
public Response build() {
return Response.serverError().entity(this).build();
return Response.status(getStatus()).entity(this).build();
}

/** the error as a Status */
public Status getStatus() {
switch(code) {
case E_BAD_LOCALE:
case E_BAD_SECTION:
case E_BAD_XPATH:
return Response.Status.NOT_FOUND;
case E_NO_PERMISSION:
return Response.Status.FORBIDDEN;
case E_BAD_VALUE:
case E_VOTE_NOT_ACCEPTED:
return Response.Status.NOT_ACCEPTABLE;
case E_SESSION_DISCONNECTED:
case E_NOT_LOGGED_IN:
return Response.Status.UNAUTHORIZED;
default:
return Response.Status.INTERNAL_SERVER_ERROR;
}
}

public static Response surveyNotQuiteReady() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -372,18 +372,33 @@ private static Dashboard.ReviewNotification[] getOnePathDash(
// separated from
// the HTTP response concerns, so that VoteAPI and XPathAlt can share code without the
// awkwardness of forbiddenIsOk.
static Response handleVote(
public static Response handleVote(
String loc,
String xp,
String value,
int voteLevelChanged,
final CookieSession mySession,
boolean forbiddenIsOk) {
// translate this call into jax-rs Response
try {
final VoteResponse r = getHandleVoteResponse(loc, xp, value, voteLevelChanged, mySession, forbiddenIsOk);
return Response.ok(r).build();
} catch (Throwable se) {
return new STError(se).build();
}
}
/** this function is the implementation of handleVote() but does not use any jax-rs, for unit tests */
public static VoteResponse getHandleVoteResponse(String loc,
String xp,
String value,
int voteLevelChanged,
final CookieSession mySession,
boolean forbiddenIsOk) throws SurveyException {
VoteResponse r = new VoteResponse();
mySession.userDidAction();
CLDRLocale locale = CLDRLocale.getInstance(loc);
if (!UserRegistry.userCanModifyLocale(mySession.user, locale)) {
return Response.status(Status.FORBIDDEN).build();
throw new SurveyException(ErrorCode.E_NO_PERMISSION, "Not allowed to modify " + locale);
}
loc = locale.getBaseName(); // sanitized
final SurveyMain sm = CookieSession.sm;
Expand Down Expand Up @@ -445,15 +460,13 @@ static Response handleVote(
}
} catch (Throwable t) {
SurveyLog.logException(logger, t, "Processing submission " + locale + ":" + xp);
return (new STError(t).build());
throw new SurveyException(ErrorCode.E_INTERNAL, "Processing submission " + locale + ":" + xp);
}
}
if (!forbiddenIsOk && r.statusAction.isForbidden()) {
return Response.status(Response.Status.NOT_ACCEPTABLE)
.entity(new STError("Status action is forbidden: " + r.statusAction))
.build();
throw new SurveyException(ErrorCode.E_VOTE_NOT_ACCEPTED, "Status action is forbidden: " + r.statusAction);
}
return Response.ok(r).build();
return r;
}

private static void normalizedToZeroLengthError(VoteResponse r, List<CheckStatus> result) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,13 @@
import java.util.Date;
import java.util.Map;
import java.util.TreeMap;

import javax.ws.rs.core.Response;

import org.unicode.cldr.draft.FileUtilities;
import org.unicode.cldr.test.CheckCLDR;
import org.unicode.cldr.unittest.web.TestAll.WebTestInfo;
import org.unicode.cldr.util.CLDRConfig;
import org.unicode.cldr.util.CLDRFile;
import org.unicode.cldr.util.CLDRFile.DraftStatus;
import org.unicode.cldr.util.CLDRLocale;
Expand All @@ -28,6 +33,7 @@
import org.unicode.cldr.web.BallotBox;
import org.unicode.cldr.web.BallotBox.InvalidXPathException;
import org.unicode.cldr.web.BallotBox.VoteNotAcceptedException;
import org.unicode.cldr.web.SurveyMain.Phase;
import org.unicode.cldr.web.CookieSession;
import org.unicode.cldr.web.DBUtils;
import org.unicode.cldr.web.STFactory;
Expand All @@ -36,6 +42,8 @@
import org.unicode.cldr.web.UserRegistry;
import org.unicode.cldr.web.UserRegistry.LogoutException;
import org.unicode.cldr.web.UserRegistry.User;
import org.unicode.cldr.web.api.VoteAPI;
import org.unicode.cldr.web.api.VoteAPIHelper;
import org.unicode.cldr.web.XPathTable;

public class TestSTFactory extends TestFmwk {
Expand Down Expand Up @@ -453,6 +461,8 @@ public void TestVettingDataDriven() throws SQLException, IOException {

public void TestVotePerf() throws SQLException, IOException {
if (TestAll.skipIfNoDb()) return;
final CheckCLDR.Phase p = CLDRConfig.getInstance().getPhase();
assertTrue("phase " + p + ".isUnitTest()", p.isUnitTest());
runDataDrivenTest("TestVotePerf"); // TestSTFactory.xml
}

Expand Down Expand Up @@ -550,6 +560,36 @@ public void handlePathValue(String path, String value) {
+ xpath);
}
break;
case "apivote":
case "apiunvote":
{
UserRegistry.User u = getUserFromAttrs(attrs, "name");
CLDRLocale locale = CLDRLocale.getInstance(attrs.get("locale"));
boolean needException =
getBooleanAttr(attrs, "exception", false);
if (elem.equals("apiunvote")) {
value = null;
}
final CookieSession mySession = CookieSession.newSession(u, "999.999.999.999");
try {
final VoteAPI.VoteResponse r = VoteAPIHelper.getHandleVoteResponse(locale.getBaseName(), xpath, value, 0, mySession, false);
final boolean isOk = r.didVote;
final boolean asExpected = (isOk == !needException);
if (!asExpected) {
errln("exception=" + needException + " but got status " + r.didNotSubmit + " - " + r.toString());
} else {
logln(" status = " + r.didNotSubmit);
}
} catch(Throwable iae) {
if (needException == true) {
logln("Caught expected: " + iae);
} else {
iae.printStackTrace();
errln("Unexpected exception: " + iae);
}
}
}
break;
case "vote":
case "unvote":
{
Expand Down Expand Up @@ -592,6 +632,7 @@ public void handlePathValue(String path, String value) {
logln(u + " " + elem + "d for " + xpath + " = " + value);
}
break;
case "apiverify": // TODO
case "verify":
{
value = value.trim();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
Except as contained in this notice, the name of a copyright holder shall not be used in advertising or otherwise to promote the sale, use or other dealings in these Data Files or Software without prior written authorization of the copyright holder.
-->

<!ELEMENT TestSTFactory ((user | vote | unvote | verify | echo | warn | setvar | verifyUser)*) >
<!ELEMENT TestSTFactory ((user | vote | unvote | verify | echo | warn | setvar | verifyUser | apivote | apiunvote | apiverify)*) >
<!-- <!ATTLIST TestSTFactory version CDATA #REQUIRED> -->

<!ELEMENT user EMPTY >
Expand All @@ -23,6 +23,20 @@ Except as contained in this notice, the name of a copyright holder shall not be
<!ATTLIST vote name NMTOKEN #REQUIRED>
<!ATTLIST vote exception ( true | false ) #IMPLIED>

<!-- vote with API -->
<!ELEMENT apivote (#PCDATA) >
<!ATTLIST apivote locale CDATA #REQUIRED>
<!ATTLIST apivote xpath CDATA #REQUIRED>
<!ATTLIST apivote name NMTOKEN #REQUIRED>
<!ATTLIST apivote exception ( true | false ) #IMPLIED>

<!-- unvote with API -->
<!ELEMENT apiunvote EMPTY >
<!ATTLIST apiunvote locale CDATA #REQUIRED>
<!ATTLIST apiunvote xpath CDATA #REQUIRED>
<!ATTLIST apiunvote name NMTOKEN #REQUIRED>
<!ATTLIST apiunvote exception ( true | false ) #IMPLIED>

<!ELEMENT unvote EMPTY >
<!ATTLIST unvote locale CDATA #REQUIRED>
<!ATTLIST unvote xpath CDATA #REQUIRED>
Expand All @@ -35,6 +49,13 @@ Except as contained in this notice, the name of a copyright holder shall not be
<!ATTLIST verify orgStatus CDATA #IMPLIED>
<!ATTLIST verify statusOrg CDATA #IMPLIED>

<!-- verify but with API -->
<!ELEMENT apiverify (#PCDATA) >
<!ATTLIST apiverify locale CDATA #REQUIRED>
<!ATTLIST apiverify xpath CDATA #REQUIRED>
<!ATTLIST apiverify status NMTOKEN #REQUIRED>
<!ATTLIST apiverify name NMTOKEN #REQUIRED>

<!ELEMENT setvar EMPTY >
<!ATTLIST setvar locale CDATA #REQUIRED>
<!ATTLIST setvar xpath CDATA #REQUIRED>
Expand Down
Loading

0 comments on commit ff320de

Please sign in to comment.