Commit f1f711963b8e5f0b2b5a9d80a522cbd616a153a9
1 parent
f588d741
Add and test QPDFLogger class
Showing
9 changed files
with
561 additions
and
0 deletions
include/qpdf/QPDFLogger.hh
0 → 100644
| 1 | +// Copyright (c) 2005-2022 Jay Berkenbilt | |
| 2 | +// | |
| 3 | +// This file is part of qpdf. | |
| 4 | +// | |
| 5 | +// Licensed under the Apache License, Version 2.0 (the "License"); | |
| 6 | +// you may not use this file except in compliance with the License. | |
| 7 | +// You may obtain a copy of the License at | |
| 8 | +// | |
| 9 | +// http://www.apache.org/licenses/LICENSE-2.0 | |
| 10 | +// | |
| 11 | +// Unless required by applicable law or agreed to in writing, software | |
| 12 | +// distributed under the License is distributed on an "AS IS" BASIS, | |
| 13 | +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| 14 | +// See the License for the specific language governing permissions and | |
| 15 | +// limitations under the License. | |
| 16 | +// | |
| 17 | +// Versions of qpdf prior to version 7 were released under the terms | |
| 18 | +// of version 2.0 of the Artistic License. At your option, you may | |
| 19 | +// continue to consider qpdf to be licensed under those terms. Please | |
| 20 | +// see the manual for additional information. | |
| 21 | + | |
| 22 | +#ifndef QPDFLOGGER_HH | |
| 23 | +#define QPDFLOGGER_HH | |
| 24 | + | |
| 25 | +#include <qpdf/DLL.h> | |
| 26 | +#include <qpdf/Pipeline.hh> | |
| 27 | +#include <iostream> | |
| 28 | +#include <memory> | |
| 29 | + | |
| 30 | +class QPDFLogger | |
| 31 | +{ | |
| 32 | + public: | |
| 33 | + QPDF_DLL | |
| 34 | + QPDFLogger(); | |
| 35 | + | |
| 36 | + QPDF_DLL | |
| 37 | + static std::shared_ptr<QPDFLogger> defaultLogger(); | |
| 38 | + | |
| 39 | + // Defaults: | |
| 40 | + // | |
| 41 | + // info -- if save is standard output, standard error, else standard output | |
| 42 | + // warn -- whatever error points to | |
| 43 | + // error -- standard error | |
| 44 | + // save -- undefined unless set | |
| 45 | + // | |
| 46 | + // On deletion, finish() is called for the standard output and | |
| 47 | + // standard error pipelines, which flushes output. If you supply | |
| 48 | + // any custom pipelines, you must call finish() on them yourself. | |
| 49 | + // Note that calling finish is not needed for string, stdio, or | |
| 50 | + // ostream pipelines. | |
| 51 | + // | |
| 52 | + // NOTES ABOUT THE SAVE PIPELINE | |
| 53 | + // | |
| 54 | + // You should never set the save pipeline to the same destination | |
| 55 | + // as something else. Doing so will corrupt your save output. If | |
| 56 | + // you want to save to standard output, use the method | |
| 57 | + // saveToStandardOutput(). In addition to setting the save | |
| 58 | + // pipeline, that does the following extra things: | |
| 59 | + // | |
| 60 | + // * If standard output has been used, a logic error is thrown | |
| 61 | + // * If info is set to standard output at the time of the set save | |
| 62 | + // call, it is switched to standard error. | |
| 63 | + // | |
| 64 | + // This is not a guarantee. You can still mess this up in ways | |
| 65 | + // that are not checked. Here are a few examples: | |
| 66 | + // | |
| 67 | + // * Don't set any pipeline to standard output *after* passing it | |
| 68 | + // to setSave() | |
| 69 | + // * Don't use a separate mechanism to write stdout/stderr other | |
| 70 | + // than QPDFLogger::standardOutput() | |
| 71 | + // * Don't set anything to the same custom pipeline that save is | |
| 72 | + // set to. | |
| 73 | + // | |
| 74 | + // Just be sure that if you change pipelines around, you should | |
| 75 | + // avoid having the save pipeline also be used for any other | |
| 76 | + // purpose. The special case for saving to standard output allows | |
| 77 | + // you to call saveToStandardOutput() early without having to | |
| 78 | + // worry about the info pipeline. | |
| 79 | + | |
| 80 | + QPDF_DLL | |
| 81 | + void info(char const*); | |
| 82 | + QPDF_DLL | |
| 83 | + void info(std::string const&); | |
| 84 | + QPDF_DLL | |
| 85 | + std::shared_ptr<Pipeline> getInfo(bool null_okay = false); | |
| 86 | + | |
| 87 | + QPDF_DLL | |
| 88 | + void warn(char const*); | |
| 89 | + QPDF_DLL | |
| 90 | + void warn(std::string const&); | |
| 91 | + QPDF_DLL | |
| 92 | + std::shared_ptr<Pipeline> getWarn(bool null_okay = false); | |
| 93 | + | |
| 94 | + QPDF_DLL | |
| 95 | + void error(char const*); | |
| 96 | + QPDF_DLL | |
| 97 | + void error(std::string const&); | |
| 98 | + QPDF_DLL | |
| 99 | + std::shared_ptr<Pipeline> getError(bool null_okay = false); | |
| 100 | + | |
| 101 | + QPDF_DLL | |
| 102 | + std::shared_ptr<Pipeline> getSave(bool null_okay = false); | |
| 103 | + | |
| 104 | + QPDF_DLL | |
| 105 | + std::shared_ptr<Pipeline> standardOutput(); | |
| 106 | + QPDF_DLL | |
| 107 | + std::shared_ptr<Pipeline> standardError(); | |
| 108 | + QPDF_DLL | |
| 109 | + std::shared_ptr<Pipeline> discard(); | |
| 110 | + | |
| 111 | + // Passing a null pointer resets to default | |
| 112 | + QPDF_DLL | |
| 113 | + void setInfo(std::shared_ptr<Pipeline>); | |
| 114 | + QPDF_DLL | |
| 115 | + void setWarn(std::shared_ptr<Pipeline>); | |
| 116 | + QPDF_DLL | |
| 117 | + void setError(std::shared_ptr<Pipeline>); | |
| 118 | + // See notes above about the save pipeline | |
| 119 | + QPDF_DLL | |
| 120 | + void setSave(std::shared_ptr<Pipeline>); | |
| 121 | + QPDF_DLL | |
| 122 | + void saveToStandardOutput(); | |
| 123 | + | |
| 124 | + // Shortcut for logic to reset output to new output/error streams. | |
| 125 | + // out_stream is used for info, err_stream is used for error, and | |
| 126 | + // warning is cleared so that it follows error. | |
| 127 | + QPDF_DLL | |
| 128 | + void setOutputStreams(std::ostream* out_stream, std::ostream* err_stream); | |
| 129 | + | |
| 130 | + private: | |
| 131 | + std::shared_ptr<Pipeline> | |
| 132 | + throwIfNull(std::shared_ptr<Pipeline>, bool null_okay); | |
| 133 | + | |
| 134 | + class Members | |
| 135 | + { | |
| 136 | + friend class QPDFLogger; | |
| 137 | + | |
| 138 | + public: | |
| 139 | + QPDF_DLL | |
| 140 | + ~Members(); | |
| 141 | + | |
| 142 | + private: | |
| 143 | + Members(); | |
| 144 | + Members(Members const&) = delete; | |
| 145 | + | |
| 146 | + std::shared_ptr<Pipeline> p_discard; | |
| 147 | + std::shared_ptr<Pipeline> p_real_stdout; | |
| 148 | + std::shared_ptr<Pipeline> p_stdout; | |
| 149 | + std::shared_ptr<Pipeline> p_stderr; | |
| 150 | + std::shared_ptr<Pipeline> p_info; | |
| 151 | + std::shared_ptr<Pipeline> p_warn; | |
| 152 | + std::shared_ptr<Pipeline> p_error; | |
| 153 | + std::shared_ptr<Pipeline> p_save; | |
| 154 | + }; | |
| 155 | + std::shared_ptr<Members> m; | |
| 156 | +}; | |
| 157 | + | |
| 158 | +#endif // QPDFLOGGER_HH | ... | ... |
libqpdf/CMakeLists.txt
libqpdf/QPDFLogger.cc
0 → 100644
| 1 | +#include <qpdf/QPDFLogger.hh> | |
| 2 | + | |
| 3 | +#include <qpdf/Pl_Discard.hh> | |
| 4 | +#include <qpdf/Pl_OStream.hh> | |
| 5 | +#include <iostream> | |
| 6 | +#include <stdexcept> | |
| 7 | + | |
| 8 | +namespace | |
| 9 | +{ | |
| 10 | + class Pl_Track: public Pipeline | |
| 11 | + { | |
| 12 | + public: | |
| 13 | + Pl_Track(char const* identifier, Pipeline* next) : | |
| 14 | + Pipeline(identifier, next), | |
| 15 | + used(false) | |
| 16 | + { | |
| 17 | + } | |
| 18 | + | |
| 19 | + virtual void | |
| 20 | + write(unsigned char const* data, size_t len) override | |
| 21 | + { | |
| 22 | + this->used = true; | |
| 23 | + getNext()->write(data, len); | |
| 24 | + } | |
| 25 | + | |
| 26 | + virtual void | |
| 27 | + finish() override | |
| 28 | + { | |
| 29 | + getNext()->finish(); | |
| 30 | + } | |
| 31 | + | |
| 32 | + bool | |
| 33 | + getUsed() const | |
| 34 | + { | |
| 35 | + return used; | |
| 36 | + } | |
| 37 | + | |
| 38 | + private: | |
| 39 | + bool used; | |
| 40 | + }; | |
| 41 | +}; // namespace | |
| 42 | + | |
| 43 | +QPDFLogger::Members::Members() : | |
| 44 | + p_discard(new Pl_Discard()), | |
| 45 | + p_real_stdout(new Pl_OStream("standard output", std::cout)), | |
| 46 | + p_stdout(new Pl_Track("track stdout", p_real_stdout.get())), | |
| 47 | + p_stderr(new Pl_OStream("standard error", std::cerr)), | |
| 48 | + p_info(p_stdout), | |
| 49 | + p_warn(nullptr), | |
| 50 | + p_error(p_stderr), | |
| 51 | + p_save(nullptr) | |
| 52 | +{ | |
| 53 | +} | |
| 54 | + | |
| 55 | +QPDFLogger::Members::~Members() | |
| 56 | +{ | |
| 57 | + p_stdout->finish(); | |
| 58 | + p_stderr->finish(); | |
| 59 | +} | |
| 60 | + | |
| 61 | +QPDFLogger::QPDFLogger() : | |
| 62 | + m(new Members()) | |
| 63 | +{ | |
| 64 | +} | |
| 65 | + | |
| 66 | +std::shared_ptr<QPDFLogger> | |
| 67 | +QPDFLogger::defaultLogger() | |
| 68 | +{ | |
| 69 | + static auto l = std::make_shared<QPDFLogger>(); | |
| 70 | + return l; | |
| 71 | +} | |
| 72 | + | |
| 73 | +void | |
| 74 | +QPDFLogger::info(char const* s) | |
| 75 | +{ | |
| 76 | + getInfo(false)->writeCStr(s); | |
| 77 | +} | |
| 78 | + | |
| 79 | +void | |
| 80 | +QPDFLogger::info(std::string const& s) | |
| 81 | +{ | |
| 82 | + getInfo(false)->writeString(s); | |
| 83 | +} | |
| 84 | + | |
| 85 | +std::shared_ptr<Pipeline> | |
| 86 | +QPDFLogger::getInfo(bool null_okay) | |
| 87 | +{ | |
| 88 | + return throwIfNull(this->m->p_info, null_okay); | |
| 89 | +} | |
| 90 | + | |
| 91 | +void | |
| 92 | +QPDFLogger::warn(char const* s) | |
| 93 | +{ | |
| 94 | + getWarn(false)->writeCStr(s); | |
| 95 | +} | |
| 96 | + | |
| 97 | +void | |
| 98 | +QPDFLogger::warn(std::string const& s) | |
| 99 | +{ | |
| 100 | + getWarn(false)->writeString(s); | |
| 101 | +} | |
| 102 | + | |
| 103 | +std::shared_ptr<Pipeline> | |
| 104 | +QPDFLogger::getWarn(bool null_okay) | |
| 105 | +{ | |
| 106 | + if (this->m->p_warn) { | |
| 107 | + return this->m->p_warn; | |
| 108 | + } | |
| 109 | + return getError(null_okay); | |
| 110 | +} | |
| 111 | + | |
| 112 | +void | |
| 113 | +QPDFLogger::error(char const* s) | |
| 114 | +{ | |
| 115 | + getError(false)->writeCStr(s); | |
| 116 | +} | |
| 117 | + | |
| 118 | +void | |
| 119 | +QPDFLogger::error(std::string const& s) | |
| 120 | +{ | |
| 121 | + getError(false)->writeString(s); | |
| 122 | +} | |
| 123 | + | |
| 124 | +std::shared_ptr<Pipeline> | |
| 125 | +QPDFLogger::getError(bool null_okay) | |
| 126 | +{ | |
| 127 | + return throwIfNull(this->m->p_error, null_okay); | |
| 128 | +} | |
| 129 | + | |
| 130 | +std::shared_ptr<Pipeline> | |
| 131 | +QPDFLogger::getSave(bool null_okay) | |
| 132 | +{ | |
| 133 | + return throwIfNull(this->m->p_save, null_okay); | |
| 134 | +} | |
| 135 | + | |
| 136 | +std::shared_ptr<Pipeline> | |
| 137 | +QPDFLogger::standardOutput() | |
| 138 | +{ | |
| 139 | + return this->m->p_stdout; | |
| 140 | +} | |
| 141 | + | |
| 142 | +std::shared_ptr<Pipeline> | |
| 143 | +QPDFLogger::standardError() | |
| 144 | +{ | |
| 145 | + return this->m->p_stderr; | |
| 146 | +} | |
| 147 | + | |
| 148 | +std::shared_ptr<Pipeline> | |
| 149 | +QPDFLogger::discard() | |
| 150 | +{ | |
| 151 | + return this->m->p_discard; | |
| 152 | +} | |
| 153 | + | |
| 154 | +void | |
| 155 | +QPDFLogger::setInfo(std::shared_ptr<Pipeline> p) | |
| 156 | +{ | |
| 157 | + if (p == nullptr) { | |
| 158 | + if (this->m->p_save == this->m->p_stdout) { | |
| 159 | + p = this->m->p_stderr; | |
| 160 | + } else { | |
| 161 | + p = this->m->p_stdout; | |
| 162 | + } | |
| 163 | + } | |
| 164 | + this->m->p_info = p; | |
| 165 | +} | |
| 166 | + | |
| 167 | +void | |
| 168 | +QPDFLogger::setWarn(std::shared_ptr<Pipeline> p) | |
| 169 | +{ | |
| 170 | + this->m->p_warn = p; | |
| 171 | +} | |
| 172 | + | |
| 173 | +void | |
| 174 | +QPDFLogger::setError(std::shared_ptr<Pipeline> p) | |
| 175 | +{ | |
| 176 | + if (p == nullptr) { | |
| 177 | + p = this->m->p_stderr; | |
| 178 | + } | |
| 179 | + this->m->p_error = p; | |
| 180 | +} | |
| 181 | + | |
| 182 | +void | |
| 183 | +QPDFLogger::setSave(std::shared_ptr<Pipeline> p) | |
| 184 | +{ | |
| 185 | + if (p == this->m->p_stdout) { | |
| 186 | + auto pt = dynamic_cast<Pl_Track*>(p.get()); | |
| 187 | + if (pt->getUsed()) { | |
| 188 | + throw std::logic_error( | |
| 189 | + "QPDFLogger: called setSave on standard output after standard" | |
| 190 | + " output has already been used"); | |
| 191 | + } | |
| 192 | + if (this->m->p_info == this->m->p_stdout) { | |
| 193 | + this->m->p_info = this->m->p_stderr; | |
| 194 | + } | |
| 195 | + } | |
| 196 | + this->m->p_save = p; | |
| 197 | +} | |
| 198 | + | |
| 199 | +void | |
| 200 | +QPDFLogger::saveToStandardOutput() | |
| 201 | +{ | |
| 202 | + setSave(standardOutput()); | |
| 203 | +} | |
| 204 | + | |
| 205 | +void | |
| 206 | +QPDFLogger::setOutputStreams(std::ostream* out_stream, std::ostream* err_stream) | |
| 207 | +{ | |
| 208 | + if (out_stream == &std::cout) { | |
| 209 | + out_stream = nullptr; | |
| 210 | + } | |
| 211 | + if (err_stream == &std::cerr) { | |
| 212 | + err_stream = nullptr; | |
| 213 | + } | |
| 214 | + std::shared_ptr<Pipeline> new_out; | |
| 215 | + std::shared_ptr<Pipeline> new_err; | |
| 216 | + | |
| 217 | + if (out_stream == nullptr) { | |
| 218 | + if (this->m->p_save == this->m->p_stdout) { | |
| 219 | + new_out = this->m->p_stderr; | |
| 220 | + } else { | |
| 221 | + new_out = this->m->p_stdout; | |
| 222 | + } | |
| 223 | + } else { | |
| 224 | + new_out = std::make_shared<Pl_OStream>("output", *out_stream); | |
| 225 | + } | |
| 226 | + if (err_stream == nullptr) { | |
| 227 | + new_err = this->m->p_stderr; | |
| 228 | + } else { | |
| 229 | + new_err = std::make_shared<Pl_OStream>("error output", *err_stream); | |
| 230 | + } | |
| 231 | + this->m->p_info = new_out; | |
| 232 | + this->m->p_warn = nullptr; | |
| 233 | + this->m->p_error = new_err; | |
| 234 | +} | |
| 235 | + | |
| 236 | +std::shared_ptr<Pipeline> | |
| 237 | +QPDFLogger::throwIfNull(std::shared_ptr<Pipeline> p, bool null_okay) | |
| 238 | +{ | |
| 239 | + if (!(null_okay || p)) { | |
| 240 | + throw std::logic_error( | |
| 241 | + "QPDFLogger: requested a null pipeline without null_okay == true"); | |
| 242 | + } | |
| 243 | + return p; | |
| 244 | +} | ... | ... |
libtests/CMakeLists.txt
libtests/logger.cc
0 → 100644
| 1 | +#include <qpdf/assert_test.h> | |
| 2 | + | |
| 3 | +#include <qpdf/Pl_String.hh> | |
| 4 | +#include <qpdf/QPDFLogger.hh> | |
| 5 | +#include <stdexcept> | |
| 6 | + | |
| 7 | +static void | |
| 8 | +test1() | |
| 9 | +{ | |
| 10 | + // Standard behavior | |
| 11 | + | |
| 12 | + auto logger = QPDFLogger::defaultLogger(); | |
| 13 | + | |
| 14 | + logger->info("info to stdout\n"); | |
| 15 | + logger->warn("warn to stderr\n"); | |
| 16 | + logger->error("error to stderr\n"); | |
| 17 | + assert(logger->getSave(true) == nullptr); | |
| 18 | + try { | |
| 19 | + logger->getSave(); | |
| 20 | + assert(false); | |
| 21 | + } catch (std::logic_error& e) { | |
| 22 | + *(logger->getInfo()) << "getSave exception: " << e.what() << "\n"; | |
| 23 | + } | |
| 24 | + try { | |
| 25 | + logger->saveToStandardOutput(); | |
| 26 | + assert(false); | |
| 27 | + } catch (std::logic_error& e) { | |
| 28 | + *(logger->getInfo()) | |
| 29 | + << "saveToStandardOutput exception: " << e.what() << "\n"; | |
| 30 | + } | |
| 31 | + logger->setWarn(logger->discard()); | |
| 32 | + logger->warn("warning not seen\n"); | |
| 33 | + logger->setWarn(nullptr); | |
| 34 | + logger->warn("restored warning to stderr\n"); | |
| 35 | +} | |
| 36 | + | |
| 37 | +static void | |
| 38 | +test2() | |
| 39 | +{ | |
| 40 | + // First call saveToStandardOutput. Then use info, which then to | |
| 41 | + // go stderr. | |
| 42 | + QPDFLogger l; | |
| 43 | + l.saveToStandardOutput(); | |
| 44 | + l.info(std::string("info to stderr\n")); | |
| 45 | + *(l.getSave()) << "save to stdout\n"; | |
| 46 | + l.setInfo(nullptr); | |
| 47 | + l.info("info still to stderr\n"); | |
| 48 | + l.setSave(nullptr); | |
| 49 | + l.setInfo(nullptr); | |
| 50 | + l.info("info back to stdout\n"); | |
| 51 | +} | |
| 52 | + | |
| 53 | +static void | |
| 54 | +test3() | |
| 55 | +{ | |
| 56 | + // Error/warning | |
| 57 | + QPDFLogger l; | |
| 58 | + | |
| 59 | + // Warning follows error when error is set explicitly. | |
| 60 | + std::string errors; | |
| 61 | + auto pl_error = std::make_shared<Pl_String>("errors", nullptr, errors); | |
| 62 | + l.setError(pl_error); | |
| 63 | + l.warn("warn follows error\n"); | |
| 64 | + assert(errors == "warn follows error\n"); | |
| 65 | + l.error("error too\n"); | |
| 66 | + assert(errors == "warn follows error\nerror too\n"); | |
| 67 | + | |
| 68 | + // Set warnings -- now they're separate | |
| 69 | + std::string warnings; | |
| 70 | + auto pl_warn = std::make_shared<Pl_String>("warnings", nullptr, warnings); | |
| 71 | + l.setWarn(pl_warn); | |
| 72 | + l.warn(std::string("warning now separate\n")); | |
| 73 | + l.error(std::string("new error\n")); | |
| 74 | + assert(warnings == "warning now separate\n"); | |
| 75 | + assert(errors == "warn follows error\nerror too\nnew error\n"); | |
| 76 | + std::string errors2; | |
| 77 | + pl_error = std::make_shared<Pl_String>("errors", nullptr, errors2); | |
| 78 | + l.setError(pl_error); | |
| 79 | + l.warn("new warning\n"); | |
| 80 | + l.error("another new error\n"); | |
| 81 | + assert(warnings == "warning now separate\nnew warning\n"); | |
| 82 | + assert(errors == "warn follows error\nerror too\nnew error\n"); | |
| 83 | + assert(errors2 == "another new error\n"); | |
| 84 | + | |
| 85 | + // Restore warnings to default -- follows error again | |
| 86 | + l.setWarn(nullptr); | |
| 87 | + l.warn("warning 3\n"); | |
| 88 | + l.error("error 3\n"); | |
| 89 | + assert(warnings == "warning now separate\nnew warning\n"); | |
| 90 | + assert(errors == "warn follows error\nerror too\nnew error\n"); | |
| 91 | + assert(errors2 == "another new error\nwarning 3\nerror 3\n"); | |
| 92 | + | |
| 93 | + // Restore everything to default | |
| 94 | + l.setInfo(nullptr); | |
| 95 | + l.setWarn(nullptr); | |
| 96 | + l.setError(nullptr); | |
| 97 | + l.info("after reset, info to stdout\n"); | |
| 98 | + l.warn("after reset, warn to stderr\n"); | |
| 99 | + l.error("after reset, error to stderr\n"); | |
| 100 | +} | |
| 101 | + | |
| 102 | +int | |
| 103 | +main() | |
| 104 | +{ | |
| 105 | + test1(); | |
| 106 | + test2(); | |
| 107 | + test3(); | |
| 108 | + return 0; | |
| 109 | +} | ... | ... |
libtests/qtest/logger.test
0 → 100644
| 1 | +#!/usr/bin/env perl | |
| 2 | +require 5.008; | |
| 3 | +use warnings; | |
| 4 | +use strict; | |
| 5 | + | |
| 6 | +chdir("logger") or die "chdir testdir failed: $!\n"; | |
| 7 | + | |
| 8 | +require TestDriver; | |
| 9 | + | |
| 10 | +my $td = new TestDriver('logger'); | |
| 11 | + | |
| 12 | +cleanup(); | |
| 13 | + | |
| 14 | +$td->runtest("logger", | |
| 15 | + {$td->COMMAND => "logger >stdout 2>stderr"}, | |
| 16 | + {$td->STRING => "", $td->EXIT_STATUS => 0}, | |
| 17 | + $td->NORMALIZE_NEWLINES); | |
| 18 | +$td->runtest("check stdout", | |
| 19 | + {$td->FILE => "stdout"}, | |
| 20 | + {$td->FILE => "exp-stdout"}, | |
| 21 | + $td->NORMALIZE_NEWLINES); | |
| 22 | +$td->runtest("check stderr", | |
| 23 | + {$td->FILE => "stderr"}, | |
| 24 | + {$td->FILE => "exp-stderr"}, | |
| 25 | + $td->NORMALIZE_NEWLINES); | |
| 26 | + | |
| 27 | +cleanup(); | |
| 28 | +$td->report(3); | |
| 29 | + | |
| 30 | +sub cleanup | |
| 31 | +{ | |
| 32 | + unlink "stdout", "stderr"; | |
| 33 | +} | ... | ... |
libtests/qtest/logger/exp-stderr
0 → 100644
libtests/qtest/logger/exp-stdout
0 → 100644
| 1 | +info to stdout | |
| 2 | +getSave exception: QPDFLogger: requested a null pipeline without null_okay == true | |
| 3 | +saveToStandardOutput exception: QPDFLogger: called setSave on standard output after standard output has already been used | |
| 4 | +save to stdout | |
| 5 | +info back to stdout | |
| 6 | +after reset, info to stdout | ... | ... |
qpdf/sizes.cc
| ... | ... | @@ -31,6 +31,7 @@ |
| 31 | 31 | #include <qpdf/QPDFFileSpecObjectHelper.hh> |
| 32 | 32 | #include <qpdf/QPDFFormFieldObjectHelper.hh> |
| 33 | 33 | #include <qpdf/QPDFJob.hh> |
| 34 | +#include <qpdf/QPDFLogger.hh> | |
| 34 | 35 | #include <qpdf/QPDFMatrix.hh> |
| 35 | 36 | #include <qpdf/QPDFNameTreeObjectHelper.hh> |
| 36 | 37 | #include <qpdf/QPDFNumberTreeObjectHelper.hh> |
| ... | ... | @@ -98,6 +99,7 @@ main() |
| 98 | 99 | print_size(QPDFJob::EncConfig); |
| 99 | 100 | print_size(QPDFJob::PagesConfig); |
| 100 | 101 | print_size(QPDFJob::UOConfig); |
| 102 | + print_size(QPDFLogger); | |
| 101 | 103 | print_size(QPDFMatrix); |
| 102 | 104 | print_size(QPDFNameTreeObjectHelper); |
| 103 | 105 | print_size(QPDFNameTreeObjectHelper::iterator); | ... | ... |