diff --git a/backend/brother_mfp/brother_mfp-encoder.cpp b/backend/brother_mfp/brother_mfp-encoder.cpp index 9d7e1ed6f..e6ccf3d56 100644 --- a/backend/brother_mfp/brother_mfp-encoder.cpp +++ b/backend/brother_mfp/brother_mfp-encoder.cpp @@ -35,6 +35,9 @@ #include #include +#include +#include + #include "../include/sane/sane.h" #include "../include/sane/sanei.h" #include "../include/sane/saneopts.h" @@ -189,7 +192,7 @@ DecodeStatus BrotherEncoderFamily2::EncodeQueryBlock (SANE_Byte *data, size_t da if (*length > data_len) { DBG (DBG_SERIOUS, - "BrotherEncoderFamily2::EncodeBasicParameterBlock: query block too long for buffer: %zu\n", + "BrotherEncoderFamily2::EncodeQueryBlock: query block too long for buffer: %zu\n", *length); return DECODE_STATUS_INVAL; } @@ -210,7 +213,7 @@ DecodeStatus BrotherEncoderFamily2::DecodeQueryBlockResp (const SANE_Byte *data, { DBG (DBG_SERIOUS, - "BrotherEncoderFamily2::DecodeSessionResp: invalid query response block: len = %zu\n", + "BrotherEncoderFamily2::DecodeQueryBlockResp: invalid query response block: len = %zu\n", data_len); return DECODE_STATUS_ERROR; @@ -232,7 +235,7 @@ DecodeStatus BrotherEncoderFamily2::EncodeSourceStatusBlock (SANE_Byte *data, si if (*length > data_len) { DBG (DBG_SERIOUS, - "BrotherEncoderFamily2::EncodeBasicParameterBlock: source status too long for buffer: %zu\n", + "BrotherEncoderFamily2::EncodeSourceStatusBlock: source status too long for buffer: %zu\n", *length); return DECODE_STATUS_INVAL; } @@ -301,7 +304,7 @@ DecodeStatus BrotherEncoderFamily2::DecodeSourceSelectBlockResp (const SANE_Byte if (data_len != 1) { DBG (DBG_SERIOUS, - "BrotherEncoderFamily2::DecodeSourceStatusBlockResp: source select response invalid: %zu\n", + "BrotherEncoderFamily2::DecodeSourceSelectBlockResp: source select response invalid: %zu\n", data_len); return DECODE_STATUS_ERROR; } @@ -619,11 +622,11 @@ DecodeStatus BrotherEncoderFamily2::DecodeScanData (const SANE_Byte *src_data, s } ret_status = colour_decoder.DecodeScanData (src_data, - in_len, - &bytes_consumed, - dest_data, - dest_data_len, - &bytes_written); + in_len, + &bytes_consumed, + dest_data, + dest_data_len, + &bytes_written); } else if (current_header.block_type == BROTHER_DATA_BLOCK_JPEG) { @@ -633,11 +636,11 @@ DecodeStatus BrotherEncoderFamily2::DecodeScanData (const SANE_Byte *src_data, s } ret_status = jfif_decoder.DecodeScanData (src_data, - in_len, - &bytes_consumed, - dest_data, - dest_data_len, - &bytes_written); + in_len, + &bytes_consumed, + dest_data, + dest_data_len, + &bytes_written); } else if (current_header.block_type == BROTHER_DATA_BLOCK_GRAY_RLENGTH) { @@ -647,11 +650,11 @@ DecodeStatus BrotherEncoderFamily2::DecodeScanData (const SANE_Byte *src_data, s } ret_status = gray_decoder.DecodeScanData (src_data, - in_len, - &bytes_consumed, - dest_data, - dest_data_len, - &bytes_written); + in_len, + &bytes_consumed, + dest_data, + dest_data_len, + &bytes_written); } else if (current_header.block_type == BROTHER_DATA_BLOCK_GRAY_RAW) { @@ -661,11 +664,11 @@ DecodeStatus BrotherEncoderFamily2::DecodeScanData (const SANE_Byte *src_data, s } ret_status = gray_raw_decoder.DecodeScanData (src_data, - in_len, - &bytes_consumed, - dest_data, - dest_data_len, - &bytes_written); + in_len, + &bytes_consumed, + dest_data, + dest_data_len, + &bytes_written); } else { @@ -719,11 +722,8 @@ DecodeStatus BrotherEncoderFamily2::DecodeScanData (const SANE_Byte *src_data, s } } -// if (ret_status == DECODE_STATUS_GOOD) -// { - *src_data_consumed = orig_src_data_len - src_data_len; - *dest_data_written = orig_dest_data_len - dest_data_len; -// } + *src_data_consumed = orig_src_data_len - src_data_len; + *dest_data_written = orig_dest_data_len - dest_data_len; return ret_status; } @@ -915,7 +915,7 @@ DecodeStatus BrotherEncoderFamily3::EncodeSourceStatusBlock (SANE_Byte *data, si } DecodeStatus BrotherEncoderFamily3::DecodeSourceStatusBlockResp (const SANE_Byte *data, size_t data_len, - BrotherSourceStatusResponse &response) + BrotherSourceStatusResponse &response) { if (data_len != 1) { @@ -1080,7 +1080,7 @@ DecodeStatus BrotherEncoderFamily3::EncodeBasicParameterBlock (SANE_Byte *data, DecodeStatus BrotherEncoderFamily3::DecodeBasicParameterBlockResp (const SANE_Byte *data, size_t data_len, - BrotherBasicParamResponse &response) + BrotherBasicParamResponse &response) { /* * TODO: Decode this block. @@ -1095,7 +1095,7 @@ DecodeStatus BrotherEncoderFamily3::DecodeBasicParameterBlockResp (const SANE_By } DecodeStatus BrotherEncoderFamily3::EncodeParameterBlockBlank (SANE_Byte *data, size_t data_len, - size_t *length) + size_t *length) { const char *mode_text = ScanModeToText (scan_params.param_scan_mode); if (nullptr == mode_text) @@ -2510,7 +2510,6 @@ DecodeStatus BrotherInterleavedRGBColourDecoder::DecodeScanData (const SANE_Byte return DECODE_STATUS_GOOD; } - #include #include diff --git a/backend/brother_mfp/brother_mfp-encoder.h b/backend/brother_mfp/brother_mfp-encoder.h index 70d030eab..adec3be8b 100644 --- a/backend/brother_mfp/brother_mfp-encoder.h +++ b/backend/brother_mfp/brother_mfp-encoder.h @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -163,7 +164,6 @@ struct BrotherSourceStatusResponse }; - /* * DecodeStatus * @@ -312,9 +312,6 @@ protected: BrotherParameters scan_params; }; -#include - - class BrotherJFIFDecoder { public: @@ -367,8 +364,8 @@ private: static void TermSource(j_decompress_ptr cinfo); DecodeStatus DecodeScanData_CompressBuffer (const SANE_Byte *src_data, size_t src_data_len, - size_t *src_data_consumed, SANE_Byte *dst_data, size_t dest_data_len, - size_t *dest_data_written); + size_t *src_data_consumed, SANE_Byte *dst_data, + size_t dest_data_len, size_t *dest_data_written); struct CompressionState { @@ -434,8 +431,8 @@ public: CHANNELS_CrYCb // YCrCb }; private: - void ConvertYCbCrToRGB (SANE_Byte y, SANE_Byte cb, SANE_Byte cr, SANE_Byte *red, SANE_Byte *green, - SANE_Byte *blue); + static void ConvertYCbCrToRGB (SANE_Byte y, SANE_Byte cb, SANE_Byte cr, SANE_Byte *red, + SANE_Byte *green, SANE_Byte *blue); BrotherParameters decode_params; SANE_Word capabilities; diff --git a/backend/brother_mfp/brother_mfp.cpp b/backend/brother_mfp/brother_mfp.cpp index 46b831e6b..af2196cc4 100644 --- a/backend/brother_mfp/brother_mfp.cpp +++ b/backend/brother_mfp/brother_mfp.cpp @@ -850,6 +850,8 @@ sane_exit (void) if (devlist) free (devlist); + sanei_usb_exit(); + return; } diff --git a/testsuite/backend/brother_mfp/Makefile.am b/testsuite/backend/brother_mfp/Makefile.am index c3e139e20..e72d83a62 100644 --- a/testsuite/backend/brother_mfp/Makefile.am +++ b/testsuite/backend/brother_mfp/Makefile.am @@ -23,7 +23,11 @@ brother_mfp_unit_tests_SOURCES = \ brother_mfp_tests.cpp \ brother_mfp_tests.h \ brother_mfp_tests_family4.cpp \ + brother_mfp_tests_family3.cpp \ + brother_mfp_tests_family2.cpp \ brother_mfp_tests_gray_rlength.cpp \ + brother_mfp_tests_colour_int_rgb.cpp \ + brother_mfp_tests_colour_jpeg.cpp \ ../genesys/minigtest.cpp brother_mfp_unit_tests_LDADD = $(TEST_LDADD) diff --git a/testsuite/backend/brother_mfp/brother_mfp_tests.cpp b/testsuite/backend/brother_mfp/brother_mfp_tests.cpp index 029441e99..123d57562 100644 --- a/testsuite/backend/brother_mfp/brother_mfp_tests.cpp +++ b/testsuite/backend/brother_mfp/brother_mfp_tests.cpp @@ -29,6 +29,11 @@ int main () DBG_INIT (); test_family4 (); + test_family3 (); + test_family2 (); test_gray_rlength (); + test_colour_int_rgb(); + test_colour_jpeg(); + return finish_tests (); } diff --git a/testsuite/backend/brother_mfp/brother_mfp_tests.h b/testsuite/backend/brother_mfp/brother_mfp_tests.h index a3f46c6ae..b3af0a566 100644 --- a/testsuite/backend/brother_mfp/brother_mfp_tests.h +++ b/testsuite/backend/brother_mfp/brother_mfp_tests.h @@ -21,4 +21,8 @@ #pragma once extern void test_family4(); +extern void test_family3(); +extern void test_family2(); extern void test_gray_rlength(); +extern void test_colour_int_rgb(); +extern void test_colour_jpeg(); diff --git a/testsuite/backend/brother_mfp/brother_mfp_tests_colour_int_rgb.cpp b/testsuite/backend/brother_mfp/brother_mfp_tests_colour_int_rgb.cpp new file mode 100644 index 000000000..931b5830d --- /dev/null +++ b/testsuite/backend/brother_mfp/brother_mfp_tests_colour_int_rgb.cpp @@ -0,0 +1,170 @@ +/* sane - Scanner Access Now Easy. + + Copyright (C) 2022 Ralph Little + + This file is part of the SANE package. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#define DEBUG_DECLARE_ONLY + +#include "../../include/sane/sanei_debug.h" +#include "brother_mfp_tests.h" +#include "../../backend/brother_mfp/brother_mfp-encoder.h" +#include "../genesys/minigtest.h" + +/* + * TEST: BrotherInterleavedRGBColourDecoder() + * + */ +static void test_colour_int_rgb_enc_rgb() +{ + BrotherInterleavedRGBColourDecoder decoder(CAP_MODE_COLOUR); + const SANE_Byte *src_data; + SANE_Byte dest_data[1024]; + DecodeStatus res_code; + size_t src_data_consumed; + size_t dest_data_written; + + /* + * Normal decode. + * + */ + BrotherParameters params; + params.param_pixel_x_width = 6; + + decoder.NewPage(params); + src_data = (const SANE_Byte *)"123456"; + + res_code = decoder.DecodeScanData (src_data, + strlen((const char *)src_data), + &src_data_consumed, + dest_data, + sizeof(dest_data), + &dest_data_written); + + ASSERT_EQ(res_code, DECODE_STATUS_GOOD); + ASSERT_EQ(src_data_consumed, (size_t)6); + ASSERT_EQ(dest_data_written, (size_t)0); + + decoder.NewBlock(); + src_data = (const SANE_Byte *)"ABCDEF"; + + res_code = decoder.DecodeScanData (src_data, + strlen((const char *)src_data), + &src_data_consumed, + dest_data, + sizeof(dest_data), + &dest_data_written); + + ASSERT_EQ(res_code, DECODE_STATUS_GOOD); + ASSERT_EQ(src_data_consumed, (size_t)6); + ASSERT_EQ(dest_data_written, (size_t)0); + + decoder.NewBlock(); + src_data = (const SANE_Byte *)"MNOPQR"; + + res_code = decoder.DecodeScanData (src_data, + strlen((const char *)src_data), + &src_data_consumed, + dest_data, + sizeof(dest_data), + &dest_data_written); + + ASSERT_EQ(res_code, DECODE_STATUS_GOOD); + ASSERT_EQ(src_data_consumed, (size_t)6); + ASSERT_EQ(dest_data_written, (size_t)18); + + ASSERT_EQ(memcmp(dest_data, "1AM2BN3CO4DP5EQ6FR", 18), 0); +} + + + +static void test_colour_int_rgb_enc_ycrcb() +{ + BrotherInterleavedRGBColourDecoder decoder(CAP_MODE_COLOUR | CAP_ENCODING_RAW_IS_CrYCb); + const SANE_Byte *src_data; + SANE_Byte dest_data[1024]; + DecodeStatus res_code; + size_t src_data_consumed; + size_t dest_data_written; + + /* + * Normal decode. + * + */ + BrotherParameters params; + params.param_pixel_x_width = 7; + + decoder.NewPage(params); + decoder.NewBlock(); + src_data = (const SANE_Byte *)"\x5B" "\x63" "\x60" "\x5D" "\x5D" "\x62" "\x6A"; + + res_code = decoder.DecodeScanData (src_data, + strlen((const char *)src_data), + &src_data_consumed, + dest_data, + sizeof(dest_data), + &dest_data_written); + + ASSERT_EQ(res_code, DECODE_STATUS_GOOD); + ASSERT_EQ(src_data_consumed, (size_t)7); + ASSERT_EQ(dest_data_written, (size_t)0); + + decoder.NewBlock(); + src_data = (const SANE_Byte *)"\xDD" "\xE9" "\xEE" "\xEF" "\xED" "\xED" "\xEB"; + + res_code = decoder.DecodeScanData (src_data, + strlen((const char *)src_data), + &src_data_consumed, + dest_data, + sizeof(dest_data), + &dest_data_written); + + ASSERT_EQ(res_code, DECODE_STATUS_GOOD); + ASSERT_EQ(src_data_consumed, (size_t)7); + ASSERT_EQ(dest_data_written, (size_t)0); + + decoder.NewBlock(); + src_data = (const SANE_Byte *)"\x70" "\x6E" "\x6D" "\x6E" "\x6E" "\x6E" "\x6D"; + + res_code = decoder.DecodeScanData (src_data, + strlen((const char *)src_data), + &src_data_consumed, + dest_data, + sizeof(dest_data), + &dest_data_written); + + ASSERT_EQ(res_code, DECODE_STATUS_GOOD); + ASSERT_EQ(src_data_consumed, (size_t)7); + ASSERT_EQ(dest_data_written, (size_t)21); + + // YCbCr data converted to RGB: + ASSERT_EQ(memcmp (dest_data, + "\xa9" "\xfc" "\xc0" "\xc0" "\xff" "\xc9" "\xc1" "\xff" + "\xcc" "\xbd" "\xff" "\xcf" "\xbb" "\xff" "\xcd" "\xc2" + "\xff" "\xcd" "\xcc" "\xff" "\xc9", + 21), + 0); +} +/* + * Run all the tests. + * + */ +void test_colour_int_rgb() +{ + test_colour_int_rgb_enc_rgb(); + test_colour_int_rgb_enc_ycrcb(); +} diff --git a/testsuite/backend/brother_mfp/brother_mfp_tests_colour_jpeg.cpp b/testsuite/backend/brother_mfp/brother_mfp_tests_colour_jpeg.cpp new file mode 100644 index 000000000..645b3639c --- /dev/null +++ b/testsuite/backend/brother_mfp/brother_mfp_tests_colour_jpeg.cpp @@ -0,0 +1,225 @@ +/* sane - Scanner Access Now Easy. + + Copyright (C) 2022 Ralph Little + + This file is part of the SANE package. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#define DEBUG_DECLARE_ONLY + +#include "../../include/sane/sanei_debug.h" +#include "brother_mfp_tests.h" +#include "../../backend/brother_mfp/brother_mfp-encoder.h" +#include "../genesys/minigtest.h" + +/* + * TEST: BrotherJFIFDecoder() + * + */ + +static void test_colour_jpeg_normal() +{ + BrotherJFIFDecoder decoder; + const SANE_Byte *src_data; + SANE_Byte dest_data[1024]; + DecodeStatus res_code; + size_t src_data_consumed; + size_t dest_data_written; + + /* + * Normal decode. + * + * Test image is 7x14 pixels. + * + */ + +#define HEX2DEC(ptr) ((ptr) >= 'a' && (ptr) <= 'f'? (ptr) - 'a' + 10: (ptr) - '0') + + src_data = (const SANE_Byte *)"ffd8ffdb008400" + "010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010" + "101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101" + "010101010101010101010101010101010101010101010101ffdd00040000ffc0001108000e000703012200021101031101ffc401a" + "20000010501010101010100000000000000000102030405060708090a0b100002010303020403050504040000017d010203000411" + "05122131410613516107227114328191a1082342b1c11552d1f02433627282090a161718191a25262728292a3435363738393a434" + "445464748494a535455565758595a636465666768696a737475767778797a838485868788898a92939495969798999aa2a3a4a5a6" + "a7a8a9aab2b3b4b5b6b7b8b9bac2c3c4c5c6c7c8c9cad2d3d4d5d6d7d8d9dae1e2e3e4e5e6e7e8e9eaf1f2f3f4f5f6f7f8f9fa010" + "0030101010101010101010000000000000102030405060708090a0b11000201020404030407050404000102770001020311040521" + "31061241510761711322328108144291a1b1c109233352f0156272d10a162434e125f11718191a262728292a35363738393a43444" + "5464748494a535455565758595a636465666768696a737475767778797a82838485868788898a92939495969798999aa2a3a4a5a6" + "a7a8a9aab2b3b4b5b6b7b8b9bac2c3c4c5c6c7c8c9cad2d3d4d5d6d7d8d9dae2e3e4e5e6e7e8e9eaf2f3f4f5f6f7f8f9faffda000" + "c03010002110311003f00fe929ffe0a19adf807c37f1447ed15fb3378c7e0bfc56f87be1ed37c5ba47c32b3f17e8fe3b87c79e1ed" + "5af534bb2bad03c5ba3585ae991bc7a93ada5f5bcd687ece4131b4ce92431f51a7fede07c33e1cf8a371f1f7e0c6bff03fc77f0d3" + "40d13c5f1f810f88f4ff18cde2ef0b78866b6b5d36f741d4f4fb0b088ddc77575059ea1a6cd6919b59dc0599d63b816ff006df8bf" + "f626fd9abc7fac6b9e20f1b780f57f14eb5e23d134ef0e6a9a8eb7f137e2bdfdc1d0f4abd4d4ac74dd38cfe3765d12de2bf8d6e9f" + "f00b1174e7b89b2d72d36e605fe32fd8aff0066cf887ab6b7aef8e3c03a9f8a356f10f87f4af0b6ab7bac7c47f8a375249a068b73" + "05e69ba6da2b78d045a5c30dddbc57323e951d94d7738796f249de594bfec74f8a3c2ea90a0b11c279861e55ead0a9984b2f963ff" + "d8e341e50a587c8e38de2dc4c6385c5468e70b131cd96618b8bc5615e0f1b8454d470ff009d4b23e35929a867186a0aa29b8db170" + "aff535cb5a30a54e3538720b1897b5a32856adec151960e8a9e1b150ad8a856fffd9"; + + SANE_Byte *in_buffer = new SANE_Byte[strlen((const char *)src_data) / 2]; + SANE_Byte *in_ptr = in_buffer; + + for (const SANE_Byte *src_ptr = src_data; *src_ptr; src_ptr += 2) + { + *in_ptr++ = HEX2DEC(src_ptr[0]) << 4 | HEX2DEC(src_ptr[1]); + } + + /* + * Test JPEG image has expected width. + * + */ + BrotherParameters params; + params.param_pixel_x_width = 7; + + decoder.NewPage(params); + decoder.NewBlock(); + + res_code = decoder.DecodeScanData (in_buffer, + in_ptr - in_buffer, + &src_data_consumed, + dest_data, + sizeof(dest_data), + &dest_data_written); + + ASSERT_EQ(res_code, DECODE_STATUS_GOOD); + ASSERT_EQ(src_data_consumed, (size_t)(in_ptr - in_buffer)); + ASSERT_EQ(dest_data_written, (size_t)294); + + const SANE_Byte expected_dest[] = "\xe4" "\xf0" "\xf0" "\xe8" "\xf2" "\xf4" "\xea" "\xed" "\xf6" "\xeb" + "\xee" "\xf7" "\xeb" "\xee" "\xf7" "\xeb" "\xf0" "\xf6" "\xed" "\xf0" "\xf9" "\xea" "\xf5" "\xf7" + "\xe7" "\xf2" "\xf6" "\xea" "\xee" "\xf7" "\xea" "\xee" "\xf7" "\xe9" "\xf0" "\xf8" "\xe8" "\xef" + "\xf5" "\xea" "\xee" "\xf7" "\xe9" "\xf6" "\xfc" "\xe9" "\xf6" "\xfc" "\xea" "\xf5" "\xfb" "\xea" + "\xf5" "\xfb" "\xe9" "\xf4" "\xfa" "\xe8" "\xf3" "\xf9" "\xe9" "\xf2" "\xf7" "\xdc" "\xe9" "\xff" + "\xd9" "\xe8" "\xff" "\xdd" "\xee" "\xff" "\xe0" "\xf5" "\xff" "\xe3" "\xf7" "\xff" "\xe3" "\xf7" + "\xff" "\xe3" "\xf6" "\xff" "\x4e" "\x59" "\xa9" "\x4c" "\x5e" "\xaa" "\x61" "\x7e" "\xc4" "\xa9" + "\xca" "\xfd" "\xd8" "\xf8" "\xff" "\xd5" "\xf9" "\xff" "\xb2" "\xda" "\xfe" "\x55" "\x5e" "\xad" + "\x4e" "\x5e" "\xac" "\x3f" "\x5c" "\xa8" "\x5b" "\x7f" "\xbd" "\xb2" "\xd6" "\xf6" "\xc2" "\xe9" + "\xff" "\x76" "\xa1" "\xd6" "\xd8" "\xdf" "\xf9" "\xce" "\xdb" "\xfd" "\x90" "\xa4" "\xd6" "\x5e" + "\x77" "\xad" "\x7b" "\x9a" "\xc6" "\xa3" "\xc3" "\xf2" "\x69" "\x88" "\xc8" "\xe9" "\xfe" "\xff" + "\xe7" "\xfd" "\xff" "\xcf" "\xe5" "\xff" "\x76" "\x8e" "\xbe" "\x73" "\x8d" "\xbe" "\x9e" "\xb9" + "\xf0" "\x74" "\x8c" "\xd2" "\xd1" "\xff" "\xff" "\xd5" "\xff" "\xff" "\xbd" "\xe3" "\xff" "\x6c" + "\x8d" "\xba" "\x72" "\x8d" "\xba" "\xa0" "\xb9" "\xef" "\x76" "\x8e" "\xd4" "\xa2" "\xcf" "\xd4" + "\x9c" "\xc6" "\xd2" "\x70" "\x92" "\xad" "\x5a" "\x74" "\x95" "\x8d" "\xa1" "\xc2" "\xb4" "\xc6" + "\xec" "\x80" "\x91" "\xc5" "\xf3" "\xff" "\xff" "\xf5" "\xff" "\xff" "\xf7" "\xff" "\xff" "\xf8" + "\xff" "\xff" "\xf9" "\xff" "\xff" "\xf9" "\xff" "\xff" "\xf9" "\xfe" "\xff" "\xff" "\xff" "\xff" + "\xff" "\xff" "\xff" "\xff" "\xff" "\xfd" "\xff" "\xff" "\xfd" "\xff" "\xff" "\xff" "\xff" "\xff" + "\xff" "\xff" "\xff" "\xff" "\xfe" "\xfe" "\xfc" "\xff" "\xff" "\xfd" "\xff" "\xff" "\xff" "\xff" + "\xff" "\xff" "\xfe" "\xfe" "\xfe" "\xff" "\xff" "\xff" "\xff" "\xff" "\xff" "\xff" "\xff" "\xfd" + "\xff" "\xff" "\xfd" "\xff" "\xff" "\xff" "\xff" "\xff" "\xff" "\xff" "\xff" "\xff" "\xff" "\xff" + "\xff" "\xff" "\xff" "\xff" ; + + ASSERT_EQ(memcmp(dest_data, expected_dest, 294), 0); + +// /* +// * Test JPEG image has extra width: expecting 5. +// * +// */ +// params.param_pixel_x_width = 5; +// +// decoder.NewPage(params); +// decoder.NewBlock(); +// +// res_code = decoder.DecodeScanData (in_buffer, +// in_ptr - in_buffer, +// &src_data_consumed, +// dest_data, +// sizeof(dest_data), +// &dest_data_written); +// +// ASSERT_EQ(res_code, DECODE_STATUS_GOOD); +// ASSERT_EQ(src_data_consumed, (size_t)(in_ptr - in_buffer)); +// ASSERT_EQ(dest_data_written, (size_t)210); +// +// const SANE_Byte expected_dest2[] = "\xe4" "\xf0" "\xf0" "\xe8" "\xf2" "\xf4" "\xea" "\xed" "\xf6" "\xeb" +// "\xee" "\xf7" "\xeb" "\xee" "\xf7" "\xea" "\xf5" "\xf7" "\xe7" "\xf2" "\xf6" "\xea" "\xee" "\xf7" +// "\xea" "\xee" "\xf7" "\xe9" "\xf0" "\xf8" "\xe9" "\xf6" "\xfc" "\xe9" "\xf6" "\xfc" "\xea" "\xf5" +// "\xfb" "\xea" "\xf5" "\xfb" "\xe9" "\xf4" "\xfa" "\xdc" "\xe9" "\xff" "\xd9" "\xe8" "\xff" "\xdd" +// "\xee" "\xff" "\xe0" "\xf5" "\xff" "\xe3" "\xf7" "\xff" "\x4e" "\x59" "\xa9" "\x4c" "\x5e" "\xaa" +// "\x61" "\x7e" "\xc4" "\xa9" "\xca" "\xfd" "\xd8" "\xf8" "\xff" "\x55" "\x5e" "\xad" "\x4e" "\x5e" +// "\xac" "\x3f" "\x5c" "\xa8" "\x5b" "\x7f" "\xbd" "\xb2" "\xd6" "\xf6" "\xd8" "\xdf" "\xf9" "\xce" +// "\xdb" "\xfd" "\x90" "\xa4" "\xd6" "\x5e" "\x77" "\xad" "\x7b" "\x9a" "\xc6" "\xe9" "\xfe" "\xff" +// "\xe7" "\xfd" "\xff" "\xcf" "\xe5" "\xff" "\x76" "\x8e" "\xbe" "\x73" "\x8d" "\xbe" "\xd1" "\xff" +// "\xff" "\xd5" "\xff" "\xff" "\xbd" "\xe3" "\xff" "\x6c" "\x8d" "\xba" "\x72" "\x8d" "\xba" "\xa2" +// "\xcf" "\xd4" "\x9c" "\xc6" "\xd2" "\x70" "\x92" "\xad" "\x5a" "\x74" "\x95" "\x8d" "\xa1" "\xc2" +// "\xf3" "\xff" "\xff" "\xf5" "\xff" "\xff" "\xf7" "\xff" "\xff" "\xf8" "\xff" "\xff" "\xf9" "\xff" +// "\xff" "\xff" "\xff" "\xff" "\xff" "\xff" "\xff" "\xff" "\xff" "\xfd" "\xff" "\xff" "\xfd" "\xff" +// "\xff" "\xff" "\xfe" "\xfe" "\xfc" "\xff" "\xff" "\xfd" "\xff" "\xff" "\xff" "\xff" "\xff" "\xff" +// "\xfe" "\xfe" "\xfe" "\xff" "\xff" "\xfd" "\xff" "\xff" "\xfd" "\xff" "\xff" "\xff" "\xff" "\xff" +// "\xff" "\xff" "\xff" "\xff"; +// +// ASSERT_EQ(memcmp(dest_data, expected_dest2, 210), 0); +// +// /* +// * Test JPEG image has short width: expecting 9. +// * Output will be padded with black. +// * +// */ +// params.param_pixel_x_width = 9; +// +// decoder.NewPage(params); +// decoder.NewBlock(); +// +// res_code = decoder.DecodeScanData (in_buffer, +// in_ptr - in_buffer, +// &src_data_consumed, +// dest_data, +// sizeof(dest_data), +// &dest_data_written); +// +// ASSERT_EQ(res_code, DECODE_STATUS_GOOD); +// ASSERT_EQ(src_data_consumed, (size_t)(in_ptr - in_buffer)); +// ASSERT_EQ(dest_data_written, (size_t)378); +// +// const SANE_Byte expected_dest3[] = "\xe4" "\xf0" "\xf0" "\xe8" "\xf2" "\xf4" "\xea" "\xed" "\xf6" "\xeb" +// "\xee" "\xf7" "\xeb" "\xee" "\xf7" "\xeb" "\xf0" "\xf6" "\xed" "\xf0" "\xf9" "\x00" "\x00" "\x00" +// "\x00" "\x00" "\x00" "\xea" "\xf5" "\xf7" "\xe7" "\xf2" "\xf6" "\xea" "\xee" "\xf7" "\xea" "\xee" +// "\xf7" "\xe9" "\xf0" "\xf8" "\xe8" "\xef" "\xf5" "\xea" "\xee" "\xf7" "\x00" "\x00" "\x00" "\x00" +// "\x00" "\x00" "\xe9" "\xf6" "\xfc" "\xe9" "\xf6" "\xfc" "\xea" "\xf5" "\xfb" "\xea" "\xf5" "\xfb" +// "\xe9" "\xf4" "\xfa" "\xe8" "\xf3" "\xf9" "\xe9" "\xf2" "\xf7" "\x00" "\x00" "\x00" "\x00" "\x00" +// "\x00" "\xdc" "\xe9" "\xff" "\xd9" "\xe8" "\xff" "\xdd" "\xee" "\xff" "\xe0" "\xf5" "\xff" "\xe3" +// "\xf7" "\xff" "\xe3" "\xf7" "\xff" "\xe3" "\xf6" "\xff" "\x00" "\x00" "\x00" "\x00" "\x00" "\x00" +// "\x4e" "\x59" "\xa9" "\x4c" "\x5e" "\xaa" "\x61" "\x7e" "\xc4" "\xa9" "\xca" "\xfd" "\xd8" "\xf8" +// "\xff" "\xd5" "\xf9" "\xff" "\xb2" "\xda" "\xfe" "\x00" "\x00" "\x00" "\x00" "\x00" "\x00" "\x55" +// "\x5e" "\xad" "\x4e" "\x5e" "\xac" "\x3f" "\x5c" "\xa8" "\x5b" "\x7f" "\xbd" "\xb2" "\xd6" "\xf6" +// "\xc2" "\xe9" "\xff" "\x76" "\xa1" "\xd6" "\x00" "\x00" "\x00" "\x00" "\x00" "\x00" "\xd8" "\xdf" +// "\xf9" "\xce" "\xdb" "\xfd" "\x90" "\xa4" "\xd6" "\x5e" "\x77" "\xad" "\x7b" "\x9a" "\xc6" "\xa3" +// "\xc3" "\xf2" "\x69" "\x88" "\xc8" "\x00" "\x00" "\x00" "\x00" "\x00" "\x00" "\xe9" "\xfe" "\xff" +// "\xe7" "\xfd" "\xff" "\xcf" "\xe5" "\xff" "\x76" "\x8e" "\xbe" "\x73" "\x8d" "\xbe" "\x9e" "\xb9" +// "\xf0" "\x74" "\x8c" "\xd2" "\x00" "\x00" "\x00" "\x00" "\x00" "\x00" "\xd1" "\xff" "\xff" "\xd5" +// "\xff" "\xff" "\xbd" "\xe3" "\xff" "\x6c" "\x8d" "\xba" "\x72" "\x8d" "\xba" "\xa0" "\xb9" "\xef" +// "\x76" "\x8e" "\xd4" "\x00" "\x00" "\x00" "\x00" "\x00" "\x00" "\xa2" "\xcf" "\xd4" "\x9c" "\xc6" +// "\xd2" "\x70" "\x92" "\xad" "\x5a" "\x74" "\x95" "\x8d" "\xa1" "\xc2" "\xb4" "\xc6" "\xec" "\x80" +// "\x91" "\xc5" "\x00" "\x00" "\x00" "\x00" "\x00" "\x00" "\xf3" "\xff" "\xff" "\xf5" "\xff" "\xff" +// "\xf7" "\xff" "\xff" "\xf8" "\xff" "\xff" "\xf9" "\xff" "\xff" "\xf9" "\xff" "\xff" "\xf9" "\xfe" +// "\xff" "\x00" "\x00" "\x00" "\x00" "\x00" "\x00" "\xff" "\xff" "\xff" "\xff" "\xff" "\xff" "\xff" +// "\xff" "\xfd" "\xff" "\xff" "\xfd" "\xff" "\xff" "\xff" "\xff" "\xff" "\xff" "\xff" "\xff" "\xff" +// "\x00" "\x00" "\x00" "\x00" "\x00" "\x00" "\xfe" "\xfe" "\xfc" "\xff" "\xff" "\xfd" "\xff" "\xff" +// "\xff" "\xff" "\xff" "\xff" "\xfe" "\xfe" "\xfe" "\xff" "\xff" "\xff" "\xff" "\xff" "\xff" "\x00" +// "\x00" "\x00" "\x00" "\x00" "\x00" "\xff" "\xff" "\xfd" "\xff" "\xff" "\xfd" "\xff" "\xff" "\xff" +// "\xff" "\xff" "\xff" "\xff" "\xff" "\xff" "\xff" "\xff" "\xff" "\xff" "\xff" "\xff" "\x00" "\x00" +// "\x00" "\x00" "\x00" "\x00"; +// +// ASSERT_EQ(memcmp(dest_data, expected_dest3, 378), 0); +} + +/* + * Run all the tests. + * + */ +void test_colour_jpeg() +{ + test_colour_jpeg_normal(); +} diff --git a/testsuite/backend/brother_mfp/brother_mfp_tests_family2.cpp b/testsuite/backend/brother_mfp/brother_mfp_tests_family2.cpp new file mode 100644 index 000000000..6ee6ade87 --- /dev/null +++ b/testsuite/backend/brother_mfp/brother_mfp_tests_family2.cpp @@ -0,0 +1,400 @@ +/* sane - Scanner Access Now Easy. + + Copyright (C) 2022 Ralph Little + + This file is part of the SANE package. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#define DEBUG_DECLARE_ONLY + +#include "brother_mfp_tests.h" +#include "../../backend/brother_mfp/brother_mfp-encoder.h" +#include "../genesys/minigtest.h" + +/* + * TEST: DecodeSessionResp() + * + */ +static void test_family2_decode_session_resp() +{ + DecodeStatus decode_resp; + BrotherSessionResponse sess_resp; + + BrotherEncoderFamily2 encoder(0); + + // SUCCESS status + const SANE_Byte *data = (const SANE_Byte *)"\x05" "\x10" "\x01" "\x02" "\x00"; + + decode_resp = encoder.DecodeSessionResp (data, 5, sess_resp); + + ASSERT_EQ(decode_resp, DECODE_STATUS_GOOD); + ASSERT_TRUE(sess_resp.ready); + + // BUSY status + data = (const SANE_Byte *)"\x05" "\x10" "\x01" "\x02" "\x80"; + + decode_resp = encoder.DecodeSessionResp (data, 5, sess_resp); + + ASSERT_EQ(decode_resp, DECODE_STATUS_GOOD); + ASSERT_FALSE(sess_resp.ready); + + // Length issues + data = (const SANE_Byte *)"\x05" "\x10" "\x01" "\x02" "\x20" "\x32"; + + decode_resp = encoder.DecodeSessionResp (data, 6, sess_resp); + ASSERT_EQ(decode_resp, DECODE_STATUS_ERROR); + + decode_resp = encoder.DecodeSessionResp (data, 4, sess_resp); + ASSERT_EQ(decode_resp, DECODE_STATUS_ERROR); + + decode_resp = encoder.DecodeSessionResp (data, 0, sess_resp); + ASSERT_EQ(decode_resp, DECODE_STATUS_ERROR); + + // Content problems. + const char *content_problems[] = { + "\x32" "\x10" "\x01" "\x02" "\x20", + "\x06" "\x32" "\x01" "\x02" "\x20", + "\x06" "\x10" "\x32" "\x02" "\x20", + "\x06" "\x10" "\x01" "\x32" "\x20", + "\x06" "\x10" "\x01" "\x02" "\x32", + nullptr + }; + + for (size_t test = 0; test; test++) + { + decode_resp = encoder.DecodeSessionResp ((const SANE_Byte *)content_problems[test], 5, sess_resp); + ASSERT_EQ(decode_resp, DECODE_STATUS_ERROR); + } +} + +/* + * TEST: DecodeBasicParameterBlockResp() + * + */ +static void test_family2_decode_basic_param_resp() +{ + /* + * TODO: Nothing to do here yet. + * We don't decode anything from this block. + * Watch this space. + * + */ +} + +/* + * TEST: DecodeADFBlockResp() + * + */ +static void test_family2_decode_source_status_resp() +{ + DecodeStatus decode_resp; + BrotherSourceStatusResponse adf_resp; + + BrotherEncoderFamily2 encoder(0); + + // SUCCESS status + const SANE_Byte *data = (const SANE_Byte *)"\xc2"; + decode_resp = encoder.DecodeSourceStatusBlockResp (data, 1, adf_resp); + + ASSERT_EQ(decode_resp, DECODE_STATUS_GOOD); + ASSERT_FALSE(adf_resp.source_ready); + + data = (const SANE_Byte *)"\x80"; + decode_resp = encoder.DecodeSourceStatusBlockResp (data, 1, adf_resp); + + ASSERT_EQ(decode_resp, DECODE_STATUS_GOOD); + ASSERT_TRUE(adf_resp.source_ready); + + // Wrong length. + decode_resp = encoder.DecodeSourceStatusBlockResp (data, 0, adf_resp); + ASSERT_EQ(decode_resp, DECODE_STATUS_ERROR); + + decode_resp = encoder.DecodeSourceStatusBlockResp (data, 20, adf_resp); + ASSERT_EQ(decode_resp, DECODE_STATUS_ERROR); +} + +/* + * TEST: EncodeBasicParameterBlock() + * + */ +static void test_family2_encode_basic_param() +{ + DecodeStatus decode_resp; + SANE_Byte data_buffer[1024]; + size_t ret_length; + + BrotherEncoderFamily2 encoder(0); + + // All defaults. + decode_resp = encoder.EncodeBasicParameterBlock (data_buffer, sizeof(data_buffer), &ret_length); + + ASSERT_EQ(decode_resp, DECODE_STATUS_GOOD); + + { + const char test_ret[] = "\x1b" "I\nR=100,100\nM=CGRAY\n" "\x80"; + ASSERT_EQ(ret_length, (size_t)22); + ASSERT_EQ(memcmp(test_ret, data_buffer, sizeof(test_ret)), 0); + } + + // Different resolutions. + encoder.SetRes(200,300); + + decode_resp = encoder.EncodeBasicParameterBlock (data_buffer, sizeof(data_buffer), &ret_length); + + ASSERT_EQ(decode_resp, DECODE_STATUS_GOOD); + + { + const char test_ret[] = "\x1b" "I\nR=200,300\nM=CGRAY\n" "\x80"; + ASSERT_EQ(ret_length, (size_t)22); + ASSERT_EQ(memcmp(test_ret, data_buffer, sizeof(test_ret)), 0); + } + + // GRAY mode. + encoder.SetScanMode (BROTHER_SCAN_MODE_GRAY); + decode_resp = encoder.EncodeBasicParameterBlock (data_buffer, sizeof(data_buffer), &ret_length); + + ASSERT_EQ(decode_resp, DECODE_STATUS_GOOD); + + { + const char test_ret[] = "\x1b" "I\nR=200,300\nM=GRAY64\n" "\x80"; + ASSERT_EQ(ret_length, (size_t )23); + ASSERT_EQ(memcmp (test_ret, data_buffer, sizeof(test_ret) - 1), 0); + } + + // COLOR mode + encoder.SetScanMode (BROTHER_SCAN_MODE_COLOR); + decode_resp = encoder.EncodeBasicParameterBlock (data_buffer, sizeof(data_buffer), &ret_length); + + ASSERT_EQ(decode_resp, DECODE_STATUS_GOOD); + + { + const char test_ret[] = "\x1b" "I\nR=200,300\nM=CGRAY\n" "\x80"; + ASSERT_EQ(ret_length, (size_t )22); + ASSERT_EQ(memcmp (test_ret, data_buffer, sizeof(test_ret) - 1), 0); + } + + // GRAY DITHERED mode + encoder.SetScanMode (BROTHER_SCAN_MODE_GRAY_DITHERED); + decode_resp = encoder.EncodeBasicParameterBlock (data_buffer, sizeof(data_buffer), &ret_length); + + ASSERT_EQ(decode_resp, DECODE_STATUS_GOOD); + + { + const char test_ret[] = "\x1b" "I\nR=200,300\nM=ERRDIF\n" "\x80"; + ASSERT_EQ(ret_length, (size_t )23); + ASSERT_EQ(memcmp (test_ret, data_buffer, sizeof(test_ret) - 1), 0); + } + + // TEXT mode + encoder.SetScanMode (BROTHER_SCAN_MODE_TEXT); + decode_resp = encoder.EncodeBasicParameterBlock (data_buffer, sizeof(data_buffer), &ret_length); + + ASSERT_EQ(decode_resp, DECODE_STATUS_GOOD); + + { + const char test_ret[] = "\x1b" "I\nR=200,300\nM=TEXT\n" "\x80"; + ASSERT_EQ(ret_length, (size_t )21); + ASSERT_EQ(memcmp (test_ret, data_buffer, sizeof(test_ret) - 1), 0); + } + + // Buffer too short. + encoder.SetScanMode (BROTHER_SCAN_MODE_TEXT); + decode_resp = encoder.EncodeBasicParameterBlock (data_buffer, 15, &ret_length); + + ASSERT_EQ(decode_resp, DECODE_STATUS_INVAL); +} + +/* + * TEST: EncodeParameterBlock() + * + */ +static void test_family2_encode_param() +{ + DecodeStatus decode_resp; + SANE_Byte data_buffer[1024]; + size_t ret_length; + + BrotherEncoderFamily2 encoder(0); + + // All defaults. + decode_resp = encoder.EncodeParameterBlock (data_buffer, sizeof(data_buffer), &ret_length); + + ASSERT_EQ(decode_resp, DECODE_STATUS_GOOD); + + { + const char test_ret[] = "\x1b" "X\nR=100,100\nM=CGRAY\nC=JPEG\nJ=MID\n" + "B=50\nN=50\nA=0,0,0,0\nD=SIN\n" "\x80"; + ASSERT_EQ(ret_length, sizeof(test_ret) - 1); + ASSERT_EQ(memcmp(test_ret, data_buffer, sizeof(test_ret)), 0); + } + + // Different resolutions. + encoder.SetRes(200,300); + + decode_resp = encoder.EncodeParameterBlock (data_buffer, sizeof(data_buffer), &ret_length); + + ASSERT_EQ(decode_resp, DECODE_STATUS_GOOD); + + { + const char test_ret[] = "\x1b" "X\nR=200,300\nM=CGRAY\nC=JPEG\nJ=MID\n" + "B=50\nN=50\nA=0,0,0,0\nD=SIN\n" "\x80"; + ASSERT_EQ(ret_length, sizeof(test_ret) - 1); + ASSERT_EQ(memcmp(test_ret, data_buffer, sizeof(test_ret)), 0); + } + + // Different modes: + // GRAY mode. + encoder.SetScanMode (BROTHER_SCAN_MODE_GRAY); + decode_resp = encoder.EncodeParameterBlock (data_buffer, sizeof(data_buffer), &ret_length); + + ASSERT_EQ(decode_resp, DECODE_STATUS_GOOD); + + { + const char test_ret[] = "\x1b" "X\nR=200,300\nM=GRAY64\nC=RLENGTH\n" + "B=50\nN=50\nA=0,0,0,0\nD=SIN\n" "\x80"; + ASSERT_EQ(ret_length, sizeof(test_ret) - 1); + ASSERT_EQ(memcmp (test_ret, data_buffer, sizeof(test_ret) - 1), 0); + } + + // COLOR mode + encoder.SetScanMode (BROTHER_SCAN_MODE_COLOR); + decode_resp = encoder.EncodeParameterBlock (data_buffer, sizeof(data_buffer), &ret_length); + + ASSERT_EQ(decode_resp, DECODE_STATUS_GOOD); + + { + const char test_ret[] = "\x1b" "X\nR=200,300\nM=CGRAY\nC=JPEG\nJ=MID\n" + "B=50\nN=50\nA=0,0,0,0\nD=SIN\n" "\x80"; + ASSERT_EQ(ret_length, sizeof(test_ret) - 1); + ASSERT_EQ(memcmp (test_ret, data_buffer, sizeof(test_ret) - 1), 0); + } + + // GRAY DITHERED mode + encoder.SetScanMode (BROTHER_SCAN_MODE_GRAY_DITHERED); + decode_resp = encoder.EncodeParameterBlock (data_buffer, sizeof(data_buffer), &ret_length); + + ASSERT_EQ(decode_resp, DECODE_STATUS_GOOD); + + { + const char test_ret[] = "\x1b" "X\nR=200,300\nM=ERRDIF\nC=RLENGTH\n" + "B=50\nN=50\nA=0,0,0,0\nD=SIN\n" "\x80"; + ASSERT_EQ(ret_length, sizeof(test_ret) - 1); + ASSERT_EQ(memcmp (test_ret, data_buffer, sizeof(test_ret) - 1), 0); + } + + // TEXT mode + encoder.SetScanMode (BROTHER_SCAN_MODE_TEXT); + decode_resp = encoder.EncodeParameterBlock (data_buffer, sizeof(data_buffer), &ret_length); + + ASSERT_EQ(decode_resp, DECODE_STATUS_GOOD); + + { + const char test_ret[] = "\x1b" "X\nR=200,300\nM=TEXT\nC=RLENGTH\n" + "B=50\nN=50\nA=0,0,0,0\nD=SIN\n" "\x80"; + ASSERT_EQ(ret_length, sizeof(test_ret) - 1); + ASSERT_EQ(memcmp (test_ret, data_buffer, sizeof(test_ret) - 1), 0); + } + + // Different brightness and contrast, positive and negative. + encoder.SetBrightness (-20); + encoder.SetContrast (-30); + decode_resp = encoder.EncodeParameterBlock (data_buffer, sizeof(data_buffer), &ret_length); + + ASSERT_EQ(decode_resp, DECODE_STATUS_GOOD); + + { + const char test_ret[] = "\x1b" "X\nR=200,300\nM=TEXT\nC=RLENGTH\n" + "B=30\nN=20\nA=0,0,0,0\nD=SIN\n" "\x80"; + ASSERT_EQ(ret_length, sizeof(test_ret) - 1); + ASSERT_EQ(memcmp (test_ret, data_buffer, sizeof(test_ret) - 1), 0); + } + + encoder.SetBrightness (50); + encoder.SetContrast (40); + decode_resp = encoder.EncodeParameterBlock (data_buffer, sizeof(data_buffer), &ret_length); + + ASSERT_EQ(decode_resp, DECODE_STATUS_GOOD); + + { + const char test_ret[] = "\x1b" "X\nR=200,300\nM=TEXT\nC=RLENGTH\n" + "B=100\nN=90\nA=0,0,0,0\nD=SIN\n" "\x80"; + ASSERT_EQ(ret_length, sizeof(test_ret) - 1); + ASSERT_EQ(memcmp (test_ret, data_buffer, sizeof(test_ret) - 1), 0); + } + + // Different dimensions + encoder.SetScanDimensions (0, 10, 50, 100); + decode_resp = encoder.EncodeParameterBlock (data_buffer, sizeof(data_buffer), &ret_length); + + ASSERT_EQ(decode_resp, DECODE_STATUS_GOOD); + + { + const char test_ret[] = "\x1b" "X\nR=200,300\nM=TEXT\nC=RLENGTH\n" + "B=100\nN=90\nA=0,50,10,150\nD=SIN\n" "\x80"; + ASSERT_EQ(ret_length, sizeof(test_ret) - 1); + ASSERT_EQ(memcmp (test_ret, data_buffer, sizeof(test_ret) - 1), 0); + } + + // Buffer too short. + decode_resp = encoder.EncodeParameterBlock (data_buffer, 15, &ret_length); + + ASSERT_EQ(decode_resp, DECODE_STATUS_INVAL); +} + +/* + * TEST: EncodeADFBlock() + * + */ +static void test_family2_encode_source_status() +{ + DecodeStatus decode_resp; + SANE_Byte data_buffer[1024]; + size_t ret_length; + + BrotherEncoderFamily2 encoder(0); + + // Standard call. + decode_resp = encoder.EncodeSourceStatusBlock (data_buffer, sizeof(data_buffer), &ret_length); + + ASSERT_EQ(decode_resp, DECODE_STATUS_GOOD); + + { + const char test_ret[] = "\x1b" "D\nADF\n" "\x80"; + ASSERT_EQ(ret_length, sizeof(test_ret) - 1); + ASSERT_EQ(memcmp(test_ret, data_buffer, sizeof(test_ret)), 0); + } + + // Buffer too short. + decode_resp = encoder.EncodeSourceStatusBlock (data_buffer, 5, &ret_length); + ASSERT_EQ(decode_resp, DECODE_STATUS_INVAL); +} + +/* + * Run all the tests. + * + */ +void test_family2 () +{ + // Decodes. + test_family2_decode_session_resp(); + test_family2_decode_basic_param_resp(); + test_family2_decode_source_status_resp(); + + // Encodes. + test_family2_encode_basic_param(); + test_family2_encode_param(); + test_family2_encode_source_status(); +} diff --git a/testsuite/backend/brother_mfp/brother_mfp_tests_family3.cpp b/testsuite/backend/brother_mfp/brother_mfp_tests_family3.cpp new file mode 100644 index 000000000..ebbfc91c1 --- /dev/null +++ b/testsuite/backend/brother_mfp/brother_mfp_tests_family3.cpp @@ -0,0 +1,400 @@ +/* sane - Scanner Access Now Easy. + + Copyright (C) 2022 Ralph Little + + This file is part of the SANE package. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#define DEBUG_DECLARE_ONLY + +#include "brother_mfp_tests.h" +#include "../../backend/brother_mfp/brother_mfp-encoder.h" +#include "../genesys/minigtest.h" + +/* + * TEST: DecodeSessionResp() + * + */ +static void test_family3_decode_session_resp() +{ + DecodeStatus decode_resp; + BrotherSessionResponse sess_resp; + + BrotherEncoderFamily3 encoder(0); + + // SUCCESS status + const SANE_Byte *data = (const SANE_Byte *)"\x05" "\x10" "\x01" "\x02" "\x00"; + + decode_resp = encoder.DecodeSessionResp (data, 5, sess_resp); + + ASSERT_EQ(decode_resp, DECODE_STATUS_GOOD); + ASSERT_TRUE(sess_resp.ready); + + // BUSY status + data = (const SANE_Byte *)"\x05" "\x10" "\x01" "\x02" "\x80"; + + decode_resp = encoder.DecodeSessionResp (data, 5, sess_resp); + + ASSERT_EQ(decode_resp, DECODE_STATUS_GOOD); + ASSERT_FALSE(sess_resp.ready); + + // Length issues + data = (const SANE_Byte *)"\x05" "\x10" "\x01" "\x02" "\x20" "\x32"; + + decode_resp = encoder.DecodeSessionResp (data, 6, sess_resp); + ASSERT_EQ(decode_resp, DECODE_STATUS_ERROR); + + decode_resp = encoder.DecodeSessionResp (data, 4, sess_resp); + ASSERT_EQ(decode_resp, DECODE_STATUS_ERROR); + + decode_resp = encoder.DecodeSessionResp (data, 0, sess_resp); + ASSERT_EQ(decode_resp, DECODE_STATUS_ERROR); + + // Content problems. + const char *content_problems[] = { + "\x32" "\x10" "\x01" "\x02" "\x20", + "\x06" "\x32" "\x01" "\x02" "\x20", + "\x06" "\x10" "\x32" "\x02" "\x20", + "\x06" "\x10" "\x01" "\x32" "\x20", + "\x06" "\x10" "\x01" "\x02" "\x32", + nullptr + }; + + for (size_t test = 0; test; test++) + { + decode_resp = encoder.DecodeSessionResp ((const SANE_Byte *)content_problems[test], 5, sess_resp); + ASSERT_EQ(decode_resp, DECODE_STATUS_ERROR); + } +} + +/* + * TEST: DecodeBasicParameterBlockResp() + * + */ +static void test_family3_decode_basic_param_resp() +{ + /* + * TODO: Nothing to do here yet. + * We don't decode anything from this block. + * Watch this space. + * + */ +} + +/* + * TEST: DecodeADFBlockResp() + * + */ +static void test_family3_decode_sourcestatus_resp() +{ + DecodeStatus decode_resp; + BrotherSourceStatusResponse adf_resp; + + BrotherEncoderFamily3 encoder(0); + + // SUCCESS status + const SANE_Byte *data = (const SANE_Byte *)"\xc2"; + decode_resp = encoder.DecodeSourceStatusBlockResp (data, 1, adf_resp); + + ASSERT_EQ(decode_resp, DECODE_STATUS_GOOD); + ASSERT_FALSE(adf_resp.source_ready); + + data = (const SANE_Byte *)"\x80"; + decode_resp = encoder.DecodeSourceStatusBlockResp (data, 1, adf_resp); + + ASSERT_EQ(decode_resp, DECODE_STATUS_GOOD); + ASSERT_TRUE(adf_resp.source_ready); + + // Wrong length. + decode_resp = encoder.DecodeSourceStatusBlockResp (data, 0, adf_resp); + ASSERT_EQ(decode_resp, DECODE_STATUS_ERROR); + + decode_resp = encoder.DecodeSourceStatusBlockResp (data, 20, adf_resp); + ASSERT_EQ(decode_resp, DECODE_STATUS_ERROR); +} + +/* + * TEST: EncodeBasicParameterBlock() + * + */ +static void test_family3_encode_basic_param() +{ + DecodeStatus decode_resp; + SANE_Byte data_buffer[1024]; + size_t ret_length; + + BrotherEncoderFamily3 encoder(0); + + // All defaults. + decode_resp = encoder.EncodeBasicParameterBlock (data_buffer, sizeof(data_buffer), &ret_length); + + ASSERT_EQ(decode_resp, DECODE_STATUS_GOOD); + + { + const char test_ret[] = "\x1b" "I\nR=100,100\nM=CGRAY\n" "\x80"; + ASSERT_EQ(ret_length, (size_t)22); + ASSERT_EQ(memcmp(test_ret, data_buffer, sizeof(test_ret)), 0); + } + + // Different resolutions. + encoder.SetRes(200,300); + + decode_resp = encoder.EncodeBasicParameterBlock (data_buffer, sizeof(data_buffer), &ret_length); + + ASSERT_EQ(decode_resp, DECODE_STATUS_GOOD); + + { + const char test_ret[] = "\x1b" "I\nR=200,300\nM=CGRAY\n" "\x80"; + ASSERT_EQ(ret_length, (size_t)22); + ASSERT_EQ(memcmp(test_ret, data_buffer, sizeof(test_ret)), 0); + } + + // GRAY mode. + encoder.SetScanMode (BROTHER_SCAN_MODE_GRAY); + decode_resp = encoder.EncodeBasicParameterBlock (data_buffer, sizeof(data_buffer), &ret_length); + + ASSERT_EQ(decode_resp, DECODE_STATUS_GOOD); + + { + const char test_ret[] = "\x1b" "I\nR=200,300\nM=GRAY64\n" "\x80"; + ASSERT_EQ(ret_length, (size_t )23); + ASSERT_EQ(memcmp (test_ret, data_buffer, sizeof(test_ret) - 1), 0); + } + + // COLOR mode + encoder.SetScanMode (BROTHER_SCAN_MODE_COLOR); + decode_resp = encoder.EncodeBasicParameterBlock (data_buffer, sizeof(data_buffer), &ret_length); + + ASSERT_EQ(decode_resp, DECODE_STATUS_GOOD); + + { + const char test_ret[] = "\x1b" "I\nR=200,300\nM=CGRAY\n" "\x80"; + ASSERT_EQ(ret_length, (size_t )22); + ASSERT_EQ(memcmp (test_ret, data_buffer, sizeof(test_ret) - 1), 0); + } + + // GRAY DITHERED mode + encoder.SetScanMode (BROTHER_SCAN_MODE_GRAY_DITHERED); + decode_resp = encoder.EncodeBasicParameterBlock (data_buffer, sizeof(data_buffer), &ret_length); + + ASSERT_EQ(decode_resp, DECODE_STATUS_GOOD); + + { + const char test_ret[] = "\x1b" "I\nR=200,300\nM=ERRDIF\n" "\x80"; + ASSERT_EQ(ret_length, (size_t )23); + ASSERT_EQ(memcmp (test_ret, data_buffer, sizeof(test_ret) - 1), 0); + } + + // TEXT mode + encoder.SetScanMode (BROTHER_SCAN_MODE_TEXT); + decode_resp = encoder.EncodeBasicParameterBlock (data_buffer, sizeof(data_buffer), &ret_length); + + ASSERT_EQ(decode_resp, DECODE_STATUS_GOOD); + + { + const char test_ret[] = "\x1b" "I\nR=200,300\nM=TEXT\n" "\x80"; + ASSERT_EQ(ret_length, (size_t )21); + ASSERT_EQ(memcmp (test_ret, data_buffer, sizeof(test_ret) - 1), 0); + } + + // Buffer too short. + encoder.SetScanMode (BROTHER_SCAN_MODE_TEXT); + decode_resp = encoder.EncodeBasicParameterBlock (data_buffer, 15, &ret_length); + + ASSERT_EQ(decode_resp, DECODE_STATUS_INVAL); +} + +/* + * TEST: EncodeParameterBlock() + * + */ +static void test_family3_encode_param() +{ + DecodeStatus decode_resp; + SANE_Byte data_buffer[1024]; + size_t ret_length; + + BrotherEncoderFamily3 encoder(0); + + // All defaults. + decode_resp = encoder.EncodeParameterBlock (data_buffer, sizeof(data_buffer), &ret_length); + + ASSERT_EQ(decode_resp, DECODE_STATUS_GOOD); + + { + const char test_ret[] = "\x1b" "X\nR=100,100\nM=CGRAY\nC=JPEG\nJ=MID\n" + "B=50\nN=50\nA=0,0,0,0\nD=SIN\n" "\x80"; + ASSERT_EQ(ret_length, sizeof(test_ret) - 1); + ASSERT_EQ(memcmp(test_ret, data_buffer, sizeof(test_ret)), 0); + } + + // Different resolutions. + encoder.SetRes(200,300); + + decode_resp = encoder.EncodeParameterBlock (data_buffer, sizeof(data_buffer), &ret_length); + + ASSERT_EQ(decode_resp, DECODE_STATUS_GOOD); + + { + const char test_ret[] = "\x1b" "X\nR=200,300\nM=CGRAY\nC=JPEG\nJ=MID\n" + "B=50\nN=50\nA=0,0,0,0\nD=SIN\n" "\x80"; + ASSERT_EQ(ret_length, sizeof(test_ret) - 1); + ASSERT_EQ(memcmp(test_ret, data_buffer, sizeof(test_ret)), 0); + } + + // Different modes: + // GRAY mode. + encoder.SetScanMode (BROTHER_SCAN_MODE_GRAY); + decode_resp = encoder.EncodeParameterBlock (data_buffer, sizeof(data_buffer), &ret_length); + + ASSERT_EQ(decode_resp, DECODE_STATUS_GOOD); + + { + const char test_ret[] = "\x1b" "X\nR=200,300\nM=GRAY64\nC=RLENGTH\n" + "B=50\nN=50\nA=0,0,0,0\nD=SIN\n" "\x80"; + ASSERT_EQ(ret_length, sizeof(test_ret) - 1); + ASSERT_EQ(memcmp (test_ret, data_buffer, sizeof(test_ret) - 1), 0); + } + + // COLOR mode + encoder.SetScanMode (BROTHER_SCAN_MODE_COLOR); + decode_resp = encoder.EncodeParameterBlock (data_buffer, sizeof(data_buffer), &ret_length); + + ASSERT_EQ(decode_resp, DECODE_STATUS_GOOD); + + { + const char test_ret[] = "\x1b" "X\nR=200,300\nM=CGRAY\nC=JPEG\nJ=MID\n" + "B=50\nN=50\nA=0,0,0,0\nD=SIN\n" "\x80"; + ASSERT_EQ(ret_length, sizeof(test_ret) - 1); + ASSERT_EQ(memcmp (test_ret, data_buffer, sizeof(test_ret) - 1), 0); + } + + // GRAY DITHERED mode + encoder.SetScanMode (BROTHER_SCAN_MODE_GRAY_DITHERED); + decode_resp = encoder.EncodeParameterBlock (data_buffer, sizeof(data_buffer), &ret_length); + + ASSERT_EQ(decode_resp, DECODE_STATUS_GOOD); + + { + const char test_ret[] = "\x1b" "X\nR=200,300\nM=ERRDIF\nC=RLENGTH\n" + "B=50\nN=50\nA=0,0,0,0\nD=SIN\n" "\x80"; + ASSERT_EQ(ret_length, sizeof(test_ret) - 1); + ASSERT_EQ(memcmp (test_ret, data_buffer, sizeof(test_ret) - 1), 0); + } + + // TEXT mode + encoder.SetScanMode (BROTHER_SCAN_MODE_TEXT); + decode_resp = encoder.EncodeParameterBlock (data_buffer, sizeof(data_buffer), &ret_length); + + ASSERT_EQ(decode_resp, DECODE_STATUS_GOOD); + + { + const char test_ret[] = "\x1b" "X\nR=200,300\nM=TEXT\nC=RLENGTH\n" + "B=50\nN=50\nA=0,0,0,0\nD=SIN\n" "\x80"; + ASSERT_EQ(ret_length, sizeof(test_ret) - 1); + ASSERT_EQ(memcmp (test_ret, data_buffer, sizeof(test_ret) - 1), 0); + } + + // Different brightness and contrast, positive and negative. + encoder.SetBrightness (-20); + encoder.SetContrast (-30); + decode_resp = encoder.EncodeParameterBlock (data_buffer, sizeof(data_buffer), &ret_length); + + ASSERT_EQ(decode_resp, DECODE_STATUS_GOOD); + + { + const char test_ret[] = "\x1b" "X\nR=200,300\nM=TEXT\nC=RLENGTH\n" + "B=30\nN=20\nA=0,0,0,0\nD=SIN\n" "\x80"; + ASSERT_EQ(ret_length, sizeof(test_ret) - 1); + ASSERT_EQ(memcmp (test_ret, data_buffer, sizeof(test_ret) - 1), 0); + } + + encoder.SetBrightness (50); + encoder.SetContrast (40); + decode_resp = encoder.EncodeParameterBlock (data_buffer, sizeof(data_buffer), &ret_length); + + ASSERT_EQ(decode_resp, DECODE_STATUS_GOOD); + + { + const char test_ret[] = "\x1b" "X\nR=200,300\nM=TEXT\nC=RLENGTH\n" + "B=100\nN=90\nA=0,0,0,0\nD=SIN\n" "\x80"; + ASSERT_EQ(ret_length, sizeof(test_ret) - 1); + ASSERT_EQ(memcmp (test_ret, data_buffer, sizeof(test_ret) - 1), 0); + } + + // Different dimensions + encoder.SetScanDimensions (0, 10, 50, 100); + decode_resp = encoder.EncodeParameterBlock (data_buffer, sizeof(data_buffer), &ret_length); + + ASSERT_EQ(decode_resp, DECODE_STATUS_GOOD); + + { + const char test_ret[] = "\x1b" "X\nR=200,300\nM=TEXT\nC=RLENGTH\n" + "B=100\nN=90\nA=0,50,10,150\nD=SIN\n" "\x80"; + ASSERT_EQ(ret_length, sizeof(test_ret) - 1); + ASSERT_EQ(memcmp (test_ret, data_buffer, sizeof(test_ret) - 1), 0); + } + + // Buffer too short. + decode_resp = encoder.EncodeParameterBlock (data_buffer, 15, &ret_length); + + ASSERT_EQ(decode_resp, DECODE_STATUS_INVAL); +} + +/* + * TEST: EncodeADFBlock() + * + */ +static void test_family3_encode_adf() +{ + DecodeStatus decode_resp; + SANE_Byte data_buffer[1024]; + size_t ret_length; + + BrotherEncoderFamily3 encoder(0); + + // Standard call. + decode_resp = encoder.EncodeSourceStatusBlock (data_buffer, sizeof(data_buffer), &ret_length); + + ASSERT_EQ(decode_resp, DECODE_STATUS_GOOD); + + { + const char test_ret[] = "\x1b" "D\nADF\n" "\x80"; + ASSERT_EQ(ret_length, sizeof(test_ret) - 1); + ASSERT_EQ(memcmp(test_ret, data_buffer, sizeof(test_ret)), 0); + } + + // Buffer too short. + decode_resp = encoder.EncodeSourceStatusBlock (data_buffer, 5, &ret_length); + ASSERT_EQ(decode_resp, DECODE_STATUS_INVAL); +} + +/* + * Run all the tests. + * + */ +void test_family3 () +{ + // Decodes. + test_family3_decode_session_resp(); + test_family3_decode_basic_param_resp(); + test_family3_decode_sourcestatus_resp(); + + // Encodes. + test_family3_encode_basic_param(); + test_family3_encode_param(); + test_family3_encode_adf(); +}