Search in sources :

Example 11 with UserAgent

use of nl.basjes.parse.useragent.UserAgent in project yauaa by nielsbasjes.

the class AbstractUserAgentAnalyzerTester method runTests.

public static boolean runTests(AbstractUserAgentAnalyzerDirect analyzer, boolean showAll, boolean failOnUnexpected, Collection<String> onlyValidateFieldNames, boolean measureSpeed, boolean showPassedTests, StringBuilder errorMessageReceiver) {
    analyzer.initializeMatchers();
    if (analyzer.getTestCases() == null) {
        return true;
    }
    DebugUserAgent agent = new DebugUserAgent(analyzer.getWantedFieldNames());
    List<TestResult> results = new ArrayList<>(32);
    String filenameHeader = "Test number and source";
    int filenameHeaderLength = filenameHeader.length();
    int maxFilenameLength = filenameHeaderLength;
    for (TestCase test : analyzer.getTestCases()) {
        Map<String, String> metaData = test.getMetadata();
        String filename = metaData.get("filename");
        maxFilenameLength = Math.max(maxFilenameLength, filename.length());
    }
    maxFilenameLength += 11;
    StringBuilder sb = new StringBuilder(1024);
    sb.append("| ").append(filenameHeader);
    for (int i = filenameHeaderLength; i < maxFilenameLength; i++) {
        sb.append(' ');
    }
    sb.append(" |S|AA|MF|");
    if (measureSpeed) {
        sb.append("  PPS| msPP|");
    }
    sb.append("--> S=Syntax Error, AA=Number of ambiguities during parse, MF=Matches Found");
    if (measureSpeed) {
        sb.append(", PPS=parses/sec, msPP=milliseconds per parse");
    }
    long fullStart = System.nanoTime();
    if (showPassedTests) {
        LOG.info("+===========================================================================================");
        LOG.info("%s", sb);
        LOG.info("+-------------------------------------------------------------------------------------------");
    }
    boolean allPass = true;
    int testcount = 0;
    for (TestCase test : analyzer.getTestCases()) {
        testcount++;
        String testName = test.getTestName();
        String userAgentString = test.getUserAgent();
        Map<String, String> expected = test.getExpected();
        List<String> options = test.getOptions();
        Map<String, String> metaData = test.getMetadata();
        String filename = metaData.get("filename");
        String linenumber = metaData.get("fileline");
        boolean init = false;
        if (options == null) {
            analyzer.setVerbose(false);
            agent.setDebug(false);
        } else {
            boolean newVerbose = options.contains("verbose");
            analyzer.setVerbose(newVerbose);
            agent.setDebug(newVerbose);
            init = options.contains("init");
        }
        if (expected == null || expected.size() == 0) {
            init = true;
            expected = null;
        }
        if (testName == null) {
            if (userAgentString.length() > 200) {
                testName = userAgentString.substring(0, 190) + " ... ( " + userAgentString.length() + " chars)";
            } else {
                testName = userAgentString;
            }
        }
        sb.setLength(0);
        sb.append("|").append(String.format("%5d", testcount)).append(".(").append(filename).append(':').append(linenumber).append(')');
        for (int i = filename.length() + linenumber.length() + 7; i < maxFilenameLength; i++) {
            sb.append(' ');
        }
        agent.setUserAgentString(userAgentString);
        UserAgent parseResult = null;
        long measuredSpeed = -1;
        if (measureSpeed) {
            // Preheat
            for (int i = 0; i < 100; i++) {
                analyzer.parse(agent);
            }
            long startTime = System.nanoTime();
            for (int i = 0; i < 1000; i++) {
                parseResult = analyzer.parse(agent);
            }
            long stopTime = System.nanoTime();
            measuredSpeed = (1000000000L * (1000)) / (stopTime - startTime);
        } else {
            parseResult = analyzer.parse(agent);
        }
        sb.append('|');
        if (parseResult.hasSyntaxError()) {
            sb.append('S');
        } else {
            sb.append(' ');
        }
        if (parseResult.hasAmbiguity()) {
            sb.append(String.format("|%2d", parseResult.getAmbiguityCount()));
        } else {
            sb.append("|  ");
        }
        sb.append(String.format("|%2d", agent.getNumberOfAppliedMatches()));
        if (measureSpeed) {
            sb.append('|').append(String.format("%5d", measuredSpeed));
            sb.append('|').append(String.format("%5.2f", 1000.0 / measuredSpeed));
        }
        sb.append("| ").append(testName);
        // We create the log line but we keep it until we know it actually must be output to the screen
        String testLogLine = sb.toString();
        sb.setLength(0);
        boolean pass = true;
        results.clear();
        if (init) {
            LOG.info(testLogLine);
            sb.append(agent.toYamlTestCase());
            LOG.info("%s", sb);
        }
        // "Field".length()+1;            NOSONAR: This is not commented code.
        int maxNameLength = 6;
        // "Actual".length()+1;           NOSONAR: This is not commented code.
        int maxActualLength = 7;
        // "Expected".length()+1;         NOSONAR: This is not commented code.
        int maxExpectedLength = 9;
        if (expected != null) {
            List<String> fieldNames = new ArrayList<>(parseResult.getAvailableFieldNamesSorted());
            if (onlyValidateFieldNames != null && onlyValidateFieldNames.isEmpty()) {
                onlyValidateFieldNames = null;
            } else if (onlyValidateFieldNames != null) {
                fieldNames.clear();
                fieldNames.addAll(onlyValidateFieldNames);
            }
            for (String newFieldName : expected.keySet()) {
                if (!fieldNames.contains(newFieldName)) {
                    fieldNames.add(newFieldName);
                }
            }
            for (String fieldName : fieldNames) {
                // Only check the desired fieldnames
                if (onlyValidateFieldNames != null && !onlyValidateFieldNames.contains(fieldName)) {
                    continue;
                }
                TestResult result = new TestResult();
                result.field = fieldName;
                boolean expectedSomething;
                // Actual value
                result.actual = parseResult.getValue(result.field);
                result.isDefault = parseResult.get(result.field).isDefaultValue();
                result.confidence = parseResult.getConfidence(result.field);
                if (result.actual == null) {
                    result.actual = NULL_VALUE;
                }
                // Expected value
                String expectedValue = expected.get(fieldName);
                if (expectedValue == null) {
                    expectedSomething = false;
                    if (result.isDefault) {
                        continue;
                    }
                    result.expected = "<<absent>>";
                } else {
                    expectedSomething = true;
                    result.expected = expectedValue;
                }
                result.pass = result.actual.equals(result.expected);
                if (!result.pass) {
                    result.warn = true;
                    if (expectedSomething) {
                        result.warn = false;
                        pass = false;
                        allPass = false;
                    } else {
                        if (failOnUnexpected) {
                            // We ignore this special field
                            if (!SYNTAX_ERROR.equals(result.field)) {
                                result.warn = false;
                                pass = false;
                                allPass = false;
                            }
                        }
                    }
                }
                results.add(result);
                maxNameLength = Math.max(maxNameLength, result.field.length());
                maxActualLength = Math.max(maxActualLength, result.actual.length());
                maxExpectedLength = Math.max(maxExpectedLength, result.expected.length());
            }
            if (!agent.analyzeMatchersResult()) {
                pass = false;
                allPass = false;
            }
        }
        if (!init && pass && !showAll) {
            if (showPassedTests) {
                logInfo(errorMessageReceiver, testLogLine);
            }
            continue;
        }
        if (!pass) {
            logInfo(errorMessageReceiver, testLogLine);
            logError(errorMessageReceiver, "| TEST FAILED !");
        }
        if (parseResult.hasAmbiguity()) {
            logInfo(errorMessageReceiver, "| Parsing problem: Ambiguity {} times. ", parseResult.getAmbiguityCount());
        }
        if (parseResult.hasSyntaxError()) {
            logInfo(errorMessageReceiver, "| Parsing problem: Syntax Error");
        }
        if (init || !pass) {
            sb.setLength(0);
            sb.append('\n');
            sb.append('\n');
            sb.append("- matcher:\n");
            sb.append("#    options:\n");
            sb.append("#    - 'verbose'\n");
            sb.append("    require:\n");
            for (String path : getAllPaths(userAgentString)) {
                if (path.contains("=\"")) {
                    sb.append("#    - '").append(path).append("'\n");
                }
            }
            sb.append("    extract:\n");
            sb.append("#    - 'DeviceClass                         :      1 :' \n");
            sb.append("#    - 'DeviceBrand                         :      1 :' \n");
            sb.append("#    - 'DeviceName                          :      1 :' \n");
            sb.append("#    - 'OperatingSystemClass                :      1 :' \n");
            sb.append("#    - 'OperatingSystemName                 :      1 :' \n");
            sb.append("#    - 'OperatingSystemVersion              :      1 :' \n");
            sb.append("#    - 'LayoutEngineClass                   :      1 :' \n");
            sb.append("#    - 'LayoutEngineName                    :      1 :' \n");
            sb.append("#    - 'LayoutEngineVersion                 :      1 :' \n");
            sb.append("#    - 'AgentClass                          :      1 :' \n");
            sb.append("#    - 'AgentName                           :      1 :' \n");
            sb.append("#    - 'AgentVersion                        :      1 :' \n");
            sb.append('\n');
            sb.append('\n');
            LOG.info("%s", sb);
        }
        sb.setLength(0);
        sb.append("+--------+-");
        for (int i = 0; i < maxNameLength; i++) {
            sb.append('-');
        }
        sb.append("-+-");
        for (int i = 0; i < maxActualLength; i++) {
            sb.append('-');
        }
        sb.append("-+---------+------------+-");
        for (int i = 0; i < maxExpectedLength; i++) {
            sb.append('-');
        }
        sb.append("-+");
        String separator = sb.toString();
        logInfo(errorMessageReceiver, separator);
        sb.setLength(0);
        sb.append("| Result | Field ");
        for (int i = 6; i < maxNameLength; i++) {
            sb.append(' ');
        }
        sb.append(" | Actual ");
        for (int i = 7; i < maxActualLength; i++) {
            sb.append(' ');
        }
        sb.append(" | Default | Confidence | Expected ");
        for (int i = 9; i < maxExpectedLength; i++) {
            sb.append(' ');
        }
        sb.append(" |");
        logInfo(errorMessageReceiver, sb.toString());
        logInfo(errorMessageReceiver, separator);
        Map<String, String> failComments = new HashMap<>();
        List<String> failedFieldNames = new ArrayList<>();
        for (TestResult result : results) {
            sb.setLength(0);
            if (result.pass) {
                sb.append("|        | ");
            } else {
                if (result.warn) {
                    sb.append("| ~warn~ | ");
                    failComments.put(result.field, "~~ Unexpected result ~~");
                } else {
                    sb.append("| -FAIL- | ");
                    failComments.put(result.field, "FAILED; Should be '" + result.expected + "'");
                    failedFieldNames.add(result.field);
                }
            }
            sb.append(result.field);
            for (int i = result.field.length(); i < maxNameLength; i++) {
                sb.append(' ');
            }
            sb.append(" | ");
            sb.append(result.actual);
            for (int i = result.actual.length(); i < maxActualLength; i++) {
                sb.append(' ');
            }
            if (result.isDefault) {
                sb.append(" | Default | ");
            } else {
                sb.append(" |         | ");
            }
            sb.append(String.format("%10d", result.confidence));
            sb.append(" | ");
            if (result.pass) {
                for (int i = 0; i < maxExpectedLength; i++) {
                    sb.append(' ');
                }
                sb.append(" |");
                logInfo(errorMessageReceiver, sb.toString());
            } else {
                sb.append(result.expected);
                for (int i = result.expected.length(); i < maxExpectedLength; i++) {
                    sb.append(' ');
                }
                sb.append(" |");
                if (result.warn) {
                    logWarn(errorMessageReceiver, sb.toString());
                } else {
                    logError(errorMessageReceiver, sb.toString());
                }
            }
        }
        logInfo(errorMessageReceiver, separator);
        logInfo(errorMessageReceiver, "");
        logInfo(errorMessageReceiver, agent.toMatchTrace(failedFieldNames));
        logInfo(errorMessageReceiver, "\n\nconfig:\n{}", parseResult.toYamlTestCase(!init, failComments));
        logInfo(errorMessageReceiver, "Location of failed test.({}:{})", filename, linenumber);
        if (!pass && !showAll) {
            return false;
        }
        if (init) {
            return allPass;
        }
    }
    if (showPassedTests) {
        LOG.info("+===========================================================================================");
    } else {
        LOG.info("All %d tests passed", testcount);
    }
    long fullStop = System.nanoTime();
    LOG.info("This took %8.3f ms for %5d tests : averaging to %6.3f msec/test (This includes test validation and logging!!)", (fullStop - fullStart) / 1000000.0, testcount, ((double) (fullStop - fullStart)) / (testcount * 1000000L));
    if (testcount == 0) {
        LOG.error("NO tests were run at all!!!");
        allPass = false;
    }
    return allPass;
}
Also used : HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) TestCase(nl.basjes.parse.useragent.config.TestCase) UserAgent(nl.basjes.parse.useragent.UserAgent) MutableUserAgent(nl.basjes.parse.useragent.UserAgent.MutableUserAgent)

Example 12 with UserAgent

use of nl.basjes.parse.useragent.UserAgent in project yauaa by nielsbasjes.

the class DebugUserAgent method analyzeMatchersResult.

boolean analyzeMatchersResult() {
    boolean passed = true;
    for (String fieldName : getAvailableFieldNamesSorted()) {
        Map<Long, String> receivedValues = new HashMap<>(32);
        for (Pair<UserAgent, Matcher> pair : appliedMatcherResults) {
            UserAgent result = pair.getLeft();
            AgentField partialField = result.get(fieldName);
            if (partialField != null && partialField.getConfidence() >= 0) {
                String previousValue = receivedValues.get(partialField.getConfidence());
                if (previousValue != null) {
                    if (!previousValue.equals(partialField.getValue())) {
                        if (passed) {
                            LOG.error("***********************************************************");
                            LOG.error("***        REALLY IMPORTANT ERRORS IN THE RULESET       ***");
                            LOG.error("*** YOU MUST CHANGE THE CONFIDENCE LEVELS OF YOUR RULES ***");
                            LOG.error("***********************************************************");
                        }
                        passed = false;
                        LOG.error("Found different value for \"{}\" with SAME confidence {}: \"{}\" and \"{}\"", fieldName, partialField.getConfidence(), previousValue, partialField.getValue());
                    }
                } else {
                    receivedValues.put(partialField.getConfidence(), partialField.getValue());
                }
            }
        }
    }
    return passed;
}
Also used : HashMap(java.util.HashMap) Matcher(nl.basjes.parse.useragent.analyze.Matcher) AgentField(nl.basjes.parse.useragent.AgentField) UserAgent(nl.basjes.parse.useragent.UserAgent) MutableUserAgent(nl.basjes.parse.useragent.UserAgent.MutableUserAgent)

Example 13 with UserAgent

use of nl.basjes.parse.useragent.UserAgent in project NBlog by Naccl.

the class UserAgentUtils method parseOsAndBrowser.

/**
 * 从User-Agent解析客户端操作系统和浏览器版本
 *
 * @param userAgent
 * @return
 */
public Map<String, String> parseOsAndBrowser(String userAgent) {
    UserAgent agent = uaa.parse(userAgent);
    String os = agent.getValue(UserAgent.OPERATING_SYSTEM_NAME_VERSION_MAJOR);
    String browser = agent.getValue(UserAgent.AGENT_NAME_VERSION);
    Map<String, String> map = new HashMap<>();
    map.put("os", os);
    map.put("browser", browser);
    return map;
}
Also used : HashMap(java.util.HashMap) UserAgent(nl.basjes.parse.useragent.UserAgent)

Example 14 with UserAgent

use of nl.basjes.parse.useragent.UserAgent in project yauaa by nielsbasjes.

the class AbstractSerializationTest method testParser.

private void testParser(Demo demo) {
    String userAgent = "Mozilla/5.0 (Linux; Android 7.0; Nexus 6 Build/NBD90Z) " + "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.124 Mobile Safari/537.36";
    UserAgent result = demo.parse(userAgent);
    LOG.info("Result = \n{}", result);
    assertTrue(result.toXML().contains("<DeviceName>Google Nexus 6</DeviceName>"), "The parser must extract the correct DeviceName");
}
Also used : UserAgent(nl.basjes.parse.useragent.UserAgent)

Example 15 with UserAgent

use of nl.basjes.parse.useragent.UserAgent in project yauaa by nielsbasjes.

the class TestDemo method testParser.

@Test
void testParser() {
    Demo demo = new Demo();
    String userAgent = "Mozilla/5.0 (Linux; Android 7.0; Nexus 6 Build/NBD90Z) " + "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.124 Mobile Safari/537.36";
    UserAgent result = demo.parse(userAgent);
    assertTrue(result.toXML().contains("<DeviceName>Google Nexus 6</DeviceName>"), "The parser must extract the correct DeviceName");
}
Also used : Demo(nl.example.Demo) UserAgent(nl.basjes.parse.useragent.UserAgent) Test(org.junit.jupiter.api.Test)

Aggregations

UserAgent (nl.basjes.parse.useragent.UserAgent)30 UserAgentAnalyzer (nl.basjes.parse.useragent.UserAgentAnalyzer)11 Test (org.junit.jupiter.api.Test)9 ArrayList (java.util.ArrayList)6 HashMap (java.util.HashMap)4 MissingUserAgentException (nl.basjes.parse.useragent.servlet.exceptions.MissingUserAgentException)4 MutableUserAgent (nl.basjes.parse.useragent.UserAgent.MutableUserAgent)3 AgentField (nl.basjes.parse.useragent.AgentField)2 Matcher (nl.basjes.parse.useragent.analyze.Matcher)2 Event (co.elastic.logstash.api.Event)1 BlockBuilder (io.trino.spi.block.BlockBuilder)1 Description (io.trino.spi.function.Description)1 ScalarFunction (io.trino.spi.function.ScalarFunction)1 SqlType (io.trino.spi.function.SqlType)1 MapType (io.trino.spi.type.MapType)1 TypeOperators (io.trino.spi.type.TypeOperators)1 UnsupportedEncodingException (java.io.UnsupportedEncodingException)1 Map (java.util.Map)1 TreeSet (java.util.TreeSet)1 ParsedField (nl.basjes.parse.core.ParsedField)1