1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

Merge pull request #17797 from jue89/feature/pkg-tiny-vcdiff

Add package tiny-vcdiff
This commit is contained in:
benpicco 2022-08-26 23:35:16 +02:00 committed by GitHub
commit cb27a267a9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 926 additions and 0 deletions

View File

@ -108,6 +108,7 @@
/pkg/openthread/ @Hyungsin @jia200x
/pkg/semtech-loramac/ @aabadie @jia200x
/pkg/tinydtls/ @rfuentess @leandrolanzieri
/pkg/tinyvcdiff/ @jue89
/pkg/u8g2/ @basilfx
/pkg/ucglib/ @basilfx
/pkg/wakaama/ @leandrolanzieri

View File

@ -67,6 +67,7 @@ rsource "tiny-asn1/Kconfig"
rsource "tinycbor/Kconfig"
rsource "tinycrypt/Kconfig"
rsource "tinydtls/Kconfig"
rsource "tinyvcdiff/Kconfig"
rsource "tlsf/Kconfig"
rsource "tweetnacl/Kconfig"
rsource "u8g2/Kconfig"

46
pkg/tinyvcdiff/Kconfig Normal file
View File

@ -0,0 +1,46 @@
# Copyright (c) 2022 Juergen Fitschen
#
# This file is subject to the terms and conditions of the GNU Lesser
# General Public License v2.1. See the file LICENSE in the top level
# directory for more details.
menuconfig PACKAGE_TINYVCDIFF
bool "Tiny VCDIFF"
depends on TEST_KCONFIG
if PACKAGE_TINYVCDIFF
config TINYVCDIFF_BUFFER_SIZE
int "Buffer size"
default 128
help
For VCDIFF copy and run instruction the library requires a buffer.
The best performance is achieved for sizes of typical page sizes of
the underlying MTD or VFS backend. But a size of just 1 byte would
work, too.
menuconfig MODULE_TINYVCDIFF_MTD
bool "MTD Backend"
depends on MODULE_MTD
default y
help
Use a MTD device as VCDIFF target or source.
if MODULE_TINYVCDIFF_MTD
config TINYVCDIFF_MTD_WRITE_SIZE
int "Write size"
default 4
help
Alignment and minimum size for MTD write access.
endif # MODULE_TINYVCDIFF_MTD
config MODULE_TINYVCDIFF_VFS
bool "VFS Backend"
depends on MODULE_VFS
default y
help
Use a VFS file as VCDIFF target or source.
endif # PACKAGE_TINYVCDIFF

9
pkg/tinyvcdiff/Makefile Normal file
View File

@ -0,0 +1,9 @@
PKG_NAME=tinyvcdiff
PKG_URL=https://github.com/jue89/tiny-vcdiff.git
PKG_VERSION=e1a679f36d0212f2b84057a70c72f6e9deda45b3
PKG_LICENSE=MIT
include $(RIOTBASE)/pkg/pkg.mk
all:
$(QQ)"$(MAKE)" -C $(PKG_SOURCE_DIR)/src -f $(CURDIR)/$(PKG_NAME).mk

View File

@ -0,0 +1,7 @@
ifneq (,$(filter mtd,$(USEMODULE)))
USEMODULE += tinyvcdiff_mtd
endif
ifneq (,$(filter vfs,$(USEMODULE)))
USEMODULE += tinyvcdiff_vfs
endif

View File

@ -0,0 +1,19 @@
# Buffer size for vcdiff
CONFIG_TINYVCDIFF_BUFFER_SIZE ?= 128
CFLAGS += -DVCDIFF_BUFFER_SIZE=$(CONFIG_TINYVCDIFF_BUFFER_SIZE)
# Disable debugging if DEVELHELP is turned off
ifneq ($(DEVELHELP),1)
CFLAGS += -DVCDIFF_NDEBUG
endif
INCLUDES += -I$(PKGDIRBASE)/tinyvcdiff/include
INCLUDES += -I$(RIOTPKG)/tinyvcdiff/include
ifneq (,$(filter tinyvcdiff_mtd,$(USEMODULE)))
DIRS += $(RIOTPKG)/tinyvcdiff/contrib/tinyvcdiff_mtd
endif
ifneq (,$(filter tinyvcdiff_vfs,$(USEMODULE)))
DIRS += $(RIOTPKG)/tinyvcdiff/contrib/tinyvcdiff_vfs
endif

View File

@ -0,0 +1,3 @@
MODULE = tinyvcdiff_mtd
include $(RIOTBASE)/Makefile.base

View File

@ -0,0 +1,179 @@
/*
* Copyright (C) 2022 Juergen Fitschen
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
#include "vcdiff_mtd.h"
#include "assert.h"
#include <string.h>
#define ENABLE_DEBUG 0
#include "debug.h"
static int _erase (void *dev, size_t offset, size_t len)
{
int rc;
vcdiff_mtd_t *mtd = dev;
size_t addr = offset + len;
size_t page = addr / mtd->dev->page_size;
size_t sector = page / mtd->dev->pages_per_sector;
size_t cnt = sector - mtd->next_erase_sector + 1;
/* early exit if all sectors are already in the erased state */
if (cnt == 0) {
return 0;
}
/* erase sectors */
rc = mtd_erase_sector(mtd->dev, mtd->next_erase_sector, cnt);
if (rc != 0) {
return rc;
}
mtd->next_erase_sector += cnt;
return 0;
}
static int _read (void *dev, uint8_t *dest, size_t offset, size_t len)
{
vcdiff_mtd_t *mtd = dev;
/* mtd_read_page will take care of calculation the right page */
int rc = mtd_read_page(mtd->dev, dest, 0, offset, len);
return rc;
}
static int _align_write (vcdiff_mtd_t *mtd, uint8_t **src, size_t *len)
{
size_t alignment_offset;
size_t copy_len;
alignment_offset = mtd->offset % CONFIG_TINYVCDIFF_MTD_WRITE_SIZE;
if (alignment_offset == 0) {
/* we are already aligned */
return 0;
}
/* check how many bytes have to be copied to be aligned */
copy_len = CONFIG_TINYVCDIFF_MTD_WRITE_SIZE - alignment_offset;
if (copy_len > *len) {
copy_len = *len;
}
/* copy unaligned bytes to the write buffer */
memcpy(&mtd->write_buffer[alignment_offset], *src, copy_len);
alignment_offset += copy_len;
mtd->offset += copy_len;
*len -= copy_len;
*src += copy_len;
DEBUG("_align_write: buffered %zuB for alignment\n", copy_len);
if (alignment_offset < CONFIG_TINYVCDIFF_MTD_WRITE_SIZE) {
/* we haven't collected enough bytes, yet */
return 0;
}
assert(alignment_offset == CONFIG_TINYVCDIFF_MTD_WRITE_SIZE);
DEBUG("_align_write: write buffered data\n");
/* write buffer to mtd
* mtd_read_page will take care of calculation the right page
* it's safe to call mtd_read_page_raw: the erase driver already
* prepared the sector for writing */
return mtd_write_page_raw(mtd->dev, mtd->write_buffer, 0,
mtd->offset - alignment_offset,
CONFIG_TINYVCDIFF_MTD_WRITE_SIZE);
}
static int _write (void *dev, uint8_t *src, size_t offset, size_t len)
{
int rc;
size_t to_copy;
vcdiff_mtd_t *mtd = dev;
assert(offset == mtd->offset);
DEBUG("_write: 0x%zx + %zuB\n", mtd->offset, len);
/* align writes */
rc = _align_write(dev, &src, &len);
if (rc < 0) {
/* an error occurred */
return rc;
} else if (len == 0) {
/* no bytes are left */
return 0;
}
assert((mtd->offset % CONFIG_TINYVCDIFF_MTD_WRITE_SIZE) == 0);
/* copy all aligned data */
to_copy = (len / CONFIG_TINYVCDIFF_MTD_WRITE_SIZE) * CONFIG_TINYVCDIFF_MTD_WRITE_SIZE;
rc = mtd_write_page_raw(mtd->dev, src, 0, mtd->offset, to_copy);
if (rc < 0) {
return rc;
}
mtd->offset += to_copy;
len -= to_copy;
src += to_copy;
if (len == 0) {
/* no bytes are left */
return 0;
}
assert(len < CONFIG_TINYVCDIFF_MTD_WRITE_SIZE);
/* copy remaining bytes into write_buffer */
memcpy(mtd->write_buffer, src, len);
mtd->offset += len;
DEBUG("_write: buffered %zuB for alignment\n", len);
return rc;
}
static int _flush (void *dev)
{
vcdiff_mtd_t *mtd = dev;
int rc;
uint8_t buf[CONFIG_TINYVCDIFF_MTD_WRITE_SIZE];
size_t alignment_offset;
alignment_offset = mtd->offset % CONFIG_TINYVCDIFF_MTD_WRITE_SIZE;
if (alignment_offset == 0) {
/* we are already aligned -> no bytes are left in the buffer */
return 0;
}
DEBUG("_flush: write last %zuB\n", alignment_offset);
/* get present bytes from MTD to pad alignment */
rc = mtd_read_page(mtd->dev, buf, 0, mtd->offset - alignment_offset,
CONFIG_TINYVCDIFF_MTD_WRITE_SIZE);
if (rc < 0) {
return rc;
}
/* pad write buffer */
memcpy(&mtd->write_buffer[alignment_offset], &buf[alignment_offset],
CONFIG_TINYVCDIFF_MTD_WRITE_SIZE - alignment_offset);
/* write last buffer */
rc = mtd_write_page_raw(mtd->dev, mtd->write_buffer, 0,
mtd->offset - alignment_offset,
CONFIG_TINYVCDIFF_MTD_WRITE_SIZE);
return rc;
}
const vcdiff_driver_t vcdiff_mtd_driver = {
.erase = _erase,
.read = _read,
.write = _write,
.flush = _flush
};

View File

@ -0,0 +1,3 @@
MODULE = tinyvcdiff_vfs
include $(RIOTBASE)/Makefile.base

View File

@ -0,0 +1,69 @@
/*
* Copyright (C) 2022 Juergen Fitschen
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
#include "vcdiff_vfs.h"
#include <unistd.h>
#include "errno.h"
static int _read (void *dev, uint8_t *dest, size_t offset, size_t len)
{
int rc;
vcdiff_vfs_t *vfs = dev;
/* seek to the given offset */
rc = vfs_lseek(vfs->fd, offset, SEEK_SET);
if (rc < 0) {
return rc;
} else if ((size_t) rc != offset) {
return -EFAULT;
}
/* read from file into the buffer */
rc = vfs_read(vfs->fd, dest, len);
if (rc < 0) {
return rc;
} else if ((size_t) rc != len) {
return -EFAULT;
}
return 0;
}
static int _write (void *dev, uint8_t *src, size_t offset, size_t len)
{
int rc;
vcdiff_vfs_t *vfs = dev;
/* make sure to stay in the set file size bounds */
if (offset + len > vfs->max_size) {
return -EFBIG;
}
/* seek to the given offset */
rc = vfs_lseek(vfs->fd, offset, SEEK_SET);
if (rc < 0) {
return rc;
} else if ((size_t) rc != offset) {
return -EFAULT;
}
/* write all bytes to the file */
rc = vfs_write(vfs->fd, src, len);
if (rc < 0) {
return rc;
} else if ((size_t) rc != len) {
return -EFAULT;
}
return 0;
}
const vcdiff_driver_t vcdiff_vfs_driver = {
.read = _read,
.write = _write
};

58
pkg/tinyvcdiff/doc.txt Normal file
View File

@ -0,0 +1,58 @@
/**
* @defgroup pkg_tinyvcdiff Tiny VCDIFF
* @ingroup pkg
* @brief Decoder for interleaved VCDIFF deltas
*
* # Introduction
*
* tiny-vcdiff is a decoder for binary delta files that have been generated by
* [open-vcdiff](https://github.com/google/open-vcdiff) in the interleaved format.
*
* # Usage
*
* Every delta requires a source (the known data) and a target (the reconstructed
* data). This implementation provides backends for the @ref drivers_mtd and
* @ref sys_vfs storage drivers.
*
* # Example
*
* The example down below uses a @ref drivers_mtd device as known source data and
* writes the resulting target data into a @ref sys_vfs file.
*
* ```c
* #include "vcdiff.h"
* #include "vcdiff_mtd.h"
* #include "vcdiff_vfs.h"
*
* int apply_delta (const uint8_t *data, size_t data_len,
* mtd_dev_t *source_mtd,
* int traget_fd)
* {
* int rc;
* vcdiff_t vcdiff;
* vcdiff_init(&vcdiff);
*
* /* make sure source_mtd is already powered on */
* vcdiff_mtd_t source = VCDIFF_MTD_INIT(source_mtd);
* vcdiff_set_source_driver(&vcdiff, &vcdiff_mtd_driver, &source);
*
* /* make sure the vfs file is already opened for writing */
* vcdiff_vfs_t target = VCDIFF_VFS_INIT(fd_target);
* vcdiff_set_target_driver(&vcdiff, &vcdiff_vfs_driver, &target);
*
* rc = vcdiff_apply_delta(&vcdiff, data, data_len);
* if (rc != 0) {
* return rc;
* }
*
* rc = vcdiff_finish(&vcdiff);
* return rc;
* }
* ```
*
* # License
*
* Licensed under MIT.
*
* @see https://github.com/jue89/tiny-vcdiff.git
*/

View File

@ -0,0 +1,75 @@
/*
* Copyright (C) 2022 Juergen Fitschen
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @{
*
* @file
* @ingroup pkg_tinyvcdiff
*
* @author Juergen Fitschen <me@jue.yt>
*/
#ifndef VCDIFF_MTD_H
#define VCDIFF_MTD_H
#include "vcdiff.h"
#include "mtd.h"
#ifndef CONFIG_TINYVCDIFF_MTD_WRITE_SIZE
/**
* @brief Alignment and minimum size for MTD write access
*/
#define CONFIG_TINYVCDIFF_MTD_WRITE_SIZE 4
#endif
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Driver for accessing MTD devices
*/
extern const vcdiff_driver_t vcdiff_mtd_driver;
/**
* @brief Context for the underlying MTD device
*/
typedef struct {
/**
* @brief Instance of the backing MTD device
*/
mtd_dev_t *dev;
/**
* @brief Number of the next sector that must be erased
*/
size_t next_erase_sector;
/**
* @brief Buffer for aligned writes
*/
uint8_t write_buffer[CONFIG_TINYVCDIFF_MTD_WRITE_SIZE];
/**
* @brief Current offset on the MTD device
*/
size_t offset;
} vcdiff_mtd_t;
/**
* @brief Initializes vcdiff_mtd_t
*/
#define VCDIFF_MTD_INIT(DEV) { .dev = DEV }
#ifdef __cplusplus
}
#endif
#endif /* VCDIFF_MTD_H */
/** @} */

View File

@ -0,0 +1,56 @@
/*
* Copyright (C) 2022 Juergen Fitschen
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @{
*
* @file
* @ingroup pkg_tinyvcdiff
*
* @author Juergen Fitschen <me@jue.yt>
*/
#ifndef VCDIFF_VFS_H
#define VCDIFF_VFS_H
#include "vcdiff.h"
#include "vfs.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Driver for accessing VFS-based file access
*/
extern const vcdiff_driver_t vcdiff_vfs_driver;
/**
* @brief Context for the underlying file
*/
typedef struct {
int fd; /**< File descriptor of the VFS file */
size_t max_size; /**< Maxmimum file size for vcdiff target files */
} vcdiff_vfs_t;
/**
* @brief Initializes vcdiff_vfs_t with maximum allowed file size
*/
#define VCDIFF_VFS_INIT_MAX_SIZE(FD, SIZE) { .fd = FD, .max_size = SIZE }
/**
* @brief Initializes vcdiff_vfs_t
*/
#define VCDIFF_VFS_INIT(FD) VCDIFF_VFS_INIT_MAX_SIZE(FD, SIZE_MAX)
#ifdef __cplusplus
}
#endif
#endif /* VCDIFF_VFS_H */
/** @} */

View File

@ -0,0 +1,3 @@
MODULE = tinyvcdiff
include $(RIOTBASE)/Makefile.base

View File

@ -0,0 +1,19 @@
include ../Makefile.tests_common
BLOBS += source.bin delta.bin target.bin
# Only run on native ...
TEST_ON_CI_WHITELIST += native
USEMODULE += embunit
# Library under test
USEPKG += tinyvcdiff
# MTD backend
USEMODULE += mtd
# VFS backend
USEPKG += littlefs2
include $(RIOTBASE)/Makefile.include

View File

@ -0,0 +1,25 @@
BOARD_INSUFFICIENT_MEMORY := \
arduino-duemilanove \
arduino-leonardo \
arduino-mega2560 \
arduino-nano \
arduino-uno \
atmega328p \
atmega328p-xplained-mini \
bluepill-stm32f030c8 \
i-nucleo-lrwan1 \
nucleo-f030r8 \
nucleo-f031k6 \
nucleo-f042k6 \
nucleo-l011k4 \
nucleo-l031k6 \
nucleo-l053r8 \
samd10-xmini \
slstk3400a \
stk3200 \
stm32f030f4-demo \
stm32f0discovery \
stm32g0316-disco \
stm32l0538-disco \
waspmote-pro \
#

View File

@ -0,0 +1,10 @@
pkg_tinyvcdiff
==============
This test patches the binary file `source.bin` using `delta.bin` and reconstructs `target.bin`.
`delta.bin` has been created with open-vcdiff:
```
vcdiff delta -interleaved -dictionary source.bin <target.bin >delta.bin
```

View File

@ -0,0 +1,5 @@
CONFIG_MODULE_EMBUNIT=y
CONFIG_MODULE_MTD=y
CONFIG_MODULE_LITTLEFS2_FS=y
CONFIG_PACKAGE_TINYVCDIFF=y
CONFIG_PACKAGE_LITTLEFS2=y

Binary file not shown.

View File

@ -0,0 +1,104 @@
/*
* Copyright (C) 2022 Juergen Fitschen
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @{
*
* @file
* @ingroup tests
* @brief Fake MTD device
*
* @author Juergen Fitschen <me@jue.yt>
*/
#include <string.h>
#include <errno.h>
#include "fakemtd.h"
#define ENABLE_DEBUG 0
#include "debug.h"
static inline uint32_t sector2offset(fake_mtd_t *ctx, uint32_t sector)
{
return sector * ctx->mtd.page_size * ctx->mtd.pages_per_sector;
}
static inline uint32_t page2offset(fake_mtd_t *ctx, uint32_t page)
{
return page * ctx->mtd.page_size;
}
static inline bool within_bounds(fake_mtd_t *ctx, uint32_t offset, uint32_t count)
{
return (offset + count) <= sizeof(ctx->buffer);
}
static int _init(mtd_dev_t *dev)
{
(void) dev;
return 0;
}
static int _read_page(mtd_dev_t *dev, void *buff, uint32_t page, uint32_t offset, uint32_t size)
{
fake_mtd_t *ctx = container_of(dev, fake_mtd_t, mtd);
DEBUG("fake_mtd: _read_page(%"PRIu32", %"PRIu32", %"PRIu32")\n", page, offset, size);
offset += page2offset(ctx, page);
if (!within_bounds(ctx, offset, size)) {
return -EOVERFLOW;
}
memcpy(buff, &ctx->buffer[offset], size);
return size;
}
static int _write_page(mtd_dev_t *dev, const void *buff, uint32_t page, uint32_t offset, uint32_t size)
{
fake_mtd_t *ctx = container_of(dev, fake_mtd_t, mtd);
DEBUG("fake_mtd: _write_page(%"PRIu32", %"PRIu32", %"PRIu32")\n", page, offset, size);
offset += page2offset(ctx, page);
if (!within_bounds(ctx, offset, size)) {
return -EOVERFLOW;
}
memcpy(&ctx->buffer[offset], buff, size);
return size;
}
static int _erase_sector(mtd_dev_t *dev, uint32_t sector, uint32_t count)
{
fake_mtd_t *ctx = container_of(dev, fake_mtd_t, mtd);
DEBUG("fake_mtd: _erase_sector(%"PRIu32", %"PRIu32")\n", sector, count);
uint32_t offset = sector2offset(ctx, sector);
uint32_t size = sector2offset(ctx, count);
if (!within_bounds(ctx, offset, count)) {
return -EOVERFLOW;
}
memset(&ctx->buffer[offset], 0xff, size);
return 0;
}
const mtd_desc_t fake_mtd_driver = {
.init = _init,
.read_page = _read_page,
.write_page = _write_page,
.erase_sector = _erase_sector,
};
/** @} */

View File

@ -0,0 +1,75 @@
/*
* Copyright (C) 2022 Juergen Fitschen
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @{
*
* @file
* @ingroup tests
* @brief Fake MTD device
*
* @author Juergen Fitschen <me@jue.yt>
*/
#ifndef FAKEMTD_H
#define FAKEMTD_H
#include "mtd.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Page size
*/
#define FAKE_MTD_PAGE_SIZE 128
/**
* @brief Pages per sector
*/
#define FAKE_MTD_PAGES_PER_SECTOR 4
/**
* @brief Sector count
*/
#define FAKE_MTD_SECTOR_COUNT 4
/**
* @brief Storage size in byte
*/
#define MAKE_MTD_MEM_SIZE (FAKE_MTD_PAGE_SIZE * \
FAKE_MTD_PAGES_PER_SECTOR * \
FAKE_MTD_SECTOR_COUNT)
/**
* @brief Driver for fake MTD
*/
extern const mtd_desc_t fake_mtd_driver;
/**
* @brief Context for the fake MTD
*/
typedef struct {
mtd_dev_t mtd; /**< MTD instance */
uint8_t buffer[MAKE_MTD_MEM_SIZE]; /**< Storage of the MTD */
} fake_mtd_t;
/**
* @brief Initializes fake_mtd_t
*/
#define FAKE_MTD_INIT { .mtd = { .driver = &fake_mtd_driver, \
.sector_count = FAKE_MTD_SECTOR_COUNT, \
.pages_per_sector = FAKE_MTD_PAGES_PER_SECTOR, \
.page_size = FAKE_MTD_PAGE_SIZE } }
#ifdef __cplusplus
}
#endif
#endif /* FAKEMTD_H */
/** @} */

139
tests/pkg_tinyvcdiff/main.c Normal file
View File

@ -0,0 +1,139 @@
/*
* Copyright (C) 2022 Juergen Fitschen
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup tests
* @{
*
* @file
* @brief tinyvcdiff library backend tests
*
* @author Juergen Fitschen <me@jue.yt>
*
* @}
*/
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include "embUnit.h"
#include "vcdiff.h"
#include "vcdiff_mtd.h"
#include "vcdiff_vfs.h"
#include "fakemtd.h"
#include "fs/littlefs2_fs.h"
/* Generated using open-vcdiff:
* $ echo "Hello world! I hope you are doing well ..." >source.bin
* $ echo "Hello universe! I hope you are doing well ..." >target.bin
* $ vcdiff delta -interleaved -dictionary source.bin <target.bin >delta.bin */
#include "blob/source.bin.h"
#include "blob/target.bin.h"
#include "blob/delta.bin.h"
static vcdiff_t vcdiff;
static fake_mtd_t storage_a = FAKE_MTD_INIT;
static fake_mtd_t storage_b = FAKE_MTD_INIT;
static void test_tinyvcdiff_mtd(void)
{
int rc;
mtd_dev_t * source_mtd = &storage_a.mtd;
vcdiff_mtd_t source_vcdiff = VCDIFF_MTD_INIT(source_mtd);
mtd_dev_t * target_mtd = &storage_b.mtd;
vcdiff_mtd_t target_vcdiff = VCDIFF_MTD_INIT(target_mtd);
/* write source data to fake-mtd */
mtd_write(source_mtd, source_bin, 0, source_bin_len);
/* setup vcdiff */
vcdiff_init(&vcdiff);
vcdiff_set_source_driver(&vcdiff, &vcdiff_mtd_driver, &source_vcdiff);
vcdiff_set_target_driver(&vcdiff, &vcdiff_mtd_driver, &target_vcdiff);
/* apply diff */
rc = vcdiff_apply_delta(&vcdiff, delta_bin, delta_bin_len);
TEST_ASSERT_EQUAL_INT(0, rc);
rc = vcdiff_finish(&vcdiff);
TEST_ASSERT_EQUAL_INT(0, rc);
/* check reconsturcted target */
uint8_t target_buf[target_bin_len];
mtd_read(target_mtd, target_buf, 0, sizeof(target_buf));
TEST_ASSERT_EQUAL_INT(0, memcmp(target_bin, target_buf, sizeof(target_buf)));
}
static void test_tinyvcdiff_vfs(void)
{
int rc;
int source_fd, target_fd;
littlefs2_desc_t fs = { .dev = &storage_a.mtd };
vfs_mount_t mnt = {
.mount_point = "/mnt",
.fs = &littlefs2_file_system,
.private_data = &fs,
};
vfs_format(&mnt);
vfs_mount(&mnt);
/* write source data to fs */
source_fd = vfs_open("/mnt/source", O_WRONLY | O_CREAT, 0);
vfs_write(source_fd, source_bin, source_bin_len);
vfs_close(source_fd);
/* open source and target file */
source_fd = vfs_open("/mnt/source", O_RDONLY, 0);
vcdiff_vfs_t source_vcdiff = VCDIFF_VFS_INIT(source_fd);
target_fd = vfs_open("/mnt/target", O_WRONLY | O_CREAT, 0);
vcdiff_vfs_t target_vcdiff = VCDIFF_VFS_INIT(target_fd);
/* setup vcdiff */
vcdiff_init(&vcdiff);
vcdiff_set_source_driver(&vcdiff, &vcdiff_vfs_driver, &source_vcdiff);
vcdiff_set_target_driver(&vcdiff, &vcdiff_vfs_driver, &target_vcdiff);
/* apply diff */
rc = vcdiff_apply_delta(&vcdiff, delta_bin, delta_bin_len);
TEST_ASSERT_EQUAL_INT(0, rc);
rc = vcdiff_finish(&vcdiff);
TEST_ASSERT_EQUAL_INT(0, rc);
vfs_close(source_fd);
vfs_close(target_fd);
/* check reconsturcted target */
target_fd = vfs_open("/mnt/target", O_RDONLY, 0);
uint8_t target_buf[target_bin_len];
vfs_read(target_fd, target_buf, sizeof(target_buf));
TEST_ASSERT_EQUAL_INT(0, memcmp(target_bin, target_buf, sizeof(target_buf)));
vfs_close(target_fd);
vfs_umount(&mnt);
}
Test *tests_tinyvcdiff(void)
{
EMB_UNIT_TESTFIXTURES(fixtures) {
new_TestFixture(test_tinyvcdiff_mtd),
new_TestFixture(test_tinyvcdiff_vfs),
};
EMB_UNIT_TESTCALLER(tinycvdiff_tests, NULL, NULL, fixtures);
return (Test*)&tinycvdiff_tests;
}
int main(void)
{
TESTS_START();
TESTS_RUN(tests_tinyvcdiff());
TESTS_END();
return 0;
}

View File

@ -0,0 +1 @@
Hello world! I hope you are doing well ...

View File

@ -0,0 +1 @@
Hello universe! I hope you are doing well ...

View File

@ -0,0 +1,18 @@
#!/usr/bin/env python3
# Copyright (C) 2022 Juergen Fitschen
#
# This file is subject to the terms and conditions of the GNU Lesser
# General Public License v2.1. See the file LICENSE in the top level
# directory for more details.
import sys
from testrunner import run
def testfunc(child):
child.expect("OK")
if __name__ == "__main__":
sys.exit(run(testfunc))