feat: metamorphic test and partial verification
This commit is contained in:
		
							parent
							
								
									b2fac0ffd3
								
							
						
					
					
						commit
						4b09788441
					
				@ -4,12 +4,15 @@
 | 
				
			|||||||
 Possible references include:
 | 
					 Possible references include:
 | 
				
			||||||
https://stackoverflow.com/a/7304184 - custom delimeter for istream
 | 
					https://stackoverflow.com/a/7304184 - custom delimeter for istream
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					#include "lib_random.h"
 | 
				
			||||||
 | 
					#include <cassert>
 | 
				
			||||||
#include <fstream>
 | 
					#include <fstream>
 | 
				
			||||||
#include <iostream>
 | 
					#include <iostream>
 | 
				
			||||||
#include <locale>
 | 
					#include <locale>
 | 
				
			||||||
#include <sstream>
 | 
					#include <sstream>
 | 
				
			||||||
#include <string>
 | 
					#include <string>
 | 
				
			||||||
#include <unordered_map>
 | 
					#include <unordered_map>
 | 
				
			||||||
 | 
					#include <unordered_set>
 | 
				
			||||||
#include <vector>
 | 
					#include <vector>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct semicolon_is_space : std::ctype<char> {
 | 
					struct semicolon_is_space : std::ctype<char> {
 | 
				
			||||||
@ -25,8 +28,8 @@ struct semicolon_is_space : std::ctype<char> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
class input {
 | 
					class input {
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
  std::string s;
 | 
					  std::string s = "";
 | 
				
			||||||
  unsigned long k;
 | 
					  unsigned long k = 1;
 | 
				
			||||||
  friend std::istream &operator>>(std::istream &in, input &i);
 | 
					  friend std::istream &operator>>(std::istream &in, input &i);
 | 
				
			||||||
  friend std::ostream &operator<<(std::ostream &out, const input &i);
 | 
					  friend std::ostream &operator<<(std::ostream &out, const input &i);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
@ -121,7 +124,34 @@ result find(const std::string &s, const unsigned long k) {
 | 
				
			|||||||
  return r;
 | 
					  return r;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void test(const test_case &t) {
 | 
				
			||||||
 | 
					  std::cout << t;
 | 
				
			||||||
 | 
					  if (find(t.i.s, t.i.k) == t.r) {
 | 
				
			||||||
 | 
					    std::cout << "Test case with string \"" << t.i.s << "\" and k=" << t.i.k
 | 
				
			||||||
 | 
					              << " passed.\n";
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
 | 
					    std::cout << std::flush;
 | 
				
			||||||
 | 
					    std::cerr << "TEST CASE WITH STRING \"" << t.i.s << "\" AND k=" << t.i.k
 | 
				
			||||||
 | 
					              << " FAILED.\n";
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  std::cout << "\n";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool K_verify(const test_case &t) {
 | 
				
			||||||
 | 
					  // Verifies if found solution has exactly K unique characters (one of the
 | 
				
			||||||
 | 
					  // problem requirement)
 | 
				
			||||||
 | 
					  if (!t.r.match_found)
 | 
				
			||||||
 | 
					    return true; // Do not check if no match found
 | 
				
			||||||
 | 
					  std::unordered_set<char> unique_chars;
 | 
				
			||||||
 | 
					  for (const char c : t.i.s.substr(t.r.longest_start,
 | 
				
			||||||
 | 
					                                   t.r.longest_end - t.r.longest_start + 1)) {
 | 
				
			||||||
 | 
					    unique_chars.insert(c);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  return unique_chars.size() == t.i.k;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int main(int argc, char *argv[]) {
 | 
					int main(int argc, char *argv[]) {
 | 
				
			||||||
 | 
					  std::cout << "Processing static test cases from input file (if any)\n";
 | 
				
			||||||
  semicolon_is_space delimeter;
 | 
					  semicolon_is_space delimeter;
 | 
				
			||||||
  for (int i = 1; i < argc; i++) {
 | 
					  for (int i = 1; i < argc; i++) {
 | 
				
			||||||
    std::ifstream f(argv[i]);
 | 
					    std::ifstream f(argv[i]);
 | 
				
			||||||
@ -130,16 +160,43 @@ int main(int argc, char *argv[]) {
 | 
				
			|||||||
      test_case t;
 | 
					      test_case t;
 | 
				
			||||||
      f >> t;
 | 
					      f >> t;
 | 
				
			||||||
      if (t.i.s.length()) { // skip empty line/string inputs
 | 
					      if (t.i.s.length()) { // skip empty line/string inputs
 | 
				
			||||||
        std::cout << t;
 | 
					        test(t);
 | 
				
			||||||
        if (find(t.i.s, t.i.k) == t.r) {
 | 
					 | 
				
			||||||
          std::cout << "Test case with string \"" << t.i.s
 | 
					 | 
				
			||||||
                    << "\" and k=" << t.i.k << " passed.\n";
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
          std::cout << std::flush;
 | 
					 | 
				
			||||||
          std::cerr << "TEST CASE WITH STRING \"" << t.i.s
 | 
					 | 
				
			||||||
                    << "\" AND k=" << t.i.k << " FAILED.\n";
 | 
					 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
        std::cout << "\n";
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::cout
 | 
				
			||||||
 | 
					        << "\n\n\nPerforming metamorphic tests from randomly generated input "
 | 
				
			||||||
 | 
					           "(string and K values)"
 | 
				
			||||||
 | 
					        << std::endl;
 | 
				
			||||||
 | 
					    random_number_generator<unsigned int> random_ascii_char(97, 122); // a-z
 | 
				
			||||||
 | 
					    random_number_generator<unsigned int> rng;
 | 
				
			||||||
 | 
					    for (unsigned int i = 0; i < 1; i++) {
 | 
				
			||||||
 | 
					      test_case t;
 | 
				
			||||||
 | 
					      t.i.s += (char)random_ascii_char();
 | 
				
			||||||
 | 
					      std::cout << t;
 | 
				
			||||||
 | 
					      t.r = find(t.i.s, t.i.k);
 | 
				
			||||||
 | 
					      for (unsigned int j = 0; j < 10; j++) {
 | 
				
			||||||
 | 
					        for (unsigned int k = 0, increase_str_len_by = rng(100, 1000);
 | 
				
			||||||
 | 
					             k < increase_str_len_by; k++) {
 | 
				
			||||||
 | 
					          t.i.s += (char)random_ascii_char();
 | 
				
			||||||
 | 
					          std::cout << t;
 | 
				
			||||||
 | 
					          result r = find(t.i.s, t.i.k);
 | 
				
			||||||
 | 
					          if (r.match_found && t.r.match_found)
 | 
				
			||||||
 | 
					            assert(r.longest_end - r.longest_start >=
 | 
				
			||||||
 | 
					                   t.r.longest_end - t.r.longest_start);
 | 
				
			||||||
 | 
					          t.r = r;
 | 
				
			||||||
 | 
					          assert(K_verify(t));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        while (t.r.match_found) {
 | 
				
			||||||
 | 
					          std::cout << t;
 | 
				
			||||||
 | 
					          result r = find(t.i.s, ++t.i.k);
 | 
				
			||||||
 | 
					          if (r.match_found)
 | 
				
			||||||
 | 
					            assert(r.longest_end - r.longest_start >=
 | 
				
			||||||
 | 
					                   t.r.longest_end - t.r.longest_start);
 | 
				
			||||||
 | 
					          t.r = r;
 | 
				
			||||||
 | 
					          assert(K_verify(t));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        t.i.k = rng(1, --t.i.k);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user