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