Added test worker programs for Java, Python, C; added batch tester in Python.
This commit is contained in:
parent
55c5510057
commit
6c5f8d087b
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
* QR Code generator test worker (C)
|
||||
*
|
||||
* This program reads data and encoding parameters from standard input and writes
|
||||
* QR Code bitmaps to standard output. The I/O format is one integer per line.
|
||||
* Run with no command line arguments. The program is intended for automated
|
||||
* batch testing of end-to-end functionality of this QR Code generator library.
|
||||
*
|
||||
* Copyright (c) Project Nayuki
|
||||
* https://www.nayuki.io/page/qr-code-generator-library
|
||||
*
|
||||
* (MIT License)
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
* - The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
* - The Software is provided "as is", without warranty of any kind, express or
|
||||
* implied, including but not limited to the warranties of merchantability,
|
||||
* fitness for a particular purpose and noninfringement. In no event shall the
|
||||
* authors or copyright holders be liable for any claim, damages or other
|
||||
* liability, whether in an action of contract, tort or otherwise, arising from,
|
||||
* out of or in connection with the Software or the use or other dealings in the
|
||||
* Software.
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "qrcodegen.h"
|
||||
|
||||
|
||||
// The main application program.
|
||||
int main(void) {
|
||||
// Start loop
|
||||
while (true) {
|
||||
|
||||
// Read data length or exit
|
||||
int length;
|
||||
scanf("%d", &length);
|
||||
if (length == -1)
|
||||
break;
|
||||
|
||||
// Read data bytes
|
||||
bool isAscii = true;
|
||||
uint8_t *data = malloc(length * sizeof(uint8_t));
|
||||
if (data == NULL) {
|
||||
perror("malloc");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
for (int i = 0; i < length; i++) {
|
||||
int b;
|
||||
scanf("%d", &b);
|
||||
data[i] = (uint8_t)b;
|
||||
isAscii &= 0 < b && b < 128;
|
||||
}
|
||||
|
||||
// Read encoding parameters
|
||||
int errCorLvl, minVersion, maxVersion, mask, boostEcl;
|
||||
scanf("%d %d %d %d %d", &errCorLvl, &minVersion, &maxVersion, &mask, &boostEcl);
|
||||
|
||||
// Allocate memory for QR Code
|
||||
int bufferLen = qrcodegen_BUFFER_LEN_FOR_VERSION(maxVersion);
|
||||
uint8_t *qrcode = malloc(bufferLen * sizeof(uint8_t));
|
||||
uint8_t *tempBuffer = malloc(bufferLen * sizeof(uint8_t));
|
||||
if (qrcode == NULL || tempBuffer == NULL) {
|
||||
perror("malloc");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// Try to make QR Code symbol
|
||||
int version;
|
||||
if (isAscii) {
|
||||
char *text = malloc((length + 1) * sizeof(char));
|
||||
for (int i = 0; i < length; i++)
|
||||
text[i] = (char)data[i];
|
||||
text[length] = '\0';
|
||||
version = qrcodegen_encodeText(text, tempBuffer, qrcode, (enum qrcodegen_Ecc)errCorLvl,
|
||||
minVersion, maxVersion, (enum qrcodegen_Mask)mask, boostEcl == 1);
|
||||
free(text);
|
||||
} else if (length <= bufferLen) {
|
||||
for (int i = 0; i < length; i++)
|
||||
tempBuffer[i] = data[i];
|
||||
version = qrcodegen_encodeBinary(tempBuffer, (size_t)length, qrcode, (enum qrcodegen_Ecc)errCorLvl,
|
||||
minVersion, maxVersion, (enum qrcodegen_Mask)mask, boostEcl == 1);
|
||||
} else
|
||||
version = 0;
|
||||
free(data);
|
||||
free(tempBuffer);
|
||||
|
||||
// Print grid of modules
|
||||
if (version == 0)
|
||||
printf("-1\n");
|
||||
else {
|
||||
printf("%d\n", version);
|
||||
int size = qrcodegen_getSize(version);
|
||||
for (int y = 0; y < size; y++) {
|
||||
for (int x = 0; x < size; x++)
|
||||
printf("%d\n", qrcodegen_getModule(qrcode, version, x, y) ? 1 : 0);
|
||||
}
|
||||
}
|
||||
free(qrcode);
|
||||
fflush(stdout);
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
|
@ -0,0 +1,104 @@
|
|||
/*
|
||||
* QR Code generator test worker (Java)
|
||||
*
|
||||
* This program reads data and encoding parameters from standard input and writes
|
||||
* QR Code bitmaps to standard output. The I/O format is one integer per line.
|
||||
* Run with no command line arguments. The program is intended for automated
|
||||
* batch testing of end-to-end functionality of this QR Code generator library.
|
||||
*
|
||||
* Copyright (c) Project Nayuki
|
||||
* https://www.nayuki.io/page/qr-code-generator-library
|
||||
*
|
||||
* (MIT License)
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
* - The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
* - The Software is provided "as is", without warranty of any kind, express or
|
||||
* implied, including but not limited to the warranties of merchantability,
|
||||
* fitness for a particular purpose and noninfringement. In no event shall the
|
||||
* authors or copyright holders be liable for any claim, damages or other
|
||||
* liability, whether in an action of contract, tort or otherwise, arising from,
|
||||
* out of or in connection with the Software or the use or other dealings in the
|
||||
* Software.
|
||||
*/
|
||||
|
||||
package io.nayuki.qrcodegen;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Scanner;
|
||||
|
||||
|
||||
public final class QrCodeGeneratorWorker {
|
||||
|
||||
public static void main(String[] args) {
|
||||
// Set up input stream and start loop
|
||||
Scanner input = new Scanner(System.in, "US-ASCII");
|
||||
input.useDelimiter("\r\n|\n|\r");
|
||||
while (true) {
|
||||
|
||||
// Read data length or exit
|
||||
int length = input.nextInt();
|
||||
if (length == -1)
|
||||
break;
|
||||
if (length > Short.MAX_VALUE)
|
||||
throw new RuntimeException();
|
||||
|
||||
// Read data bytes
|
||||
boolean isAscii = true;
|
||||
byte[] data = new byte[length];
|
||||
for (int i = 0; i < data.length; i++) {
|
||||
int b = input.nextInt();
|
||||
if (b < 0 || b > 255)
|
||||
throw new RuntimeException();
|
||||
data[i] = (byte)b;
|
||||
isAscii &= b < 128;
|
||||
}
|
||||
|
||||
// Read encoding parameters
|
||||
int errCorLvl = input.nextInt();
|
||||
int minVersion = input.nextInt();
|
||||
int maxVersion = input.nextInt();
|
||||
int mask = input.nextInt();
|
||||
int boostEcl = input.nextInt();
|
||||
if (!(0 <= errCorLvl && errCorLvl <= 3) || !(-1 <= mask && mask <= 7) || (boostEcl >>> 1) != 0
|
||||
|| !(1 <= minVersion && minVersion <= maxVersion && maxVersion <= 40))
|
||||
throw new RuntimeException();
|
||||
|
||||
// Make segments for encoding
|
||||
List<QrSegment> segs;
|
||||
if (isAscii)
|
||||
segs = QrSegment.makeSegments(new String(data, StandardCharsets.US_ASCII));
|
||||
else
|
||||
segs = Arrays.asList(QrSegment.makeBytes(data));
|
||||
|
||||
// Try to make QR Code symbol
|
||||
QrCode qr;
|
||||
try {
|
||||
qr = QrCode.encodeSegments(segs, QrCode.Ecc.values()[errCorLvl], minVersion, maxVersion, mask, boostEcl != 0);
|
||||
} catch (IllegalArgumentException e) {
|
||||
if (e.getMessage().equals("Data too long")) {
|
||||
System.out.println(-1);
|
||||
System.out.flush();
|
||||
continue;
|
||||
} else
|
||||
throw e;
|
||||
}
|
||||
|
||||
// Print grid of modules
|
||||
System.out.println(qr.version);
|
||||
for (int y = 0; y < qr.size; y++) {
|
||||
for (int x = 0; x < qr.size; x++)
|
||||
System.out.println(qr.getModule(x, y));
|
||||
}
|
||||
System.out.flush();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,115 @@
|
|||
#
|
||||
# QR Code generator batch test (Python 3)
|
||||
#
|
||||
# Runs various versions of the QR Code generator test worker as subprocesses,
|
||||
# feeds each one the same random input, and compares their output for equality.
|
||||
#
|
||||
# Copyright (c) Project Nayuki
|
||||
# https://www.nayuki.io/page/qr-code-generator-library
|
||||
#
|
||||
# (MIT License)
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
# this software and associated documentation files (the "Software"), to deal in
|
||||
# the Software without restriction, including without limitation the rights to
|
||||
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
# the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
# subject to the following conditions:
|
||||
# - The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
# - The Software is provided "as is", without warranty of any kind, express or
|
||||
# implied, including but not limited to the warranties of merchantability,
|
||||
# fitness for a particular purpose and noninfringement. In no event shall the
|
||||
# authors or copyright holders be liable for any claim, damages or other
|
||||
# liability, whether in an action of contract, tort or otherwise, arising from,
|
||||
# out of or in connection with the Software or the use or other dealings in the
|
||||
# Software.
|
||||
#
|
||||
|
||||
from __future__ import print_function
|
||||
import itertools, random, subprocess, sys
|
||||
if sys.version_info.major < 3:
|
||||
raise RuntimeError("Requires Python 3+")
|
||||
|
||||
|
||||
CHILD_PROGRAMS = [
|
||||
["python", "qrcodegen-worker.py"],
|
||||
["java", "io/nayuki/qrcodegen/QrCodeGeneratorWorker"],
|
||||
["./qrcodegen-worker"],
|
||||
]
|
||||
|
||||
|
||||
def main():
|
||||
global subprocs
|
||||
subprocs = [subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, universal_newlines=True) for args in CHILD_PROGRAMS]
|
||||
for i in itertools.count():
|
||||
print("Trial {}: ".format(i), end="")
|
||||
do_trial()
|
||||
print()
|
||||
|
||||
|
||||
def do_trial():
|
||||
mode = random.randrange(4)
|
||||
if mode == 0: # Numeric
|
||||
length = max(round((2 * 7089) ** random.random()), 1)
|
||||
data = [random.randrange(48, 58) for _ in range(length)]
|
||||
elif mode == 1: # Alphanumeric
|
||||
length = max(round((2 * 4296) ** random.random()), 1)
|
||||
data = [ord(random.choice("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:")) for _ in range(length)]
|
||||
elif mode == 2: # ASCII
|
||||
length = max(round((2 * 2953) ** random.random()), 1)
|
||||
data = [random.randrange(128) for _ in range(length)]
|
||||
elif mode == 3: # Byte
|
||||
length = max(round((2 * 2953) ** random.random()), 1)
|
||||
data = [random.randrange(256) for _ in range(length)]
|
||||
else:
|
||||
raise AssertionError()
|
||||
|
||||
write_all(length)
|
||||
for b in data:
|
||||
write_all(b)
|
||||
|
||||
errcorlvl = random.randrange(4)
|
||||
minversion = random.randint(1, 40)
|
||||
maxversion = random.randint(1, 40)
|
||||
if minversion > maxversion:
|
||||
minversion, maxversion = maxversion, minversion
|
||||
mask = -1
|
||||
if random.random() < 0.5:
|
||||
mask = random.randrange(8)
|
||||
boostecl = int(random.random() < 0.2)
|
||||
print("mode={} len={} ecl={} minv={} maxv={} mask={} boost={}".format(mode, length, errcorlvl, minversion, maxversion, mask, boostecl), end="")
|
||||
|
||||
write_all(errcorlvl)
|
||||
write_all(minversion)
|
||||
write_all(maxversion)
|
||||
write_all(mask)
|
||||
write_all(boostecl)
|
||||
flush_all()
|
||||
|
||||
version = read_verify()
|
||||
print(" version={}".format(version), end="")
|
||||
if version == -1:
|
||||
return
|
||||
size = version * 4 + 17
|
||||
for _ in range(size**2):
|
||||
read_verify()
|
||||
|
||||
|
||||
def write_all(val):
|
||||
for proc in subprocs:
|
||||
print(val, file=proc.stdin)
|
||||
|
||||
def flush_all():
|
||||
for proc in subprocs:
|
||||
proc.stdin.flush()
|
||||
|
||||
def read_verify():
|
||||
val = subprocs[0].stdout.readline().rstrip("\r\n")
|
||||
for proc in subprocs[1 : ]:
|
||||
if proc.stdout.readline().rstrip("\r\n") != val:
|
||||
raise ValueError("Mismatch")
|
||||
return int(val)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
|
@ -0,0 +1,93 @@
|
|||
#
|
||||
# QR Code generator test worker (Python 2, 3)
|
||||
#
|
||||
# This program reads data and encoding parameters from standard input and writes
|
||||
# QR Code bitmaps to standard output. The I/O format is one integer per line.
|
||||
# Run with no command line arguments. The program is intended for automated
|
||||
# batch testing of end-to-end functionality of this QR Code generator library.
|
||||
#
|
||||
# Copyright (c) Project Nayuki
|
||||
# https://www.nayuki.io/page/qr-code-generator-library
|
||||
#
|
||||
# (MIT License)
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
# this software and associated documentation files (the "Software"), to deal in
|
||||
# the Software without restriction, including without limitation the rights to
|
||||
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
# the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
# subject to the following conditions:
|
||||
# - The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
# - The Software is provided "as is", without warranty of any kind, express or
|
||||
# implied, including but not limited to the warranties of merchantability,
|
||||
# fitness for a particular purpose and noninfringement. In no event shall the
|
||||
# authors or copyright holders be liable for any claim, damages or other
|
||||
# liability, whether in an action of contract, tort or otherwise, arising from,
|
||||
# out of or in connection with the Software or the use or other dealings in the
|
||||
# Software.
|
||||
#
|
||||
|
||||
from __future__ import print_function
|
||||
import sys
|
||||
import qrcodegen
|
||||
py3 = sys.version_info.major >= 3
|
||||
|
||||
|
||||
def read_int():
|
||||
return int((input if py3 else raw_input)())
|
||||
|
||||
|
||||
def main():
|
||||
# Start loop
|
||||
while True:
|
||||
|
||||
# Read data or exit
|
||||
length = read_int()
|
||||
if length == -1:
|
||||
break
|
||||
data = [read_int() for _ in range(length)]
|
||||
|
||||
# Read encoding parameters
|
||||
errcorlvl = read_int()
|
||||
minversion = read_int()
|
||||
maxversion = read_int()
|
||||
mask = read_int()
|
||||
boostecl = read_int()
|
||||
|
||||
# Make segments for encoding
|
||||
if all((b < 128) for b in data): # Is ASCII
|
||||
segs = qrcodegen.QrSegment.make_segments("".join(chr(b) for b in data))
|
||||
elif py3:
|
||||
segs = [qrcodegen.QrSegment.make_bytes(bytes(data))]
|
||||
else:
|
||||
segs = [qrcodegen.QrSegment.make_bytes("".join(chr(b) for b in data))]
|
||||
|
||||
# Try to make QR Code symbol
|
||||
try:
|
||||
qr = qrcodegen.QrCode.encode_segments(segs, ECC_LEVELS[errcorlvl], minversion, maxversion, mask, boostecl != 0)
|
||||
except ValueError as e:
|
||||
if e.args[0] == "Data too long":
|
||||
print(-1)
|
||||
sys.stdout.flush()
|
||||
continue
|
||||
else:
|
||||
raise
|
||||
|
||||
# Print grid of modules
|
||||
print(qr.get_version())
|
||||
for y in range(qr.get_size()):
|
||||
for x in range(qr.get_size()):
|
||||
print(qr.get_module(x, y))
|
||||
sys.stdout.flush()
|
||||
|
||||
|
||||
ECC_LEVELS = (
|
||||
qrcodegen.QrCode.Ecc.LOW,
|
||||
qrcodegen.QrCode.Ecc.MEDIUM,
|
||||
qrcodegen.QrCode.Ecc.QUARTILE,
|
||||
qrcodegen.QrCode.Ecc.HIGH,
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
Loading…
Reference in New Issue