From 0b2cf32b840e7ea5a1fab48c4a24ce6759d4a7ed Mon Sep 17 00:00:00 2001 From: Slava Monich Date: Sun, 9 Aug 2015 12:51:26 +0300 Subject: [PATCH] [test] Added CSS parser test --- .gitignore | 1 + test/Makefile | 21 +++ test/common/common.pri | 37 ++++ test/common/stubs.cpp | 39 ++++ test/fbreader | 1 + test/fribidi | 1 + test/harbour-lib | 1 + test/linebreak | 1 + test/test-css/data/basic/in.css | 32 ++++ test/test-css/data/basic/out.css | 20 ++ test/test-css/data/test1/in.css | 270 +++++++++++++++++++++++++++ test/test-css/data/test1/out.css | 99 ++++++++++ test/test-css/data/test2/in.css | 153 ++++++++++++++++ test/test-css/data/test2/out.css | 136 ++++++++++++++ test/test-css/main.cpp | 301 +++++++++++++++++++++++++++++++ test/test-css/test-css.pro | 5 + test/tests.pro | 3 + 17 files changed, 1121 insertions(+) create mode 100644 test/Makefile create mode 100644 test/common/common.pri create mode 100644 test/common/stubs.cpp create mode 120000 test/fbreader create mode 120000 test/fribidi create mode 120000 test/harbour-lib create mode 120000 test/linebreak create mode 100644 test/test-css/data/basic/in.css create mode 100644 test/test-css/data/basic/out.css create mode 100644 test/test-css/data/test1/in.css create mode 100644 test/test-css/data/test1/out.css create mode 100644 test/test-css/data/test2/in.css create mode 100644 test/test-css/data/test2/out.css create mode 100644 test/test-css/main.cpp create mode 100644 test/test-css/test-css.pro create mode 100644 test/tests.pro diff --git a/.gitignore b/.gitignore index 30a4648..359e01e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ harbour-books.pro.user +tests.pro.user build diff --git a/test/Makefile b/test/Makefile new file mode 100644 index 0000000..723076b --- /dev/null +++ b/test/Makefile @@ -0,0 +1,21 @@ +# -*- Mode: makefile-gmake -*- + +.PHONY: all compile test test-css + +BUILD_DIR = build +PATH_BACK = .. + +all: build test + +test: test-css + +test-css: compile + @echo "====== $@ =======" + $(BUILD_DIR)/test-css/test-css -a -d test-css/data + +compile: $(BUILD_DIR) + (cd $(BUILD_DIR); qmake CONFIG+=debug $(PATH_BACK)/tests.pro) + @make -C $(BUILD_DIR) + +$(BUILD_DIR): + @mkdir -p $@ diff --git a/test/common/common.pri b/test/common/common.pri new file mode 100644 index 0000000..d0000d5 --- /dev/null +++ b/test/common/common.pri @@ -0,0 +1,37 @@ +CONFIG += link_pkgconfig +PKGCONFIG += glib-2.0 + +WARNINGS = -Wall -Wno-unused-parameter -Wno-deprecated-declarations -Wno-missing-field-initializers +QMAKE_CXXFLAGS += $$WARNINGS -Wno-psabi +QMAKE_CFLAGS += $$WARNINGS + +CONFIG(debug, debug|release) { + QMAKE_CXXFLAGS_DEBUG *= -O0 + QMAKE_CFLAGS_DEBUG *= -O0 + DEFINES += HARBOUR_DEBUG=1 +} + +# Directories +FBREADER_DIR = $$_PRO_FILE_PWD_/../fbreader/fbreader + +# Libraries +FBREADER_LIB = $$OUT_PWD/../fbreader/libfbreader.a +FRIBIDI_LIB = $$OUT_PWD/../fribidi/libfribidi.a +LINEBREAK_LIB = $$OUT_PWD/../linebreak/liblinebreak.a + +PRE_TARGETDEPS += \ + $$FBREADER_LIB \ + $$FRIBIDI_LIB \ + $$LINEBREAK_LIB + +LIBS += \ + $$FBREADER_LIB \ + $$FRIBIDI_LIB \ + $$LINEBREAK_LIB \ + -lbz2 -lz -lexpat -lmagic + +INCLUDEPATH += \ + $$FBREADER_DIR/zlibrary/core/include \ + $$FBREADER_DIR/zlibrary/text/include \ + $$FBREADER_DIR/zlibrary/ui/src/qt4 \ + $$FBREADER_DIR/fbreader/src/formats/css diff --git a/test/common/stubs.cpp b/test/common/stubs.cpp new file mode 100644 index 0000000..1c40881 --- /dev/null +++ b/test/common/stubs.cpp @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2015 Jolla Ltd. + * Contact: Slava Monich + * + * You may use this file under the terms of the BSD license as follows: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Nemo Mobile nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "ZLExecutionData.h" +#include "ZLibrary.h" +#include "ZLImage.h" + +const std::string ZLibrary::FileNameDelimiter("/"); +std::string ZLibrary::ourZLibraryDirectory("."); diff --git a/test/fbreader b/test/fbreader new file mode 120000 index 0000000..3cc4491 --- /dev/null +++ b/test/fbreader @@ -0,0 +1 @@ +../fbreader/ \ No newline at end of file diff --git a/test/fribidi b/test/fribidi new file mode 120000 index 0000000..9500c28 --- /dev/null +++ b/test/fribidi @@ -0,0 +1 @@ +../fribidi/ \ No newline at end of file diff --git a/test/harbour-lib b/test/harbour-lib new file mode 120000 index 0000000..e95a7ee --- /dev/null +++ b/test/harbour-lib @@ -0,0 +1 @@ +../harbour-lib/ \ No newline at end of file diff --git a/test/linebreak b/test/linebreak new file mode 120000 index 0000000..0d833fe --- /dev/null +++ b/test/linebreak @@ -0,0 +1 @@ +../linebreak/ \ No newline at end of file diff --git a/test/test-css/data/basic/in.css b/test/test-css/data/basic/in.css new file mode 100644 index 0000000..414f3e4 --- /dev/null +++ b/test/test-css/data/basic/in.css @@ -0,0 +1,32 @@ +/* Basic tests */ +/* 1. DOS-style EOL */ +/* 2. Ignore AT-rules */ +@foo { foo: bar; } +@font-face { + font-family: "foo"; + src: url(fonts/bar.ttf); +} +/* 3. Multi + line + comment */ +/* 4. Comment within a statement */ +body,h1,h2, /*///****/ div, p { +/* 5. Empty line */ + +/* 6. Unknown attribute */ + unknown-attribute: unknown-value; +/* 7. Extra semicolon */ + extra: semicolon;; +/* 8. Missing attribute name */ + : missing-attribute-name; +/* 9. Missing colon */ + missing-colon +/* 10. Missing semicolon */ + missing: semicolon + font-family: \ +/* 11. Multi-line statement */ \ + "Foo\ + Bar"; +/* 12: Known style with missing semicolon */ + font-style: italic +} diff --git a/test/test-css/data/basic/out.css b/test/test-css/data/basic/out.css new file mode 100644 index 0000000..433cf49 --- /dev/null +++ b/test/test-css/data/basic/out.css @@ -0,0 +1,20 @@ +body { + font-style: italic; + font-family: "Foo Bar"; +} +h1 { + font-style: italic; + font-family: "Foo Bar"; +} +h2 { + font-style: italic; + font-family: "Foo Bar"; +} +div { + font-style: italic; + font-family: "Foo Bar"; +} +p { + font-style: italic; + font-family: "Foo Bar"; +} diff --git a/test/test-css/data/test1/in.css b/test/test-css/data/test1/in.css new file mode 100644 index 0000000..18b1bf6 --- /dev/null +++ b/test/test-css/data/test1/in.css @@ -0,0 +1,270 @@ +.alert { + -moz-box-sizing: border-box; + box-sizing: border-box; + display: block + } +.book-chapter { + -moz-box-sizing: border-box; + box-sizing: border-box; + display: none; + font-size: 2em; + font-weight: bold; + line-height: 1.2; + padding-bottom: 0.3em; + position: relative; + border-bottom: #eee solid 1px; + margin: 1em 0 16px + } +.calibre { + display: block; + font-size: 1em; + padding-left: 0; + padding-right: 0; + margin: 0 5pt + } +.calibre1 { + display: none + } +.calibre2 { + -moz-box-sizing: border-box; + box-sizing: border-box; + display: block; + font-size: 2em; + font-weight: bold; + line-height: 1.2; + padding-bottom: 0.3em; + position: relative; + border-bottom: #eee solid 1px; + margin: 1em 0 16px + } +.calibre3 { + -moz-box-sizing: border-box; + box-sizing: border-box; + display: block; + font-size: 1.83333em; + font-weight: bold; + line-height: 1.2; + padding-bottom: 0.3em; + position: relative; + border-bottom: #eee solid 1px; + margin: 1em 0 16px + } +.calibre4 { + -moz-box-sizing: border-box; + box-sizing: border-box; + display: block; + margin: 0 0 16px + } +.calibre5 { + -moz-box-sizing: border-box; + box-sizing: border-box; + font-style: italic + } +.calibre6 { + -moz-box-sizing: border-box; + background: transparent; + box-sizing: border-box; + color: #4183c4; + text-decoration: none + } +.calibre7 { + -moz-box-sizing: border-box; + box-sizing: border-box; + height: auto; + max-width: 100%; + page-break-inside: avoid; + width: auto; + border: currentColor none 0 + } +.calibre8 { + -moz-box-sizing: border-box; + box-sizing: border-box; + font-weight: bold + } +.calibre9 { + -moz-box-sizing: border-box; + background-color: #f7f7f7; + border-radius: 3px; + box-sizing: border-box; + font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; + font-size: 0.75em; + padding: 0.2em 0; + margin: 0 + } +.calibre10 { + -moz-box-sizing: border-box; + background-color: #f7f7f7; + border-radius: 3px; + box-sizing: border-box; + display: block; + font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; + font-size: 0.75em; + line-height: 1.45; + overflow: auto; + white-space: pre-wrap; + word-wrap: normal; + padding: 16px; + border: currentColor none 0; + margin: 0 0 16px + } +.calibre11 { + -moz-box-sizing: border-box; + box-sizing: border-box; + display: table-row-group; + vertical-align: middle + } +.calibre12 { + -moz-box-sizing: border-box; + background-color: #fff; + box-sizing: border-box; + display: table-row; + vertical-align: inherit; + border-top: #ccc solid 1px + } +.calibre13 { + -moz-box-sizing: border-box; + box-sizing: border-box; + display: table-cell; + text-align: inherit; + vertical-align: inherit; + padding: 6px 13px; + border: #ddd solid 1px + } +.calibre14 { + -moz-box-sizing: border-box; + background-color: #f8f8f8; + box-sizing: border-box; + display: table-row; + vertical-align: inherit; + border-top: #ccc solid 1px + } +.calibre15 { + -moz-box-sizing: border-box; + box-sizing: border-box; + display: block; + font-size: 1.41667em; + font-weight: bold; + line-height: 1.43; + position: relative; + margin: 1em 0 16px + } +.hljs-comment { + -moz-box-sizing: border-box; + box-sizing: border-box; + color: #8e908c + } +.hljs-keyword { + -moz-box-sizing: border-box; + box-sizing: border-box; + color: #8959a8 + } +.hljs-preprocessor { + -moz-box-sizing: border-box; + box-sizing: border-box; + color: #f5871f + } +.hljs-string { + -moz-box-sizing: border-box; + box-sizing: border-box; + color: #718c00 + } +.lang-c { + -moz-box-sizing: border-box; + background: transparent; + background-color: transparent; + border-radius: 3px; + box-sizing: border-box; + display: inline; + font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; + font-size: 1em; + line-height: inherit; + max-width: initial; + overflow: initial; + white-space: pre-wrap; + word-wrap: normal; + padding: 0; + border: currentColor none 0; + margin: 0 + } +.list-group { + -moz-box-sizing: border-box; + box-sizing: border-box; + display: block; + list-style-type: disc; + margin-bottom: 16px; + margin-right: 0; + margin-top: 0; + padding-bottom: 0; + padding-right: 0; + padding-top: 0 + } +.list-group-item { + -moz-box-sizing: border-box; + box-sizing: border-box; + display: list-item + } +.normal { + -moz-box-sizing: border-box; + box-sizing: border-box + } +.page { + -ms-text-size-adjust: 100%; + -webkit-text-size-adjust: 100%; + color: #333; + display: block; + font-family: sans-serif; + line-height: 1.6; + overflow: hidden; + word-wrap: break-word + } +.table { + -moz-box-sizing: border-box; + border-collapse: collapse; + border-spacing: 0; + box-sizing: border-box; + display: block; + margin-bottom: 16px; + margin-top: 0; + overflow: auto; + text-indent: 0; + width: 100% + } +.table1 { + -moz-box-sizing: border-box; + border-collapse: collapse; + border-spacing: 0; + box-sizing: border-box; + display: inline; + margin-bottom: 16px; + margin-top: 0; + overflow: auto; + text-indent: 0; + width: 100% + } +.pcalibre2:focus { + text-decoration: underline + } +.pcalibre3:after { + content: " "; + letter-spacing: -0.2em + } +.pcalibre5:after { + content: normal; + letter-spacing: -0.2em + } +.pcalibre4:before { + content: " "; + letter-spacing: -0.2em + } +.pcalibre6:before { + content: normal; + letter-spacing: -0.2em + } +.pcalibre1:hover { + outline: 0; + text-decoration: underline + } +.pcalibre:active { + outline: 0; + text-decoration: underline + } diff --git a/test/test-css/data/test1/out.css b/test/test-css/data/test1/out.css new file mode 100644 index 0000000..7d24288 --- /dev/null +++ b/test/test-css/data/test1/out.css @@ -0,0 +1,99 @@ +.book-chapter { + margin-left: 0; + margin-bottom: 16px; + margin-top: 1em; + margin-right: 0; + display: none; + font-weight: bold; + font-size: 207%; /* 4 */ +} +.calibre { + margin-left: 5px; + margin-bottom: 0; + margin-top: 0; + margin-right: 5px; + font-size: 100%; /* 0 */ +} +.calibre1 { + display: none; +} +.calibre2 { + margin-left: 0; + margin-bottom: 16px; + margin-top: 1em; + margin-right: 0; + font-weight: bold; + font-size: 207%; /* 4 */ +} +.calibre3 { + margin-left: 0; + margin-bottom: 16px; + margin-top: 1em; + margin-right: 0; + font-weight: bold; + font-size: 207%; /* 4 */ +} +.calibre4 { + margin-left: 0; + margin-bottom: 16px; + margin-top: 0; + margin-right: 0; +} +.calibre5 { + font-style: italic; +} +.calibre8 { + font-weight: bold; +} +.calibre9 { + margin-left: 0; + margin-bottom: 0; + margin-top: 0; + margin-right: 0; + font-family: "Consolas", "Liberation Mono", "Menlo", "Courier", "monospace"; + font-size: 83%; /* -1 */ +} +.calibre10 { + margin-left: 0; + margin-bottom: 16px; + margin-top: 0; + margin-right: 0; + white-space: pre-wrap; + font-family: "Consolas", "Liberation Mono", "Menlo", "Courier", "monospace"; + font-size: 83%; /* -1 */ +} +.calibre15 { + margin-left: 0; + margin-bottom: 16px; + margin-top: 1em; + margin-right: 0; + font-weight: bold; + font-size: 144%; /* 2 */ +} +.lang-c { + margin-left: 0; + margin-bottom: 0; + margin-top: 0; + margin-right: 0; + white-space: pre-wrap; + font-family: "Consolas", "Liberation Mono", "Menlo", "Courier", "monospace"; + font-size: 100%; /* 0 */ +} +.list-group { + margin-bottom: 16px; + margin-top: 0; + margin-right: 0; +} +.page { + font-family: "sans-serif"; +} +.table { + margin-bottom: 16px; + margin-top: 0; + text-indent: 0; +} +.table1 { + margin-bottom: 16px; + margin-top: 0; + text-indent: 0; +} diff --git a/test/test-css/data/test2/in.css b/test/test-css/data/test2/in.css new file mode 100644 index 0000000..c53cdec --- /dev/null +++ b/test/test-css/data/test2/in.css @@ -0,0 +1,153 @@ +body.cover { + margin: 0px; + oeb-column-number: 1; + padding: 0px; +} + +svg.cover-svg { + height: 100%; + width: 100%; +} + +.z { + font-family: 'Times New Roman', serif; + margin-right: 8pt; +} + +.title { + font-size: 2.2em; + font-weight: bold; + margin: 1em 0px 0.5em 0px; + page-break-after: avoid; + page-break-inside: avoid; + text-align: center; +} + +.p { + margin: 0px 0px 0.5em 0px; + text-align: inherit; + text-indent: 0px; +} + +.epigraph { + font-style: italic; + margin: 1em 1em 2em 30%; + text-align: left; +} + +.p1 { + margin: 0px; + text-align: justify; + text-indent: 1.5em; +} + +.text-author { + margin: 0.2em 0px 0px 3em; + text-indent: 0px; +} + +.title1 { + font-size: 1.8em; + font-weight: bold; + margin: 1em 0px 0.5em 0px; + page-break-after: avoid; + page-break-inside: avoid; + text-align: center; +} + +.title2 { + font-size: 1.5em; + font-weight: bold; + margin: 1em 0px 0.5em 1.563em; + page-break-after: avoid; + page-break-inside: avoid; + text-align: left; +} + +.empty-line { + height: 1em; + margin: 0px; +} + +.a { + font-size: 0.7em; + line-height: 0.1; + vertical-align: super; +} + +.poem { + margin: 0.5em 0px 0.5em 2em; +} + +.stanza { + margin: 0.5em 0px; + page-break-inside: avoid; +} + +.v { + margin: 0px; + padding-left: 1em; + text-indent: -1em; +} + +.subtitle { + font-style: italic; + font-weight: bold; + margin: 0.5em 2em; + page-break-after: avoid; + page-break-inside: avoid; + text-align: center; + text-indent: 0px; +} + +.title3 { + font-size: 1.3em; + font-weight: bold; + margin: 1em 0px 0.5em 1.923em; + page-break-after: avoid; + page-break-inside: avoid; + text-align: left; +} + +.cite { + font-size: 0.95em; + margin: 0.5em 0px 0.5em 1em; +} + +.title4 { + font-size: 1.2em; + font-weight: bold; + margin: 1em 0px 0.5em 2.083em; + page-break-after: avoid; + page-break-inside: avoid; + text-align: left; +} + +@font-face { + font-family: 'Times New Roman'; + font-style: italic; + font-weight: normal; + src: url(fonts/Times-New-Roman-400-Italic-0dc9cb1e-1e51-102b-9d2a-1f07c3bd69d8.otf); +} + +@font-face { + font-family: 'Times New Roman'; + font-style: normal; + font-weight: normal; + src: url(fonts/Times-New-Roman-400-0dc9cb1e-1e51-102b-9d2a-1f07c3bd69d8.otf); +} + +@font-face { + font-family: 'Times New Roman'; + font-style: italic; + font-weight: bold; + src: url(fonts/Times-New-Roman-700-Italic-0dc9cb1e-1e51-102b-9d2a-1f07c3bd69d8.otf); +} + +@font-face { + font-family: 'Times New Roman'; + font-style: normal; + font-weight: bold; + src: url(fonts/Times-New-Roman-700-0dc9cb1e-1e51-102b-9d2a-1f07c3bd69d8.otf); +} + diff --git a/test/test-css/data/test2/out.css b/test/test-css/data/test2/out.css new file mode 100644 index 0000000..c311dfe --- /dev/null +++ b/test/test-css/data/test2/out.css @@ -0,0 +1,136 @@ +body.cover { + margin-left: 0; + margin-bottom: 0; + margin-top: 0; + margin-right: 0; +} +.z { + margin-right: 8px; + font-family: "Times New Roman", "serif"; +} +.title { + margin-left: 0; + margin-bottom: 0.5em; + margin-top: 1em; + margin-right: 0; + page-break-before: avoid; + text-align: center; + font-weight: bold; + font-size: 248%; /* 5 */ +} +.p { + margin-left: 0; + margin-bottom: 0.5em; + margin-top: 0; + margin-right: 0; + text-indent: 0; +} +.epigraph { + margin-left: 30%; + margin-bottom: 2em; + margin-top: 1em; + margin-right: 1em; + text-align: left; + font-style: italic; +} +.p1 { + margin-left: 0; + margin-bottom: 0; + margin-top: 0; + margin-right: 0; + text-indent: 1.5em; + text-align: justify; +} +.text-author { + margin-left: 3em; + margin-bottom: 0; + margin-top: 0.2em; + margin-right: 0; + text-indent: 0; +} +.title1 { + margin-left: 0; + margin-bottom: 0.5em; + margin-top: 1em; + margin-right: 0; + page-break-before: avoid; + text-align: center; + font-weight: bold; + font-size: 207%; /* 4 */ +} +.title2 { + margin-left: 1.56em; + margin-bottom: 0.5em; + margin-top: 1em; + margin-right: 0; + page-break-before: avoid; + text-align: left; + font-weight: bold; + font-size: 172%; /* 3 */ +} +.empty-line { + margin-left: 0; + margin-bottom: 0; + margin-top: 0; + margin-right: 0; +} +.a { + font-size: 83%; /* -1 */ +} +.poem { + margin-left: 2em; + margin-bottom: 0.5em; + margin-top: 0.5em; + margin-right: 0; +} +.stanza { + margin-left: 0; + margin-bottom: 0.5em; + margin-top: 0.5em; + margin-right: 0; +} +.v { + margin-left: 0; + margin-bottom: 0; + margin-top: 0; + margin-right: 0; + text-indent: -1em; +} +.subtitle { + margin-left: 2em; + margin-bottom: 0.5em; + margin-top: 0.5em; + margin-right: 2em; + text-indent: 0; + page-break-before: avoid; + text-align: center; + font-weight: bold; + font-style: italic; +} +.title3 { + margin-left: 1.92em; + margin-bottom: 0.5em; + margin-top: 1em; + margin-right: 0; + page-break-before: avoid; + text-align: left; + font-weight: bold; + font-size: 144%; /* 2 */ +} +.cite { + margin-left: 1em; + margin-bottom: 0.5em; + margin-top: 0.5em; + margin-right: 0; + font-size: 83%; /* -1 */ +} +.title4 { + margin-left: 2.08em; + margin-bottom: 0.5em; + margin-top: 1em; + margin-right: 0; + page-break-before: avoid; + text-align: left; + font-weight: bold; + font-size: 120%; /* 1 */ +} diff --git a/test/test-css/main.cpp b/test/test-css/main.cpp new file mode 100644 index 0000000..ddc4088 --- /dev/null +++ b/test/test-css/main.cpp @@ -0,0 +1,301 @@ +/* + * Copyright (C) 2015 Jolla Ltd. + * Contact: Slava Monich + * + * You may use this file under the terms of the BSD license as follows: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Nemo Mobile nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#define private public +#include "StyleSheetParser.h" +#undef private + +#include "ZLInputStream.h" +#include "ZLStringUtil.h" +#include "ZLFile.h" + +#include "filesystem/ZLQtFSManager.h" + +#include +#include +#include + +#define RET_OK (0) +#define RET_CMD_LINE (1) +#define RET_ERR_IO (2) +#define RET_ERR_TEST (3) + +static void +dumpLength( + const ZLTextStyleEntry& entry, + ZLTextStyleEntry::Length type, + const char* name, + std::ostream& out) +{ + if (entry.lengthSupported(type)) { + const ZLTextStyleEntry::LengthType* length = entry.myLengths + type; + out << " " << name << ": "; + if (!length->Size) { + out << "0"; + } else { + switch (entry.myLengths[type].Unit) { + case ZLTextStyleEntry::SIZE_UNIT_PIXEL: + out << length->Size << "px"; + break; + case ZLTextStyleEntry::SIZE_UNIT_EM_100: + out << length->Size/100. << "em"; + break; + case ZLTextStyleEntry::SIZE_UNIT_EX_100: + out << length->Size/100. << "ex"; + break; + case ZLTextStyleEntry::SIZE_UNIT_PERCENT: + out << length->Size << "%"; + break; + } + } + out << ";\n"; + } +} + +static void +dumpStyle( + const StyleSheetTable::Style& style, + std::ostream& out) +{ + dumpLength(style.TextStyle, ZLTextStyleEntry::LENGTH_LEFT_INDENT, "margin-left", out); + dumpLength(style.TextStyle, ZLTextStyleEntry::LENGTH_SPACE_AFTER, "margin-bottom", out); + dumpLength(style.TextStyle, ZLTextStyleEntry::LENGTH_SPACE_BEFORE, "margin-top", out); + dumpLength(style.TextStyle, ZLTextStyleEntry::LENGTH_RIGHT_INDENT, "margin-right", out); + dumpLength(style.TextStyle, ZLTextStyleEntry::LENGTH_FIRST_LINE_INDENT_DELTA, "text-indent", out); + if (style.PageBreakBefore != B3_UNDEFINED) { + out << " page-break-before: " << + ((style.PageBreakBefore == B3_TRUE) ? "always" : "avoid") << ";\n"; + } + if (style.PageBreakAfter != B3_UNDEFINED) { + out << " page-break-before: " << + ((style.PageBreakAfter == B3_TRUE) ? "always" : "avoid") << ";\n"; + } + if (style.WhiteSpace != StyleSheetTable::WS_UNDEFINED) { + static const char* values[] = {NULL, "normal", "nowrap", "pre", "pre-wrap", "pre-line" }; + out << " white-space: " << values[style.WhiteSpace] << ";\n"; + } + if (style.DisplayNone) { + out << " display: none;\n"; + } + if (style.TextStyle.alignmentTypeSupported()) { + const char* align; + switch (style.TextStyle.alignmentType()) { + case ALIGN_LEFT: align = "left"; break; + case ALIGN_RIGHT: align = "right"; break; + case ALIGN_CENTER: align = "center"; break; + case ALIGN_JUSTIFY: align = "justify"; break; + default: align = NULL; break; + } + if (align) { + out << " text-align: " << align << ";\n"; + } + } + const unsigned char supMod = style.TextStyle.supportedFontModifier(); + const unsigned char mod = style.TextStyle.fontModifier(); + if (supMod & FONT_MODIFIER_BOLD) { + out << " font-weight: " << + ((mod & FONT_MODIFIER_BOLD) ? "bold" : "normal") << ";\n"; + } + if (supMod & FONT_MODIFIER_ITALIC) { + out << " font-style: " << + ((mod & FONT_MODIFIER_ITALIC) ? "italic" : "normal") << ";\n"; + } + if (supMod & FONT_MODIFIER_SMALLCAPS) { + out << " font-variant: " << + ((mod & FONT_MODIFIER_SMALLCAPS) ? "small-caps" : "normal") << ";\n"; + } + if (style.TextStyle.fontFamiliesSupported()) { + const std::vector& fonts = style.TextStyle.fontFamilies(); + if (!fonts.empty()) { + out << " font-family: "; + std::vector::const_iterator it; + for (it = fonts.begin(); it != fonts.end(); ++it) { + if (it != fonts.begin()) out << ", "; + out << "\"" << *it << "\""; + } + out << ";\n"; + } + } + if (style.TextStyle.fontSizeSupported()) { + out << " font-size: "; + const signed char mag = style.TextStyle.fontSizeMag(); + int size = 100; + if (mag >= 0) { + for (int i = 0; i < mag; ++i) size *= 6; + for (int i = 0; i < mag; ++i) size /= 5; + } else { + for (int i = 0; i > mag; --i) size *= 5; + for (int i = 0; i > mag; --i) size /= 6; + } + out << size << "%; /* " << ((int)mag) << " */\n"; + } +} + +static void +dumpTable( + const StyleSheetTable& table, + std::ostream& out) +{ + std::vector::const_iterator it; + for (it = table.myEntries.begin(); it != table.myEntries.end(); ++it) { + const StyleSheetTable::Entry& entry = *it; + StyleSheetTable::SelectorList::const_iterator sit; + for (sit = entry.Selectors.begin(); sit != entry.Selectors.end(); ++sit) { + const StyleSheetTable::Selector& selector = *sit; + out << selector.myType; + if (!selector.myClass.empty()) out << "." << selector.myClass; + if (!selector.myId.empty()) out << "#" << selector.myId; + out << " "; + } + out << "{\n"; + dumpStyle(entry.Style, out); + out << "}\n"; + } +} + +static int +process_file( + std::string fname, + std::ostream& out) +{ + ZLFile file(fname); + shared_ptr stream = file.inputStream(); + if (!stream.isNull() && stream->open()) { + StyleSheetTable table; + StyleSheetTableParser parser(table); + parser.parse(*stream); + dumpTable(table, out); + return RET_OK; + } else { + std::cerr << "Failed to open " << fname << std::endl; + return RET_ERR_IO; + } +} + +static int +process( + std::string name) +{ + int ret; + ZLFile file(name); + if (file.isDirectory()) { + std::string in(name + "/in.css"); + std::string res(name + "/out.css"); + std::ostringstream out; + ret = process_file(in, out); + if (ret == RET_OK) { + std::ifstream fres(res.c_str()); + if (fres) { + std::stringstream buf; + buf << fres.rdbuf(); + fres.close(); + if (buf.str() != out.str()) { + std::cerr << "Test output mismatch with " << res << std::endl; + //std::cerr << out.str(); + ret = RET_ERR_TEST; + } + } else { + + std::cerr << "Failed to open " << res << std::endl; + ret = RET_ERR_IO; + } + } + std::cerr << ((ret == RET_OK) ? "OK" : "FAIL") << ": " << name << std::endl; + } else { + ret = process_file(name, std::cout); + } + return ret; +} + +int main(int argc, char **argv) +{ + int ret; + char* customDataDir = NULL; + gboolean autoTest = FALSE; + +#define DATA_DIR "data" + GOptionEntry entries[] = { + { "autotest", 'a', 0, G_OPTION_ARG_NONE, &autoTest, + "Run auto-tests", NULL }, + { "data", 'd', 0, G_OPTION_ARG_FILENAME, &customDataDir, + "Data directory for autotest [" DATA_DIR "]", "DIR" }, + { NULL } + }; + + GError* error = NULL; + GOptionContext* options = g_option_context_new("- CSS parsing test"); + g_option_context_add_main_entries(options, entries, NULL); + gboolean ok = g_option_context_parse(options, &argc, &argv, &error); + + if (ok) { + if (argc == 1 && !autoTest) { + ret = RET_CMD_LINE; + char* help = g_option_context_get_help(options, FALSE, NULL); + std::cout << help; + g_free(help); + } else { + ret = RET_OK; + ZLQtFSManager::createInstance(); + if (argc > 1) { + for (int i=1; imessage << std::endl; + g_error_free(error); + ret = RET_CMD_LINE; + } + + g_option_context_free(options); + g_free(customDataDir); + return ret; +} diff --git a/test/test-css/test-css.pro b/test/test-css/test-css.pro new file mode 100644 index 0000000..d10fcb4 --- /dev/null +++ b/test/test-css/test-css.pro @@ -0,0 +1,5 @@ +TARGET = test-css + +!include(../common/common.pri) + +SOURCES += main.cpp ../common/stubs.cpp diff --git a/test/tests.pro b/test/tests.pro new file mode 100644 index 0000000..23a5fcd --- /dev/null +++ b/test/tests.pro @@ -0,0 +1,3 @@ +TEMPLATE = subdirs +CONFIG += ordered +SUBDIRS = fribidi linebreak fbreader test-css