| /** @file |
| Licensed to the Apache Software Foundation (ASF) under one |
| or more contributor license agreements. See the NOTICE file |
| distributed with this work for additional information |
| regarding copyright ownership. The ASF licenses this file |
| to you under the Apache License, Version 2.0 (the |
| "License"); you may not use this file except in compliance |
| with the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| */ |
| |
| /* |
| * These are misc unit tests for slicer |
| */ |
| |
| #include "ContentRange.h" |
| #include "Range.h" |
| |
| #include <cassert> |
| #include <iostream> |
| #include <limits> |
| #include <sstream> |
| #include <vector> |
| |
| std::string |
| testContentRange() |
| { |
| std::ostringstream oss; |
| |
| ContentRange null; |
| if (null.isValid()) { |
| oss << "fail: null isValid test" << std::endl; |
| } |
| |
| ContentRange const exprange(1023, 1048576, 307232768); |
| |
| if (!exprange.isValid()) { |
| oss << "Fail: exprange valid" << std::endl; |
| oss << exprange.m_beg << ' ' << exprange.m_end << ' ' << exprange.m_length << std::endl; |
| } |
| |
| std::string const expstr("bytes 1023-1048575/307232768"); |
| |
| char gotbuf[1024]; |
| int gotlen = sizeof(gotbuf); |
| |
| bool const strstat(exprange.toStringClosed(gotbuf, &gotlen)); |
| |
| if (!strstat) { |
| oss << "failure status toStringClosed" << std::endl; |
| } else if ((int)expstr.size() != gotlen) { |
| oss << "Fail: expected toStringClosed length" << std::endl; |
| oss << "got: " << gotlen << " exp: " << expstr.size() << std::endl; |
| oss << "Got: " << gotbuf << std::endl; |
| oss << "Exp: " << expstr << std::endl; |
| } else if (expstr != gotbuf) { |
| oss << "Fail: expected toStringClosed value" << std::endl; |
| oss << "Got: " << gotbuf << std::endl; |
| oss << "Exp: " << expstr << std::endl; |
| } |
| |
| ContentRange gotrange; |
| bool const gotstat(gotrange.fromStringClosed(expstr.c_str())); |
| if (!gotstat) { |
| oss << "fail: gotstat from string" << std::endl; |
| } else if (gotrange.m_beg != exprange.m_beg || gotrange.m_end != exprange.m_end || gotrange.m_length != exprange.m_length) { |
| oss << "fail: value compare gotrange and exprange" << std::endl; |
| } |
| |
| std::string const teststr("bytes 0-1048575/30723276"); |
| if (!gotrange.fromStringClosed(teststr.c_str())) { |
| oss << "fail: parse teststr" << std::endl; |
| } |
| |
| return oss.str(); |
| } |
| |
| std::string |
| testParseRange() |
| { |
| std::ostringstream oss; |
| |
| std::vector<std::string> const teststrings = { |
| "bytes=0-1023", |
| "bytes=1-1024", |
| "bytes=11-11", |
| "bytes=1-" // 2nd byte to end |
| , |
| "Range: bytes=-13" // final 13 bytes |
| , |
| "bytes=3-17" // ,23-29" // open |
| , |
| "bytes=3 -17 " //,18-29" // adjacent |
| , |
| "bytes=3- 17" //, 11-29" // overlapping |
| , |
| "bytes=3 - 11" //,13-17 , 23-29" // unsorted triplet |
| , |
| "bytes=3-11 " //,13-17, 23-29" // unsorted triplet |
| , |
| "bytes=0-0" //,-1" // first and last bytes |
| , |
| "bytes=-20" // last 20 bytes of file |
| |
| , |
| "bytes=-60-50" // invalid fully negative |
| , |
| "bytes=17-13" // degenerate |
| , |
| "bytes 0-1023/146515" // this should be rejected (Content-range) |
| }; // invalid |
| |
| std::vector<Range> const exps = { |
| Range{0, 1023 + 1 }, |
| Range{1, 1024 + 1 }, |
| Range{11, 11 + 1 }, |
| Range{1, Range::maxval}, |
| Range{-1, -1 }, |
| Range{3, 17 + 1 }, |
| Range{3, 17 + 1 }, |
| Range{3, 17 + 1 }, |
| Range{3, 11 + 1 }, |
| Range{3, 11 + 1 }, |
| Range{0, 1 }, |
| Range{-20, 0 }, |
| Range{-1, -1 }, |
| Range{-1, -1 }, |
| Range{-1, -1 } |
| }; |
| |
| std::vector<bool> const expsres = {true, true, true, true, false, true, true, true, true, true, true, true, false, false, false}; |
| |
| assert(exps.size() == teststrings.size()); |
| |
| std::vector<Range> gots; |
| gots.reserve(exps.size()); |
| std::vector<bool> gotsres; |
| |
| for (std::string const &str : teststrings) { |
| Range rng; |
| gotsres.push_back(rng.fromStringClosed(str.c_str())); |
| gots.push_back(rng); |
| } |
| |
| assert(gots.size() == exps.size()); |
| |
| for (size_t index(0); index < gots.size(); ++index) { |
| if (exps[index] != gots[index] || expsres[index] != gotsres[index]) { |
| oss << "Error parsing index: " << index << std::endl; |
| oss << "test: '" << teststrings[index] << "'" << std::endl; |
| oss << "exp: " << exps[index].m_beg << ' ' << exps[index].m_end << std::endl; |
| oss << "expsres: " << (int)expsres[index] << std::endl; |
| oss << "got: " << gots[index].m_beg << ' ' << gots[index].m_end << std::endl; |
| oss << "gotsres: " << (int)gotsres[index] << std::endl; |
| } |
| } |
| |
| return oss.str(); |
| } |
| |
| struct Tests { |
| using TestFunc = std::string (*)(); |
| std::vector<std::pair<TestFunc, char const *>> funcs; |
| |
| void |
| add(TestFunc const &func, char const *const fname) |
| { |
| funcs.push_back(std::make_pair(func, fname)); |
| } |
| |
| int |
| run() const |
| { |
| int numfailed(0); |
| for (std::pair<TestFunc, char const *> const &namefunc : funcs) { |
| TestFunc const &func = namefunc.first; |
| char const *const name = namefunc.second; |
| |
| std::cerr << name << " : "; |
| |
| std::string const fres(func()); |
| if (fres.empty()) { |
| std::cerr << "pass" << std::endl; |
| } else { |
| std::cerr << "FAIL" << std::endl; |
| std::cerr << fres << std::endl; |
| ++numfailed; |
| } |
| } |
| return numfailed; |
| } |
| }; |
| |
| int |
| main() |
| { |
| Tests tests; |
| tests.add(testContentRange, "testContentRange"); |
| tests.add(testParseRange, "testParseRange"); |
| return tests.run(); |
| } |