LCOV - code coverage report
Current view: top level - svl/qa/unit - test_URIHelper.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 75 127 59.1 %
Date: 2014-11-03 Functions: 21 29 72.4 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <cassert>
      21             : #include <cstddef>
      22             : 
      23             : #include <com/sun/star/lang/Locale.hpp>
      24             : #include <com/sun/star/lang/XComponent.hpp>
      25             : #include <com/sun/star/lang/XMultiServiceFactory.hpp>
      26             : #include <com/sun/star/ucb/Command.hpp>
      27             : #include <com/sun/star/ucb/CommandAbortedException.hpp>
      28             : #include <com/sun/star/ucb/IllegalIdentifierException.hpp>
      29             : #include <com/sun/star/ucb/UniversalContentBroker.hpp>
      30             : #include <com/sun/star/ucb/XCommandProcessor.hpp>
      31             : #include <com/sun/star/ucb/XContent.hpp>
      32             : #include <com/sun/star/ucb/XContentIdentifier.hpp>
      33             : #include <com/sun/star/ucb/XContentProvider.hpp>
      34             : #include <com/sun/star/uno/Any.hxx>
      35             : #include <com/sun/star/uno/Exception.hpp>
      36             : #include <com/sun/star/uno/Reference.hxx>
      37             : #include <com/sun/star/uno/RuntimeException.hpp>
      38             : #include <com/sun/star/uno/XComponentContext.hpp>
      39             : #include <com/sun/star/uri/XUriReference.hpp>
      40             : #include <cppuhelper/bootstrap.hxx>
      41             : #include <cppuhelper/implbase1.hxx>
      42             : #include <cppuhelper/implbase2.hxx>
      43             : #include "cppunit/TestCase.h"
      44             : #include "cppunit/TestFixture.h"
      45             : #include "cppunit/TestSuite.h"
      46             : #include "cppunit/extensions/HelperMacros.h"
      47             : #include "cppunit/plugin/TestPlugIn.h"
      48             : #include <rtl/strbuf.hxx>
      49             : #include <rtl/string.h>
      50             : #include <rtl/string.hxx>
      51             : #include <rtl/textenc.h>
      52             : #include <rtl/ustring.h>
      53             : #include <rtl/ustring.hxx>
      54             : #include <sal/macros.h>
      55             : #include <sal/types.h>
      56             : #include <svl/urihelper.hxx>
      57             : #include <unotools/charclass.hxx>
      58             : 
      59             : namespace com { namespace sun { namespace star { namespace ucb {
      60             :     class XCommandEnvironment;
      61             :     class XContentEventListener;
      62             : } } } }
      63             : 
      64             : namespace {
      65             : 
      66             : // This class only implements that subset of functionality of a proper
      67             : // css::ucb::Content that is known to be needed here:
      68          64 : class Content:
      69             :     public cppu::WeakImplHelper2<
      70             :         css::ucb::XContent, css::ucb::XCommandProcessor >
      71             : {
      72             : public:
      73             :     explicit Content(
      74             :         css::uno::Reference< css::ucb::XContentIdentifier > const & identifier);
      75             : 
      76             :     virtual css::uno::Reference< css::ucb::XContentIdentifier > SAL_CALL
      77           0 :     getIdentifier() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE {
      78           0 :         return m_identifier;
      79             :     }
      80             : 
      81           0 :     virtual OUString SAL_CALL getContentType()
      82             :         throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
      83             :     {
      84           0 :         return OUString();
      85             :     }
      86             : 
      87           0 :     virtual void SAL_CALL addContentEventListener(
      88             :         css::uno::Reference< css::ucb::XContentEventListener > const &)
      89             :         throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
      90           0 :     {}
      91             : 
      92           0 :     virtual void SAL_CALL removeContentEventListener(
      93             :         css::uno::Reference< css::ucb::XContentEventListener > const &)
      94             :         throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
      95           0 :     {}
      96             : 
      97           0 :     virtual sal_Int32 SAL_CALL createCommandIdentifier()
      98             :         throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
      99             :     {
     100           0 :         return 0;
     101             :     }
     102             : 
     103             :     virtual css::uno::Any SAL_CALL execute(
     104             :         css::ucb::Command const & command, sal_Int32 commandId,
     105             :         css::uno::Reference< css::ucb::XCommandEnvironment > const &)
     106             :         throw (
     107             :             css::uno::Exception, css::ucb::CommandAbortedException,
     108             :             css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
     109             : 
     110           0 :     virtual void SAL_CALL abort(sal_Int32) throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE {}
     111             : 
     112             : private:
     113             :     static char const m_prefix[];
     114             : 
     115             :     css::uno::Reference< css::ucb::XContentIdentifier > m_identifier;
     116             : };
     117             : 
     118             : char const Content::m_prefix[] = "test:";
     119             : 
     120          32 : Content::Content(
     121             :     css::uno::Reference< css::ucb::XContentIdentifier > const & identifier):
     122          32 :     m_identifier(identifier)
     123             : {
     124             :     assert(m_identifier.is());
     125          32 :     OUString uri(m_identifier->getContentIdentifier());
     126          64 :     if (!uri.matchIgnoreAsciiCase(m_prefix)
     127          32 :         || uri.indexOf('#', RTL_CONSTASCII_LENGTH(m_prefix)) != -1)
     128             :     {
     129           0 :         throw css::ucb::IllegalIdentifierException();
     130          32 :     }
     131          32 : }
     132             : 
     133          32 : css::uno::Any Content::execute(
     134             :     css::ucb::Command const & command, sal_Int32,
     135             :     css::uno::Reference< css::ucb::XCommandEnvironment > const &)
     136             :     throw (
     137             :         css::uno::Exception, css::ucb::CommandAbortedException,
     138             :         css::uno::RuntimeException, std::exception)
     139             : {
     140          32 :     if ( command.Name != "getCasePreservingURL" )
     141             :     {
     142           0 :         throw css::uno::RuntimeException();
     143             :     }
     144             :     // If any non-empty segment starts with anything but '0', '1', or '2', fail;
     145             :     // otherwise, if the last non-empty segment starts with '1', add a final
     146             :     // slash, and if the last non-empty segment starts with '2', remove a final
     147             :     // slash (if any); also, turn the given uri into all-lowercase:
     148          32 :     OUString uri(m_identifier->getContentIdentifier());
     149          32 :     sal_Unicode c = '0';
     150         144 :     for (sal_Int32 i = RTL_CONSTASCII_LENGTH(m_prefix); i != -1;) {
     151          96 :         OUString seg(uri.getToken(0, '/', i));
     152          96 :         if (seg.getLength() > 0) {
     153          60 :             c = seg[0];
     154          60 :             if (c < '0' || c > '2') {
     155          16 :                 throw css::uno::Exception();
     156             :             }
     157             :         }
     158          96 :     }
     159          16 :     switch (c) {
     160             :     case '1':
     161           4 :         uri += "/";
     162           4 :         break;
     163             :     case '2':
     164           4 :         if (uri.endsWith("/")) {
     165           2 :             uri = uri.copy(0, uri.getLength() -1);
     166             :         }
     167           4 :         break;
     168             :     }
     169          16 :     return css::uno::makeAny(uri.toAsciiLowerCase());
     170             : }
     171             : 
     172           6 : class Provider: public cppu::WeakImplHelper1< css::ucb::XContentProvider > {
     173             : public:
     174          32 :     virtual css::uno::Reference< css::ucb::XContent > SAL_CALL queryContent(
     175             :         css::uno::Reference< css::ucb::XContentIdentifier > const & identifier)
     176             :         throw (css::ucb::IllegalIdentifierException, css::uno::RuntimeException, std::exception) SAL_OVERRIDE
     177             :     {
     178          32 :         return new Content(identifier);
     179             :     }
     180             : 
     181           0 :     virtual sal_Int32 SAL_CALL compareContentIds(
     182             :         css::uno::Reference< css::ucb::XContentIdentifier > const & id1,
     183             :         css::uno::Reference< css::ucb::XContentIdentifier > const & id2)
     184             :         throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
     185             :     {
     186             :         assert(id1.is() && id2.is());
     187             :         return
     188           0 :             id1->getContentIdentifier().compareTo(id2->getContentIdentifier());
     189             :     }
     190             : };
     191             : 
     192          18 : class Test: public CppUnit::TestFixture {
     193             : public:
     194             :     virtual void setUp() SAL_OVERRIDE;
     195             : 
     196             :     void finish();
     197             : 
     198             :     void testNormalizedMakeRelative();
     199             : 
     200             :     void testFindFirstURLInText();
     201             : 
     202           4 :     CPPUNIT_TEST_SUITE(Test);
     203           2 :     CPPUNIT_TEST(testNormalizedMakeRelative);
     204           2 :     CPPUNIT_TEST(testFindFirstURLInText);
     205           2 :     CPPUNIT_TEST(finish);
     206           4 :     CPPUNIT_TEST_SUITE_END();
     207             : 
     208             : private:
     209             :     static css::uno::Reference< css::uno::XComponentContext > m_context;
     210             : };
     211             : 
     212           6 : void Test::setUp() {
     213             :     // For whatever reason, on W32 it does not work to create/destroy a fresh
     214             :     // component context for each test in Test::setUp/tearDown; therefore, a
     215             :     // single component context is used for all tests and destroyed in the last
     216             :     // pseudo-test "finish":
     217           6 :     if (!m_context.is()) {
     218           2 :         m_context = cppu::defaultBootstrap_InitialComponentContext();
     219             :     }
     220           6 : }
     221             : 
     222           2 : void Test::finish() {
     223             :     css::uno::Reference< css::lang::XComponent >(
     224           2 :         m_context, css::uno::UNO_QUERY_THROW)->dispose();
     225           2 : }
     226             : 
     227           2 : void Test::testNormalizedMakeRelative() {
     228           4 :     css::ucb::UniversalContentBroker::create(m_context)->
     229             :         registerContentProvider(
     230           2 :             new Provider, OUString("test"),
     231           4 :             true);
     232             :     struct Data {
     233             :         char const * base;
     234             :         char const * absolute;
     235             :         char const * relative;
     236             :     };
     237             :     static Data const tests[] = {
     238             :         { "hierarchical:/", "mailto:def@a.b.c.", "mailto:def@a.b.c." },
     239             :         { "hierarchical:/", "a/b/c", "a/b/c" },
     240             :         { "hierarchical:/a", "hierarchical:/a/b/c?d#e", "/a/b/c?d#e" },
     241             :         { "hierarchical:/a/", "hierarchical:/a/b/c?d#e", "b/c?d#e" },
     242             :         { "test:/0/0/a", "test:/0/b", "../b" },
     243             :         { "test:/1/1/a", "test:/1/b", "../b" },
     244             :         { "test:/2/2//a", "test:/2/b", "../../b" },
     245             :         { "test:/0a/b", "test:/0A/c#f", "c#f" },
     246             :         { "file:///usr/bin/nonex1/nonex2",
     247             :           "file:///usr/bin/nonex1/nonex3/nonex4", "nonex3/nonex4" },
     248             :         { "file:///usr/bin/nonex1/nonex2#fragmentA",
     249             :           "file:///usr/bin/nonex1/nonex3/nonex4#fragmentB",
     250             :           "nonex3/nonex4#fragmentB" },
     251             :         { "file:///usr/nonex1/nonex2", "file:///usr/nonex3", "../nonex3" },
     252             :         { "file:///c:/windows/nonex1", "file:///c:/nonex2", "../nonex2" },
     253             : #if defined WNT
     254             :         { "file:///c:/nonex1/nonex2", "file:///C:/nonex1/nonex3/nonex4",
     255             :           "nonex3/nonex4" }
     256             : #endif
     257             :     };
     258          26 :     for (std::size_t i = 0; i < SAL_N_ELEMENTS(tests); ++i) {
     259             :         css::uno::Reference< css::uri::XUriReference > ref(
     260             :             URIHelper::normalizedMakeRelative(
     261             :                 m_context, OUString::createFromAscii(tests[i].base),
     262          24 :                 OUString::createFromAscii(tests[i].absolute)));
     263          24 :         bool ok = tests[i].relative == 0
     264           0 :             ? !ref.is()
     265          24 :             : ref.is() && ref->getUriReference().equalsAscii(tests[i].relative);
     266          48 :         OString msg;
     267          24 :         if (!ok) {
     268           0 :             OStringBuffer buf;
     269           0 :             buf.append('<');
     270           0 :             buf.append(tests[i].base);
     271           0 :             buf.append(">, <");
     272           0 :             buf.append(tests[i].absolute);
     273           0 :             buf.append(">: ");
     274           0 :             if (ref.is()) {
     275           0 :                 buf.append('<');
     276             :                 buf.append(
     277             :                     OUStringToOString(
     278           0 :                         ref->getUriReference(), RTL_TEXTENCODING_UTF8));
     279           0 :                 buf.append('>');
     280             :             } else {
     281           0 :                 buf.append("none");
     282             :             }
     283           0 :             buf.append(" instead of ");
     284           0 :             if (tests[i].relative == 0) {
     285           0 :                 buf.append("none");
     286             :             } else {
     287           0 :                 buf.append('<');
     288           0 :                 buf.append(tests[i].relative);
     289           0 :                 buf.append('>');
     290             :             }
     291           0 :             msg = buf.makeStringAndClear();
     292             :         }
     293          24 :         CPPUNIT_ASSERT_MESSAGE(msg.getStr(), ok);
     294          24 :     }
     295           2 : }
     296             : 
     297           2 : void Test::testFindFirstURLInText() {
     298             :     struct Data {
     299             :         char const * input;
     300             :         char const * result;
     301             :         sal_Int32 begin;
     302             :         sal_Int32 end;
     303             :     };
     304             :     static Data const tests[] = {
     305             :         { "...ftp://bla.bla.bla/blubber/...",
     306             :           "ftp://bla.bla.bla/blubber/", 3, 29 },
     307             :         { "..\\ftp://bla.bla.bla/blubber/...", 0, 0, 0 },
     308             :         { "..\\ftp:\\\\bla.bla.bla\\blubber/...",
     309             : //Sync with tools/source/fsys/urlobj.cxx and changeScheme
     310             : #ifdef LINUX
     311             :           "smb://bla.bla.bla/blubber%2F", 7, 29 },
     312             : #else
     313             :           "file://bla.bla.bla/blubber%2F", 7, 29 },
     314             : #endif
     315             :         { "http://sun.com", "http://sun.com/", 0, 14 },
     316             :         { "http://sun.com/", "http://sun.com/", 0, 15 },
     317             :         { "http://www.xerox.com@www.pcworld.com/go/3990332.htm", 0, 0, 0 },
     318             :         { "ftp://www.xerox.com@www.pcworld.com/go/3990332.htm",
     319             :           "ftp://www.xerox.com@www.pcworld.com/go/3990332.htm", 0, 50 },
     320             :         { "Version.1.2.3", 0, 0, 0 },
     321             :         { "Version:1.2.3", 0, 0, 0 },
     322             :         { "a.b.c", 0, 0, 0 },
     323             :         { "file:///a|...", "file:///a:", 0, 10 },
     324             :         { "file:///a||...", "file:///a%7C%7C", 0, 11 },
     325             :         { "file:///a|/bc#...", "file:///a:/bc", 0, 13 },
     326             :         { "file:///a|/bc#de...", "file:///a:/bc#de", 0, 16 },
     327             :         { "abc.def.ghi,ftp.xxx.yyy/zzz...", "ftp://ftp.xxx.yyy/zzz", 12, 27 },
     328             :         { "abc.def.ghi,Ftp.xxx.yyy/zzz...", "ftp://Ftp.xxx.yyy/zzz", 12, 27 },
     329             :         { "abc.def.ghi,www.xxx.yyy...", "http://www.xxx.yyy/", 12, 23 },
     330             :         { "abc.def.ghi,wwww.xxx.yyy...", 0, 0, 0 },
     331             :         { "abc.def.ghi,wWW.xxx.yyy...", "http://wWW.xxx.yyy/", 12, 23 },
     332             :         { "Bla {mailto.me@abc.def.g.h.i}...",
     333             :           "mailto:%7Bmailto.me@abc.def.g.h.i", 4, 28 },
     334             :         { "abc@def@ghi", 0, 0, 0 },
     335             :         { "lala@sun.com", "mailto:lala@sun.com", 0, 12 },
     336             :         { "1lala@sun.com", "mailto:1lala@sun.com", 0, 13 },
     337             :         { "aaa_bbb@xxx.yy", "mailto:aaa_bbb@xxx.yy", 0, 14 },
     338             :         { "{a:\\bla/bla/bla...}", "file:///a:/bla/bla/bla", 1, 15 },
     339             :         { "#b:/c/d#e#f#", "file:///b:/c/d", 1, 7 },
     340             :         { "a:/", "file:///a:/", 0, 3 },
     341             :         { ".component:", 0, 0, 0 },
     342             :         { ".uno:", 0, 0, 0 },
     343             :         { "cid:", 0, 0, 0 },
     344             :         { "data:", 0, 0, 0 },
     345             :         { "db:", 0, 0, 0 },
     346             :         { "file:", 0, 0, 0 },
     347             :         { "ftp:", 0, 0, 0 },
     348             :         { "http:", 0, 0, 0 },
     349             :         { "https:", 0, 0, 0 },
     350             :         { "imap:", 0, 0, 0 },
     351             :         { "javascript:", 0, 0, 0 },
     352             :         { "ldap:", 0, 0, 0 },
     353             :         { "macro:", 0, 0, 0 },
     354             :         { "mailto:", 0, 0, 0 },
     355             :         { "news:", 0, 0, 0 },
     356             :         { "out:", 0, 0, 0 },
     357             :         { "pop3:", 0, 0, 0 },
     358             :         { "private:", 0, 0, 0 },
     359             :         { "slot:", 0, 0, 0 },
     360             :         { "staroffice.component:", 0, 0, 0 },
     361             :         { "staroffice.db:", 0, 0, 0 },
     362             :         { "staroffice.factory:", 0, 0, 0 },
     363             :         { "staroffice.helpid:", 0, 0, 0 },
     364             :         { "staroffice.java:", 0, 0, 0 },
     365             :         { "staroffice.macro:", 0, 0, 0 },
     366             :         { "staroffice.out:", 0, 0, 0 },
     367             :         { "staroffice.pop3:", 0, 0, 0 },
     368             :         { "staroffice.private:", 0, 0, 0 },
     369             :         { "staroffice.searchfolder:", 0, 0, 0 },
     370             :         { "staroffice.slot:", 0, 0, 0 },
     371             :         { "staroffice.trashcan:", 0, 0, 0 },
     372             :         { "staroffice.uno:", 0, 0, 0 },
     373             :         { "staroffice.vim:", 0, 0, 0 },
     374             :         { "staroffice:", 0, 0, 0 },
     375             :         { "vim:", 0, 0, 0 },
     376             :         { "vnd.sun.star.cmd:", 0, 0, 0 },
     377             :         { "vnd.sun.star.help:", 0, 0, 0 },
     378             :         { "vnd.sun.star.hier:", 0, 0, 0 },
     379             :         { "vnd.sun.star.pkg:", 0, 0, 0 },
     380             :         { "vnd.sun.star.script:", 0, 0, 0 },
     381             :         { "vnd.sun.star.webdav:", 0, 0, 0 },
     382             :         { "vnd.sun.star.wfs:", 0, 0, 0 },
     383             :         { "generic:path", 0, 0, 0 },
     384             :         { "wfs:", 0, 0, 0 }
     385             :     };
     386           2 :     CharClass charClass( m_context, LanguageTag( com::sun::star::lang::Locale("en", "US", "")));
     387         144 :     for (std::size_t i = 0; i < SAL_N_ELEMENTS(tests); ++i) {
     388         142 :         OUString input(OUString::createFromAscii(tests[i].input));
     389         142 :         sal_Int32 begin = 0;
     390         142 :         sal_Int32 end = input.getLength();
     391             :         OUString result(
     392         284 :             URIHelper::FindFirstURLInText(input, begin, end, charClass));
     393         142 :         bool ok = tests[i].result == 0
     394         204 :             ? (result.getLength() == 0 && begin == input.getLength()
     395         204 :                && end == input.getLength())
     396          80 :             : (result.equalsAscii(tests[i].result) && begin == tests[i].begin
     397         324 :                && end == tests[i].end);
     398         284 :         OString msg;
     399         142 :         if (!ok) {
     400           0 :             OStringBuffer buf;
     401           0 :             buf.append('"');
     402           0 :             buf.append(tests[i].input);
     403           0 :             buf.append("\" -> ");
     404           0 :             buf.append(tests[i].result == 0 ? "none" : tests[i].result);
     405           0 :             buf.append(" (");
     406           0 :             buf.append(static_cast< sal_Int32 >(tests[i].begin));
     407           0 :             buf.append(", ");
     408           0 :             buf.append(static_cast< sal_Int32 >(tests[i].end));
     409           0 :             buf.append(')');
     410           0 :             buf.append(" != ");
     411           0 :             buf.append(OUStringToOString(result, RTL_TEXTENCODING_UTF8));
     412           0 :             buf.append(" (");
     413           0 :             buf.append(static_cast< sal_Int32 >(begin));
     414           0 :             buf.append(", ");
     415           0 :             buf.append(static_cast< sal_Int32 >(end));
     416           0 :             buf.append(')');
     417           0 :             msg = buf.makeStringAndClear();
     418             :         }
     419         142 :         CPPUNIT_ASSERT_MESSAGE(msg.getStr(), ok);
     420         144 :     }
     421           2 : }
     422             : 
     423           2 : css::uno::Reference< css::uno::XComponentContext > Test::m_context;
     424             : 
     425           2 : CPPUNIT_TEST_SUITE_REGISTRATION(Test);
     426             : 
     427             : }
     428             : 
     429           8 : CPPUNIT_PLUGIN_IMPLEMENT();
     430             : 
     431             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10