Compare commits
51 Commits
Author | SHA1 | Date | |
---|---|---|---|
d5dede5a61 | |||
719400068a | |||
aaf8c6adc1 | |||
dc081ae2aa | |||
3cf3097094 | |||
e801626232 | |||
a5093c4aa3 | |||
c311bb5c95 | |||
887705969f | |||
316871523d | |||
a3d193516c | |||
6709dba0e7 | |||
a8d8613f2c | |||
aae086cc65 | |||
6ec6fe96e4 | |||
2d31b57097 | |||
b1d4848b81 | |||
3678301916 | |||
459ccf7d6b | |||
db54afd180 | |||
f4fe94dfe6 | |||
28b92b0f4c | |||
c966fc6954 | |||
d0761bf60e | |||
0f41ee6a2e | |||
0aeafec019 | |||
9a0df4f577 | |||
61714836bb | |||
cff0c100ec | |||
010c49d100 | |||
ff5dbaffc0 | |||
b56d581e4b | |||
aa661aaaa7 | |||
cc3f430bab | |||
139db5b03b | |||
7d0e5c80bd | |||
f716ad9dd1 | |||
671772a20e | |||
b0173f6d68 | |||
3da5872df8 | |||
3deb6e8469 | |||
0c674e0137 | |||
7948d820c3 | |||
5aac3422aa | |||
e8eaa7a232 | |||
04b3382029 | |||
7fe6df5889 | |||
2647c85323 | |||
93140231c6 | |||
e76e56e025 | |||
b1062e701e |
9
.github/workflows/cd.yml
vendored
9
.github/workflows/cd.yml
vendored
@ -30,9 +30,6 @@ jobs:
|
||||
- name: Build
|
||||
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} -j 4
|
||||
|
||||
- name: temp test
|
||||
run: ${{github.workspace}}/build/bin/mono_time_test
|
||||
|
||||
- name: Determine tag name
|
||||
id: tag
|
||||
shell: bash
|
||||
@ -84,9 +81,6 @@ jobs:
|
||||
- name: Build
|
||||
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}
|
||||
|
||||
- name: temp test
|
||||
run: ${{github.workspace}}/build/bin/mono_time_test.exe
|
||||
|
||||
- name: Determine tag name
|
||||
id: tag
|
||||
shell: bash
|
||||
@ -138,9 +132,6 @@ jobs:
|
||||
- name: Build
|
||||
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} -j 4
|
||||
|
||||
- name: temp test
|
||||
run: ${{github.workspace}}/build/bin/mono_time_test.exe
|
||||
|
||||
- name: Determine tag name
|
||||
id: tag
|
||||
shell: bash
|
||||
|
6
.github/workflows/ci.yml
vendored
6
.github/workflows/ci.yml
vendored
@ -29,9 +29,6 @@ jobs:
|
||||
- name: Build
|
||||
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} -j 4
|
||||
|
||||
- name: temp test
|
||||
run: ${{github.workspace}}/build/bin/mono_time_test
|
||||
|
||||
macos:
|
||||
timeout-minutes: 10
|
||||
|
||||
@ -75,6 +72,3 @@ jobs:
|
||||
- name: Build
|
||||
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} -j 4
|
||||
|
||||
- name: temp test
|
||||
run: ${{github.workspace}}/build/bin/mono_time_test.exe
|
||||
|
||||
|
@ -2,3 +2,7 @@
|
||||
|
||||

|
||||
|
||||
## Highly experimental solanaceae client with Tox built-in
|
||||
|
||||

|
||||
|
||||
|
1
external/CMakeLists.txt
vendored
1
external/CMakeLists.txt
vendored
@ -17,4 +17,5 @@ add_subdirectory(./imgui)
|
||||
|
||||
add_subdirectory(./stb)
|
||||
add_subdirectory(./libwebp)
|
||||
add_subdirectory(./qoi)
|
||||
|
||||
|
11
external/qoi/CMakeLists.txt
vendored
Normal file
11
external/qoi/CMakeLists.txt
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
cmake_minimum_required(VERSION 3.13...3.24 FATAL_ERROR)
|
||||
|
||||
project(qoi C CXX)
|
||||
|
||||
add_library(qoi_interface INTERFACE)
|
||||
target_include_directories(qoi_interface SYSTEM INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
|
||||
# static lib with impl
|
||||
add_library(qoi "qoi.cpp")
|
||||
target_link_libraries(qoi qoi_interface)
|
||||
|
3
external/qoi/qoi.cpp
vendored
Normal file
3
external/qoi/qoi.cpp
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
#define QOI_IMPLEMENTATION
|
||||
#include <qoi/qoi.h>
|
||||
|
5
external/qoi/qoi/.gitignore
vendored
Normal file
5
external/qoi/qoi/.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
images/
|
||||
stb_image.h
|
||||
stb_image_write.h
|
||||
qoibench
|
||||
qoiconv
|
21
external/qoi/qoi/LICENSE
vendored
Normal file
21
external/qoi/qoi/LICENSE
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2022 Dominic Szablewski
|
||||
|
||||
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.
|
22
external/qoi/qoi/Makefile
vendored
Normal file
22
external/qoi/qoi/Makefile
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
CC ?= gcc
|
||||
CFLAGS_BENCH ?= -std=gnu99 -O3
|
||||
LFLAGS_BENCH ?= -lpng
|
||||
CFLAGS_CONV ?= -std=c99 -O3
|
||||
|
||||
TARGET_BENCH ?= qoibench
|
||||
TARGET_CONV ?= qoiconv
|
||||
|
||||
all: $(TARGET_BENCH) $(TARGET_CONV)
|
||||
|
||||
bench: $(TARGET_BENCH)
|
||||
|
||||
$(TARGET_BENCH):$(TARGET_BENCH).c
|
||||
$(CC) $(CFLAGS_BENCH) $(CFLAGS) $(TARGET_BENCH).c -o $(TARGET_BENCH) $(LFLAGS_BENCH)
|
||||
|
||||
conv: $(TARGET_CONV)
|
||||
$(TARGET_CONV):$(TARGET_CONV).c
|
||||
$(CC) $(CFLAGS_CONV) $(CFLAGS) $(TARGET_CONV).c -o $(TARGET_CONV)
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
$(RM) $(TARGET_BENCH) $(TARGET_CONV)
|
179
external/qoi/qoi/README.md
vendored
Normal file
179
external/qoi/qoi/README.md
vendored
Normal file
@ -0,0 +1,179 @@
|
||||

|
||||
|
||||
# QOI - The “Quite OK Image Format” for fast, lossless image compression
|
||||
|
||||
Single-file MIT licensed library for C/C++
|
||||
|
||||
See [qoi.h](https://github.com/phoboslab/qoi/blob/master/qoi.h) for
|
||||
the documentation and format specification.
|
||||
|
||||
More info at https://qoiformat.org
|
||||
|
||||
|
||||
## Why?
|
||||
|
||||
Compared to stb_image and stb_image_write QOI offers 20x-50x faster encoding,
|
||||
3x-4x faster decoding and 20% better compression. It's also stupidly simple and
|
||||
fits in about 300 lines of C.
|
||||
|
||||
|
||||
## Example Usage
|
||||
|
||||
- [qoiconv.c](https://github.com/phoboslab/qoi/blob/master/qoiconv.c)
|
||||
converts between png <> qoi
|
||||
- [qoibench.c](https://github.com/phoboslab/qoi/blob/master/qoibench.c)
|
||||
a simple wrapper to benchmark stbi, libpng and qoi
|
||||
|
||||
|
||||
## MIME Type, File Extension
|
||||
|
||||
The recommended MIME type for QOI images is `image/qoi`. While QOI is not yet
|
||||
officially registered with IANA, I believe QOI has found enough adoption to
|
||||
prevent any future image format from choosing the same name, thus making a
|
||||
MIME type collision highly unlikely ([see #167](https://github.com/phoboslab/qoi/issues/167)).
|
||||
|
||||
The recommended file extension for QOI images is `.qoi`
|
||||
|
||||
|
||||
## Limitations
|
||||
|
||||
The QOI file format allows for huge images with up to 18 exa-pixels. A streaming
|
||||
en-/decoder can handle these with minimal RAM requirements, assuming there is
|
||||
enough storage space.
|
||||
|
||||
This particular implementation of QOI however is limited to images with a
|
||||
maximum size of 400 million pixels. It will safely refuse to en-/decode anything
|
||||
larger than that. This is not a streaming en-/decoder. It loads the whole image
|
||||
file into RAM before doing any work and is not extensively optimized for
|
||||
performance (but it's still very fast).
|
||||
|
||||
If this is a limitation for your use case, please look into any of the other
|
||||
implementations listed below.
|
||||
|
||||
|
||||
## Improvements, New Versions and Contributing
|
||||
|
||||
The QOI format has been finalized. It was a conscious decision to **not** have a
|
||||
version number in the file header. If you have a working QOI implementation today,
|
||||
you can rest assured that it will be compatible with all QOI files tomorrow.
|
||||
|
||||
There are a lot of interesting ideas for a successor of QOI, but none of these will
|
||||
be implemented here. That doesn't mean you shouldn't experiment with QOI, but please
|
||||
be aware that pull requests that change the format will not be accepted.
|
||||
|
||||
Likewise, pull requests for performance improvements will probably not be accepted
|
||||
either, as this "reference implementation" tries to be as easy to read as possible.
|
||||
|
||||
|
||||
## Tools
|
||||
|
||||
- [floooh/qoiview](https://github.com/floooh/qoiview) - native QOI viewer
|
||||
- [pfusik/qoi-fu](https://github.com/pfusik/qoi-fu/releases) - QOI Plugin installer for Windows Explorer, Finder, GNOME, GIMP, Paint.NET and XnView
|
||||
- [iOrange/QoiFileTypeNet](https://github.com/iOrange/QoiFileTypeNet/releases) - QOI Plugin for Paint.NET
|
||||
- [iOrange/QOIThumbnailProvider](https://github.com/iOrange/QOIThumbnailProvider) - Add thumbnails for QOI images in Windows Explorer
|
||||
- [Tom94/tev](https://github.com/Tom94/tev) - another native QOI viewer (allows pixel peeping and comparison with other image formats)
|
||||
- [qoiconverterx](https://apps.apple.com/br/app/qoiconverterx/id1602159820) QOI <=> PNG converter available on the Mac App Store
|
||||
- [kaetemi/qoi-ma](https://github.com/kaetemi/qoi-max) - QOI Bitmap I/O Plugin for 3ds Max
|
||||
- [rtexviewer](https://raylibtech.itch.io/rtexviewer) - texture viewer, supports QOI
|
||||
- [rtexpacker](https://raylibtech.itch.io/rtexpacker) - texture packer, supports QOI
|
||||
- [DmitriySalnikov/godot_qoi](https://github.com/DmitriySalnikov/godot_qoi) - QOI GDNative Addon for Godot Engine
|
||||
- [dan9er/farbfeld-convert-qoi](https://gitlab.com/dan9er/farbfeld-convert-qoi) - QOI <=> farbfeld converter
|
||||
- [LTMX/Unity.QOI](https://github.com/LTMX/Unity.QOI) - QOI Importer and Exporter for the Unity3D Game Engine
|
||||
- [Ben1138/unity-qoi](https://github.com/Ben1138/unity-qoi) - QOI Importer(only) support for the Unity3D Game Engine
|
||||
- [xiaozhuai/jetbrains-qo](https://github.com/xiaozhuai/jetbrains-qoi) - [QOI Support](https://plugins.jetbrains.com/plugin/19352-qoi-support) for Jetbrains' IDE.
|
||||
- [serge-ivamov/QOIql](https://github.com/serge-ivamov/QOIql) - MacOS QuickLook plugin for QOI
|
||||
- [tobozo/kde-thumbnailer-qoi](https://github.com/tobozo/kde-thumbnailer-qoi) - QOI Thumbnailer for KDE
|
||||
- [walksanatora/qoi-thumbnailer-nemo](https://github.com/walksanatora/qoi-thumbnailer-nemo) - QOI Thumbnailer for Nemo
|
||||
- [hzeller/timg](https://github.com/hzeller/timg) - a terminal image viewer with QOI support
|
||||
- [LuisAlfredo92/Super-QOI-converter](https://github.com/LuisAlfredo92/Super-QOI-converter "LuisAlfredo92/Super-QOI-converter") - A program to convert JPG, JPEG, BMP, and PNG to QOI
|
||||
- [Console version](https://github.com/LuisAlfredo92/Super-QOI-converter-Console- "Console version"): Available for Linux, OSX and Windows
|
||||
- [GUI version](https://github.com/LuisAlfredo92/Super-QOI-converter-GUI- "GUI version"): Available only for windows
|
||||
- [tacent view](https://github.com/bluescan/tacentview) - Image and texture viewer, supports QOI
|
||||
- [colemanrgb/qoi2spr](https://github.com/colemanrgb/qoi2spr) - A variety of applications for decoding and encoding of QOI images on [RISC OS](https://www.riscosopen.org/)
|
||||
|
||||
## Implementations & Bindings of QOI
|
||||
|
||||
- [pfusik/qoi-fu](https://github.com/pfusik/qoi-fu) - Fusion, transpiling to C, C++, C#, D, Java, JavaScript, Python, Swift and TypeScript
|
||||
- [kodonnell/qoi](https://github.com/kodonnell/qoi) - Python
|
||||
- [JaffaKetchup/dqoi](https://github.com/JaffaKetchup/dqoi) - Dart, with Flutter support
|
||||
- [Cr4xy/lua-qoi](https://github.com/Cr4xy/lua-qoi) - Lua
|
||||
- [superzazu/SDL_QOI](https://github.com/superzazu/SDL_QOI) - C, SDL2 bindings
|
||||
- [saharNooby/qoi-java](https://github.com/saharNooby/qoi-java) - Java
|
||||
- [MasterQ32/zig-qoi](https://github.com/MasterQ32/zig-qoi) - Zig
|
||||
- [rbino/qoix](https://github.com/rbino/qoix) - Elixir
|
||||
- [NUlliiON/QoiSharp](https://github.com/NUlliiON/QoiSharp) - C#
|
||||
- [aldanor/qoi-rust](https://github.com/aldanor/qoi-rust) - Rust
|
||||
- [zakarumych/rapid-qoi](https://github.com/zakarumych/rapid-qoi) - Rust
|
||||
- [takeyourhatoff/qoi](https://github.com/takeyourhatoff/qoi) - Go
|
||||
- [DosWorld/pasqoi](https://github.com/DosWorld/pasqoi) - Pascal
|
||||
- [elihwyma/Swift-QOI](https://github.com/elihwyma/Swift-QOI) - Swift
|
||||
- [xfmoulet/qoi](https://github.com/xfmoulet/qoi) - Go
|
||||
- [erratique.ch/qoic](https://erratique.ch/software/qoic) - OCaml
|
||||
- [arian/go-qoi](https://github.com/arian/go-qoi) - Go
|
||||
- [kchapelier/qoijs](https://github.com/kchapelier/qoijs) - JavaScript
|
||||
- [KristofferC/QOI.jl](https://github.com/KristofferC/QOI.jl) - Julia
|
||||
- [shadowMitia/libqoi](https://github.com/shadowMitia/libqoi) - C++
|
||||
- [MKCG/php-qoi](https://github.com/MKCG/php-qoi) - PHP
|
||||
- [LightHouseSoftware/qoiformats](https://github.com/LightHouseSoftware/qoiformats) - D
|
||||
- [mhoward540/qoi-nim](https://github.com/mhoward540/qoi-nim) - Nim
|
||||
- [wx257osn2/qoixx](https://github.com/wx257osn2/qoixx) - C++
|
||||
- [Tiefseetauchner/lr-paint](https://github.com/Tiefseetauchner/lr-paint) - Processing
|
||||
- [amstan/qoi-fpga](https://github.com/amstan/qoi-fpga) - FPGA: verilog
|
||||
- [musabkilic/qoi-decoder](https://github.com/musabkilic/qoi-decoder) - Python
|
||||
- [mathpn/py-qoi](https://github.com/mathpn/py-qoi) - Python
|
||||
- [JohannesFriedrich/qoi4R](https://github.com/JohannesFriedrich/qoi4R) - R
|
||||
- [shraiwi/mini-qoi](https://github.com/shraiwi/mini-qoi) - C, streaming decoder
|
||||
- [10maurycy10/libqoi/](https://github.com/10maurycy10/libqoi/) - Rust
|
||||
- [0xd34df00d/hsqoi](https://github.com/0xd34df00d/hsqoi) - Haskell
|
||||
- [418Coffee/qoi-v](https://github.com/418Coffee/qoi-v) - V
|
||||
- [Imagine-Programming/QoiImagePlugin](https://github.com/Imagine-Programming/QoiImagePlugin) - PureBasic
|
||||
- [Fabien-Chouteau/qoi-spark](https://github.com/Fabien-Chouteau/qoi-spark) - Ada/SPARK formally proven
|
||||
- [mzgreen/qoi-kotlin](https://github.com/mzgreen/qoi-kotlin) - Kotlin Multiplatform
|
||||
- [Aftersol/Simplified-QOI-Codec](https://github.com/Aftersol/Simplified-QOI-Codec) - C99, encoder and decoder, freestanding
|
||||
- [AuburnSounds/gamut](https://github.com/AuburnSounds/gamut) - D
|
||||
- [AngusJohnson/TQoiImage](https://github.com/AngusJohnson/TQoiImage) - Delphi
|
||||
- [MarkJeronimus/qoi-java-spi](https://github.com/MarkJeronimus/qoi-java-spi) - Java SPI
|
||||
- [aumouvantsillage/qoi-racket](https://github.com/aumouvantsillage/qoi-racket) - Racket
|
||||
- [rubikscraft/qoi-stream](https://github.com/rubikscraft/qoi-stream) - C99, one byte at a time streaming encoder and decoder
|
||||
- [rubikscraft/qoi-img](https://github.com/rubikscraft/qoi-img) - NodeJS typescript, bindings to both [QOIxx](https://github.com/wx257osn2/qoixx) and [qoi-stream](https://github.com/rubikscraft/qoi-stream)
|
||||
- [grego/hare-qoi](https://git.sr.ht/~grego/hare-qoi) - Hare
|
||||
- [MrNocole/ZTQOI](https://github.com/MrNocole/ZTQOI) - Objective-C
|
||||
- [bpanthi977/qoi](https://github.com/bpanthi977/qoi) - Common Lisp
|
||||
- [Floessie/pam2qoi](https://github.com/Floessie/pam2qoi) - C++
|
||||
- [SpeckyYT/spwn-qoi](https://github.com/SpeckyYT/spwn-qoi) - SPWN
|
||||
- [n00bmind/qoi](https://github.com/n00bmind/qoi) - Jai
|
||||
- [SixLabors/ImageSharp](https://github.com/SixLabors/ImageSharp) - C# image proccesing library
|
||||
- [zertovitch/gid](https://github.com/zertovitch/gid) - Ada
|
||||
- [nazrin/lil](https://codeberg.org/nazrin/lil) - Lua image library
|
||||
|
||||
## QOI Support in Other Software
|
||||
|
||||
- [Amiga OS QOI datatype](https://github.com/dgaw/qoi-datatype) - adds support for decoding QOI images to the Amiga operating system.
|
||||
- [SerenityOS](https://github.com/SerenityOS/serenity) - supports decoding QOI system wide through a custom [cpp implementation in LibGfx](https://github.com/SerenityOS/serenity/blob/master/Userland/Libraries/LibGfx/QOILoader.h)
|
||||
- [Raylib](https://github.com/raysan5/raylib) - supports decoding and encoding QOI textures through its [rtextures module](https://github.com/raysan5/raylib/blob/master/src/rtextures.c)
|
||||
- [Rebol3](https://github.com/Oldes/Rebol3/issues/39) - supports decoding and encoding QOI using a native codec
|
||||
- [c-ray](https://github.com/vkoskiv/c-ray) - supports QOI natively
|
||||
- [SAIL](https://sail.software) - image decoding library, supports decoding and encoding QOI images
|
||||
- [Orx](https://github.com/orx/orx) - 2D game engine, supports QOI natively
|
||||
- [IrfanView](https://www.irfanview.com) - supports decoding and encoding QOI through its Formats plugin
|
||||
- [ImageMagick](https://github.com/ImageMagick/ImageMagick) - supports decoding and encoding QOI, since 7.1.0-20
|
||||
- [barebox](https://barebox.org) - bootloader, supports decoding QOI images for splash logo, since v2022.03.0
|
||||
- [KorGE](https://korge.org) - & KorIM Kotlin 2D game engine and imaging library, supports decoding and encoding QOI natively since 2.7.0
|
||||
- [DOjS](https://github.com/SuperIlu/DOjS) - DOS JavaScript Canvas implementation supports loading QOI files
|
||||
- [XnView MP](https://www.xnview.com/en/xnviewmp/) - supports decoding QOI since 1.00
|
||||
- [ffmpeg](https://ffmpeg.org/) - supports decoding and encoding QOI since 5.1
|
||||
- [JPEGView](https://github.com/sylikc/jpegview) - lightweight Windows image viewer, supports decoding and encoding of QOI natively, since 1.1.44
|
||||
- [darktable](https://github.com/darktable-org/darktable) - photography workflow application and raw developer, supports decoding since 4.4.0
|
||||
- [KDE](https://kde.org) - supports decoding and encoding QOI images. Implemented in [KImageFormats](https://invent.kde.org/frameworks/kimageformats)
|
||||
- [EFL](https://www.enlightenment.org) - supports decoding and encoding QOI images since 1.27.
|
||||
- [Swingland](https://git.sr.ht/~phlash/swingland) - supports QOI decoding/loading via the `ImageIO` API of this Java Swing reimplemenation for Wayland
|
||||
- [Imagine](https://www.nyam.pe.kr/dev/imagine/) - supports decoding and encoding QOI images since 1.3.9
|
||||
- [Uiua](https://uiua.org) - supports decoding and encoding QOI images since 0.8.0
|
||||
|
||||
## Packages
|
||||
|
||||
- [AUR](https://aur.archlinux.org/pkgbase/qoi-git/) - system-wide qoi.h, qoiconv and qoibench install as split packages.
|
||||
- [Debian](https://packages.debian.org/bookworm/source/qoi) - packages for binaries and qoi.h
|
||||
- [Ubuntu](https://launchpad.net/ubuntu/+source/qoi) - packages for binaries and qoi.h
|
||||
|
||||
Packages for other systems [tracked at Repology](https://repology.org/project/qoi/versions).
|
649
external/qoi/qoi/qoi.h
vendored
Normal file
649
external/qoi/qoi/qoi.h
vendored
Normal file
@ -0,0 +1,649 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2021, Dominic Szablewski - https://phoboslab.org
|
||||
SPDX-License-Identifier: MIT
|
||||
|
||||
|
||||
QOI - The "Quite OK Image" format for fast, lossless image compression
|
||||
|
||||
-- About
|
||||
|
||||
QOI encodes and decodes images in a lossless format. Compared to stb_image and
|
||||
stb_image_write QOI offers 20x-50x faster encoding, 3x-4x faster decoding and
|
||||
20% better compression.
|
||||
|
||||
|
||||
-- Synopsis
|
||||
|
||||
// Define `QOI_IMPLEMENTATION` in *one* C/C++ file before including this
|
||||
// library to create the implementation.
|
||||
|
||||
#define QOI_IMPLEMENTATION
|
||||
#include "qoi.h"
|
||||
|
||||
// Encode and store an RGBA buffer to the file system. The qoi_desc describes
|
||||
// the input pixel data.
|
||||
qoi_write("image_new.qoi", rgba_pixels, &(qoi_desc){
|
||||
.width = 1920,
|
||||
.height = 1080,
|
||||
.channels = 4,
|
||||
.colorspace = QOI_SRGB
|
||||
});
|
||||
|
||||
// Load and decode a QOI image from the file system into a 32bbp RGBA buffer.
|
||||
// The qoi_desc struct will be filled with the width, height, number of channels
|
||||
// and colorspace read from the file header.
|
||||
qoi_desc desc;
|
||||
void *rgba_pixels = qoi_read("image.qoi", &desc, 4);
|
||||
|
||||
|
||||
|
||||
-- Documentation
|
||||
|
||||
This library provides the following functions;
|
||||
- qoi_read -- read and decode a QOI file
|
||||
- qoi_decode -- decode the raw bytes of a QOI image from memory
|
||||
- qoi_write -- encode and write a QOI file
|
||||
- qoi_encode -- encode an rgba buffer into a QOI image in memory
|
||||
|
||||
See the function declaration below for the signature and more information.
|
||||
|
||||
If you don't want/need the qoi_read and qoi_write functions, you can define
|
||||
QOI_NO_STDIO before including this library.
|
||||
|
||||
This library uses malloc() and free(). To supply your own malloc implementation
|
||||
you can define QOI_MALLOC and QOI_FREE before including this library.
|
||||
|
||||
This library uses memset() to zero-initialize the index. To supply your own
|
||||
implementation you can define QOI_ZEROARR before including this library.
|
||||
|
||||
|
||||
-- Data Format
|
||||
|
||||
A QOI file has a 14 byte header, followed by any number of data "chunks" and an
|
||||
8-byte end marker.
|
||||
|
||||
struct qoi_header_t {
|
||||
char magic[4]; // magic bytes "qoif"
|
||||
uint32_t width; // image width in pixels (BE)
|
||||
uint32_t height; // image height in pixels (BE)
|
||||
uint8_t channels; // 3 = RGB, 4 = RGBA
|
||||
uint8_t colorspace; // 0 = sRGB with linear alpha, 1 = all channels linear
|
||||
};
|
||||
|
||||
Images are encoded row by row, left to right, top to bottom. The decoder and
|
||||
encoder start with {r: 0, g: 0, b: 0, a: 255} as the previous pixel value. An
|
||||
image is complete when all pixels specified by width * height have been covered.
|
||||
|
||||
Pixels are encoded as
|
||||
- a run of the previous pixel
|
||||
- an index into an array of previously seen pixels
|
||||
- a difference to the previous pixel value in r,g,b
|
||||
- full r,g,b or r,g,b,a values
|
||||
|
||||
The color channels are assumed to not be premultiplied with the alpha channel
|
||||
("un-premultiplied alpha").
|
||||
|
||||
A running array[64] (zero-initialized) of previously seen pixel values is
|
||||
maintained by the encoder and decoder. Each pixel that is seen by the encoder
|
||||
and decoder is put into this array at the position formed by a hash function of
|
||||
the color value. In the encoder, if the pixel value at the index matches the
|
||||
current pixel, this index position is written to the stream as QOI_OP_INDEX.
|
||||
The hash function for the index is:
|
||||
|
||||
index_position = (r * 3 + g * 5 + b * 7 + a * 11) % 64
|
||||
|
||||
Each chunk starts with a 2- or 8-bit tag, followed by a number of data bits. The
|
||||
bit length of chunks is divisible by 8 - i.e. all chunks are byte aligned. All
|
||||
values encoded in these data bits have the most significant bit on the left.
|
||||
|
||||
The 8-bit tags have precedence over the 2-bit tags. A decoder must check for the
|
||||
presence of an 8-bit tag first.
|
||||
|
||||
The byte stream's end is marked with 7 0x00 bytes followed a single 0x01 byte.
|
||||
|
||||
|
||||
The possible chunks are:
|
||||
|
||||
|
||||
.- QOI_OP_INDEX ----------.
|
||||
| Byte[0] |
|
||||
| 7 6 5 4 3 2 1 0 |
|
||||
|-------+-----------------|
|
||||
| 0 0 | index |
|
||||
`-------------------------`
|
||||
2-bit tag b00
|
||||
6-bit index into the color index array: 0..63
|
||||
|
||||
A valid encoder must not issue 2 or more consecutive QOI_OP_INDEX chunks to the
|
||||
same index. QOI_OP_RUN should be used instead.
|
||||
|
||||
|
||||
.- QOI_OP_DIFF -----------.
|
||||
| Byte[0] |
|
||||
| 7 6 5 4 3 2 1 0 |
|
||||
|-------+-----+-----+-----|
|
||||
| 0 1 | dr | dg | db |
|
||||
`-------------------------`
|
||||
2-bit tag b01
|
||||
2-bit red channel difference from the previous pixel between -2..1
|
||||
2-bit green channel difference from the previous pixel between -2..1
|
||||
2-bit blue channel difference from the previous pixel between -2..1
|
||||
|
||||
The difference to the current channel values are using a wraparound operation,
|
||||
so "1 - 2" will result in 255, while "255 + 1" will result in 0.
|
||||
|
||||
Values are stored as unsigned integers with a bias of 2. E.g. -2 is stored as
|
||||
0 (b00). 1 is stored as 3 (b11).
|
||||
|
||||
The alpha value remains unchanged from the previous pixel.
|
||||
|
||||
|
||||
.- QOI_OP_LUMA -------------------------------------.
|
||||
| Byte[0] | Byte[1] |
|
||||
| 7 6 5 4 3 2 1 0 | 7 6 5 4 3 2 1 0 |
|
||||
|-------+-----------------+-------------+-----------|
|
||||
| 1 0 | green diff | dr - dg | db - dg |
|
||||
`---------------------------------------------------`
|
||||
2-bit tag b10
|
||||
6-bit green channel difference from the previous pixel -32..31
|
||||
4-bit red channel difference minus green channel difference -8..7
|
||||
4-bit blue channel difference minus green channel difference -8..7
|
||||
|
||||
The green channel is used to indicate the general direction of change and is
|
||||
encoded in 6 bits. The red and blue channels (dr and db) base their diffs off
|
||||
of the green channel difference and are encoded in 4 bits. I.e.:
|
||||
dr_dg = (cur_px.r - prev_px.r) - (cur_px.g - prev_px.g)
|
||||
db_dg = (cur_px.b - prev_px.b) - (cur_px.g - prev_px.g)
|
||||
|
||||
The difference to the current channel values are using a wraparound operation,
|
||||
so "10 - 13" will result in 253, while "250 + 7" will result in 1.
|
||||
|
||||
Values are stored as unsigned integers with a bias of 32 for the green channel
|
||||
and a bias of 8 for the red and blue channel.
|
||||
|
||||
The alpha value remains unchanged from the previous pixel.
|
||||
|
||||
|
||||
.- QOI_OP_RUN ------------.
|
||||
| Byte[0] |
|
||||
| 7 6 5 4 3 2 1 0 |
|
||||
|-------+-----------------|
|
||||
| 1 1 | run |
|
||||
`-------------------------`
|
||||
2-bit tag b11
|
||||
6-bit run-length repeating the previous pixel: 1..62
|
||||
|
||||
The run-length is stored with a bias of -1. Note that the run-lengths 63 and 64
|
||||
(b111110 and b111111) are illegal as they are occupied by the QOI_OP_RGB and
|
||||
QOI_OP_RGBA tags.
|
||||
|
||||
|
||||
.- QOI_OP_RGB ------------------------------------------.
|
||||
| Byte[0] | Byte[1] | Byte[2] | Byte[3] |
|
||||
| 7 6 5 4 3 2 1 0 | 7 .. 0 | 7 .. 0 | 7 .. 0 |
|
||||
|-------------------------+---------+---------+---------|
|
||||
| 1 1 1 1 1 1 1 0 | red | green | blue |
|
||||
`-------------------------------------------------------`
|
||||
8-bit tag b11111110
|
||||
8-bit red channel value
|
||||
8-bit green channel value
|
||||
8-bit blue channel value
|
||||
|
||||
The alpha value remains unchanged from the previous pixel.
|
||||
|
||||
|
||||
.- QOI_OP_RGBA ---------------------------------------------------.
|
||||
| Byte[0] | Byte[1] | Byte[2] | Byte[3] | Byte[4] |
|
||||
| 7 6 5 4 3 2 1 0 | 7 .. 0 | 7 .. 0 | 7 .. 0 | 7 .. 0 |
|
||||
|-------------------------+---------+---------+---------+---------|
|
||||
| 1 1 1 1 1 1 1 1 | red | green | blue | alpha |
|
||||
`-----------------------------------------------------------------`
|
||||
8-bit tag b11111111
|
||||
8-bit red channel value
|
||||
8-bit green channel value
|
||||
8-bit blue channel value
|
||||
8-bit alpha channel value
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
Header - Public functions */
|
||||
|
||||
#ifndef QOI_H
|
||||
#define QOI_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* A pointer to a qoi_desc struct has to be supplied to all of qoi's functions.
|
||||
It describes either the input format (for qoi_write and qoi_encode), or is
|
||||
filled with the description read from the file header (for qoi_read and
|
||||
qoi_decode).
|
||||
|
||||
The colorspace in this qoi_desc is an enum where
|
||||
0 = sRGB, i.e. gamma scaled RGB channels and a linear alpha channel
|
||||
1 = all channels are linear
|
||||
You may use the constants QOI_SRGB or QOI_LINEAR. The colorspace is purely
|
||||
informative. It will be saved to the file header, but does not affect
|
||||
how chunks are en-/decoded. */
|
||||
|
||||
#define QOI_SRGB 0
|
||||
#define QOI_LINEAR 1
|
||||
|
||||
typedef struct {
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
unsigned char channels;
|
||||
unsigned char colorspace;
|
||||
} qoi_desc;
|
||||
|
||||
#ifndef QOI_NO_STDIO
|
||||
|
||||
/* Encode raw RGB or RGBA pixels into a QOI image and write it to the file
|
||||
system. The qoi_desc struct must be filled with the image width, height,
|
||||
number of channels (3 = RGB, 4 = RGBA) and the colorspace.
|
||||
|
||||
The function returns 0 on failure (invalid parameters, or fopen or malloc
|
||||
failed) or the number of bytes written on success. */
|
||||
|
||||
int qoi_write(const char *filename, const void *data, const qoi_desc *desc);
|
||||
|
||||
|
||||
/* Read and decode a QOI image from the file system. If channels is 0, the
|
||||
number of channels from the file header is used. If channels is 3 or 4 the
|
||||
output format will be forced into this number of channels.
|
||||
|
||||
The function either returns NULL on failure (invalid data, or malloc or fopen
|
||||
failed) or a pointer to the decoded pixels. On success, the qoi_desc struct
|
||||
will be filled with the description from the file header.
|
||||
|
||||
The returned pixel data should be free()d after use. */
|
||||
|
||||
void *qoi_read(const char *filename, qoi_desc *desc, int channels);
|
||||
|
||||
#endif /* QOI_NO_STDIO */
|
||||
|
||||
|
||||
/* Encode raw RGB or RGBA pixels into a QOI image in memory.
|
||||
|
||||
The function either returns NULL on failure (invalid parameters or malloc
|
||||
failed) or a pointer to the encoded data on success. On success the out_len
|
||||
is set to the size in bytes of the encoded data.
|
||||
|
||||
The returned qoi data should be free()d after use. */
|
||||
|
||||
void *qoi_encode(const void *data, const qoi_desc *desc, int *out_len);
|
||||
|
||||
|
||||
/* Decode a QOI image from memory.
|
||||
|
||||
The function either returns NULL on failure (invalid parameters or malloc
|
||||
failed) or a pointer to the decoded pixels. On success, the qoi_desc struct
|
||||
is filled with the description from the file header.
|
||||
|
||||
The returned pixel data should be free()d after use. */
|
||||
|
||||
void *qoi_decode(const void *data, int size, qoi_desc *desc, int channels);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* QOI_H */
|
||||
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
Implementation */
|
||||
|
||||
#ifdef QOI_IMPLEMENTATION
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef QOI_MALLOC
|
||||
#define QOI_MALLOC(sz) malloc(sz)
|
||||
#define QOI_FREE(p) free(p)
|
||||
#endif
|
||||
#ifndef QOI_ZEROARR
|
||||
#define QOI_ZEROARR(a) memset((a),0,sizeof(a))
|
||||
#endif
|
||||
|
||||
#define QOI_OP_INDEX 0x00 /* 00xxxxxx */
|
||||
#define QOI_OP_DIFF 0x40 /* 01xxxxxx */
|
||||
#define QOI_OP_LUMA 0x80 /* 10xxxxxx */
|
||||
#define QOI_OP_RUN 0xc0 /* 11xxxxxx */
|
||||
#define QOI_OP_RGB 0xfe /* 11111110 */
|
||||
#define QOI_OP_RGBA 0xff /* 11111111 */
|
||||
|
||||
#define QOI_MASK_2 0xc0 /* 11000000 */
|
||||
|
||||
#define QOI_COLOR_HASH(C) (C.rgba.r*3 + C.rgba.g*5 + C.rgba.b*7 + C.rgba.a*11)
|
||||
#define QOI_MAGIC \
|
||||
(((unsigned int)'q') << 24 | ((unsigned int)'o') << 16 | \
|
||||
((unsigned int)'i') << 8 | ((unsigned int)'f'))
|
||||
#define QOI_HEADER_SIZE 14
|
||||
|
||||
/* 2GB is the max file size that this implementation can safely handle. We guard
|
||||
against anything larger than that, assuming the worst case with 5 bytes per
|
||||
pixel, rounded down to a nice clean value. 400 million pixels ought to be
|
||||
enough for anybody. */
|
||||
#define QOI_PIXELS_MAX ((unsigned int)400000000)
|
||||
|
||||
typedef union {
|
||||
struct { unsigned char r, g, b, a; } rgba;
|
||||
unsigned int v;
|
||||
} qoi_rgba_t;
|
||||
|
||||
static const unsigned char qoi_padding[8] = {0,0,0,0,0,0,0,1};
|
||||
|
||||
static void qoi_write_32(unsigned char *bytes, int *p, unsigned int v) {
|
||||
bytes[(*p)++] = (0xff000000 & v) >> 24;
|
||||
bytes[(*p)++] = (0x00ff0000 & v) >> 16;
|
||||
bytes[(*p)++] = (0x0000ff00 & v) >> 8;
|
||||
bytes[(*p)++] = (0x000000ff & v);
|
||||
}
|
||||
|
||||
static unsigned int qoi_read_32(const unsigned char *bytes, int *p) {
|
||||
unsigned int a = bytes[(*p)++];
|
||||
unsigned int b = bytes[(*p)++];
|
||||
unsigned int c = bytes[(*p)++];
|
||||
unsigned int d = bytes[(*p)++];
|
||||
return a << 24 | b << 16 | c << 8 | d;
|
||||
}
|
||||
|
||||
void *qoi_encode(const void *data, const qoi_desc *desc, int *out_len) {
|
||||
int i, max_size, p, run;
|
||||
int px_len, px_end, px_pos, channels;
|
||||
unsigned char *bytes;
|
||||
const unsigned char *pixels;
|
||||
qoi_rgba_t index[64];
|
||||
qoi_rgba_t px, px_prev;
|
||||
|
||||
if (
|
||||
data == NULL || out_len == NULL || desc == NULL ||
|
||||
desc->width == 0 || desc->height == 0 ||
|
||||
desc->channels < 3 || desc->channels > 4 ||
|
||||
desc->colorspace > 1 ||
|
||||
desc->height >= QOI_PIXELS_MAX / desc->width
|
||||
) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
max_size =
|
||||
desc->width * desc->height * (desc->channels + 1) +
|
||||
QOI_HEADER_SIZE + sizeof(qoi_padding);
|
||||
|
||||
p = 0;
|
||||
bytes = (unsigned char *) QOI_MALLOC(max_size);
|
||||
if (!bytes) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
qoi_write_32(bytes, &p, QOI_MAGIC);
|
||||
qoi_write_32(bytes, &p, desc->width);
|
||||
qoi_write_32(bytes, &p, desc->height);
|
||||
bytes[p++] = desc->channels;
|
||||
bytes[p++] = desc->colorspace;
|
||||
|
||||
|
||||
pixels = (const unsigned char *)data;
|
||||
|
||||
QOI_ZEROARR(index);
|
||||
|
||||
run = 0;
|
||||
px_prev.rgba.r = 0;
|
||||
px_prev.rgba.g = 0;
|
||||
px_prev.rgba.b = 0;
|
||||
px_prev.rgba.a = 255;
|
||||
px = px_prev;
|
||||
|
||||
px_len = desc->width * desc->height * desc->channels;
|
||||
px_end = px_len - desc->channels;
|
||||
channels = desc->channels;
|
||||
|
||||
for (px_pos = 0; px_pos < px_len; px_pos += channels) {
|
||||
px.rgba.r = pixels[px_pos + 0];
|
||||
px.rgba.g = pixels[px_pos + 1];
|
||||
px.rgba.b = pixels[px_pos + 2];
|
||||
|
||||
if (channels == 4) {
|
||||
px.rgba.a = pixels[px_pos + 3];
|
||||
}
|
||||
|
||||
if (px.v == px_prev.v) {
|
||||
run++;
|
||||
if (run == 62 || px_pos == px_end) {
|
||||
bytes[p++] = QOI_OP_RUN | (run - 1);
|
||||
run = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
int index_pos;
|
||||
|
||||
if (run > 0) {
|
||||
bytes[p++] = QOI_OP_RUN | (run - 1);
|
||||
run = 0;
|
||||
}
|
||||
|
||||
index_pos = QOI_COLOR_HASH(px) % 64;
|
||||
|
||||
if (index[index_pos].v == px.v) {
|
||||
bytes[p++] = QOI_OP_INDEX | index_pos;
|
||||
}
|
||||
else {
|
||||
index[index_pos] = px;
|
||||
|
||||
if (px.rgba.a == px_prev.rgba.a) {
|
||||
signed char vr = px.rgba.r - px_prev.rgba.r;
|
||||
signed char vg = px.rgba.g - px_prev.rgba.g;
|
||||
signed char vb = px.rgba.b - px_prev.rgba.b;
|
||||
|
||||
signed char vg_r = vr - vg;
|
||||
signed char vg_b = vb - vg;
|
||||
|
||||
if (
|
||||
vr > -3 && vr < 2 &&
|
||||
vg > -3 && vg < 2 &&
|
||||
vb > -3 && vb < 2
|
||||
) {
|
||||
bytes[p++] = QOI_OP_DIFF | (vr + 2) << 4 | (vg + 2) << 2 | (vb + 2);
|
||||
}
|
||||
else if (
|
||||
vg_r > -9 && vg_r < 8 &&
|
||||
vg > -33 && vg < 32 &&
|
||||
vg_b > -9 && vg_b < 8
|
||||
) {
|
||||
bytes[p++] = QOI_OP_LUMA | (vg + 32);
|
||||
bytes[p++] = (vg_r + 8) << 4 | (vg_b + 8);
|
||||
}
|
||||
else {
|
||||
bytes[p++] = QOI_OP_RGB;
|
||||
bytes[p++] = px.rgba.r;
|
||||
bytes[p++] = px.rgba.g;
|
||||
bytes[p++] = px.rgba.b;
|
||||
}
|
||||
}
|
||||
else {
|
||||
bytes[p++] = QOI_OP_RGBA;
|
||||
bytes[p++] = px.rgba.r;
|
||||
bytes[p++] = px.rgba.g;
|
||||
bytes[p++] = px.rgba.b;
|
||||
bytes[p++] = px.rgba.a;
|
||||
}
|
||||
}
|
||||
}
|
||||
px_prev = px;
|
||||
}
|
||||
|
||||
for (i = 0; i < (int)sizeof(qoi_padding); i++) {
|
||||
bytes[p++] = qoi_padding[i];
|
||||
}
|
||||
|
||||
*out_len = p;
|
||||
return bytes;
|
||||
}
|
||||
|
||||
void *qoi_decode(const void *data, int size, qoi_desc *desc, int channels) {
|
||||
const unsigned char *bytes;
|
||||
unsigned int header_magic;
|
||||
unsigned char *pixels;
|
||||
qoi_rgba_t index[64];
|
||||
qoi_rgba_t px;
|
||||
int px_len, chunks_len, px_pos;
|
||||
int p = 0, run = 0;
|
||||
|
||||
if (
|
||||
data == NULL || desc == NULL ||
|
||||
(channels != 0 && channels != 3 && channels != 4) ||
|
||||
size < QOI_HEADER_SIZE + (int)sizeof(qoi_padding)
|
||||
) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bytes = (const unsigned char *)data;
|
||||
|
||||
header_magic = qoi_read_32(bytes, &p);
|
||||
desc->width = qoi_read_32(bytes, &p);
|
||||
desc->height = qoi_read_32(bytes, &p);
|
||||
desc->channels = bytes[p++];
|
||||
desc->colorspace = bytes[p++];
|
||||
|
||||
if (
|
||||
desc->width == 0 || desc->height == 0 ||
|
||||
desc->channels < 3 || desc->channels > 4 ||
|
||||
desc->colorspace > 1 ||
|
||||
header_magic != QOI_MAGIC ||
|
||||
desc->height >= QOI_PIXELS_MAX / desc->width
|
||||
) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (channels == 0) {
|
||||
channels = desc->channels;
|
||||
}
|
||||
|
||||
px_len = desc->width * desc->height * channels;
|
||||
pixels = (unsigned char *) QOI_MALLOC(px_len);
|
||||
if (!pixels) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
QOI_ZEROARR(index);
|
||||
px.rgba.r = 0;
|
||||
px.rgba.g = 0;
|
||||
px.rgba.b = 0;
|
||||
px.rgba.a = 255;
|
||||
|
||||
chunks_len = size - (int)sizeof(qoi_padding);
|
||||
for (px_pos = 0; px_pos < px_len; px_pos += channels) {
|
||||
if (run > 0) {
|
||||
run--;
|
||||
}
|
||||
else if (p < chunks_len) {
|
||||
int b1 = bytes[p++];
|
||||
|
||||
if (b1 == QOI_OP_RGB) {
|
||||
px.rgba.r = bytes[p++];
|
||||
px.rgba.g = bytes[p++];
|
||||
px.rgba.b = bytes[p++];
|
||||
}
|
||||
else if (b1 == QOI_OP_RGBA) {
|
||||
px.rgba.r = bytes[p++];
|
||||
px.rgba.g = bytes[p++];
|
||||
px.rgba.b = bytes[p++];
|
||||
px.rgba.a = bytes[p++];
|
||||
}
|
||||
else if ((b1 & QOI_MASK_2) == QOI_OP_INDEX) {
|
||||
px = index[b1];
|
||||
}
|
||||
else if ((b1 & QOI_MASK_2) == QOI_OP_DIFF) {
|
||||
px.rgba.r += ((b1 >> 4) & 0x03) - 2;
|
||||
px.rgba.g += ((b1 >> 2) & 0x03) - 2;
|
||||
px.rgba.b += ( b1 & 0x03) - 2;
|
||||
}
|
||||
else if ((b1 & QOI_MASK_2) == QOI_OP_LUMA) {
|
||||
int b2 = bytes[p++];
|
||||
int vg = (b1 & 0x3f) - 32;
|
||||
px.rgba.r += vg - 8 + ((b2 >> 4) & 0x0f);
|
||||
px.rgba.g += vg;
|
||||
px.rgba.b += vg - 8 + (b2 & 0x0f);
|
||||
}
|
||||
else if ((b1 & QOI_MASK_2) == QOI_OP_RUN) {
|
||||
run = (b1 & 0x3f);
|
||||
}
|
||||
|
||||
index[QOI_COLOR_HASH(px) % 64] = px;
|
||||
}
|
||||
|
||||
pixels[px_pos + 0] = px.rgba.r;
|
||||
pixels[px_pos + 1] = px.rgba.g;
|
||||
pixels[px_pos + 2] = px.rgba.b;
|
||||
|
||||
if (channels == 4) {
|
||||
pixels[px_pos + 3] = px.rgba.a;
|
||||
}
|
||||
}
|
||||
|
||||
return pixels;
|
||||
}
|
||||
|
||||
#ifndef QOI_NO_STDIO
|
||||
#include <stdio.h>
|
||||
|
||||
int qoi_write(const char *filename, const void *data, const qoi_desc *desc) {
|
||||
FILE *f = fopen(filename, "wb");
|
||||
int size, err;
|
||||
void *encoded;
|
||||
|
||||
if (!f) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
encoded = qoi_encode(data, desc, &size);
|
||||
if (!encoded) {
|
||||
fclose(f);
|
||||
return 0;
|
||||
}
|
||||
|
||||
fwrite(encoded, 1, size, f);
|
||||
fflush(f);
|
||||
err = ferror(f);
|
||||
fclose(f);
|
||||
|
||||
QOI_FREE(encoded);
|
||||
return err ? 0 : size;
|
||||
}
|
||||
|
||||
void *qoi_read(const char *filename, qoi_desc *desc, int channels) {
|
||||
FILE *f = fopen(filename, "rb");
|
||||
int size, bytes_read;
|
||||
void *pixels, *data;
|
||||
|
||||
if (!f) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fseek(f, 0, SEEK_END);
|
||||
size = ftell(f);
|
||||
if (size <= 0 || fseek(f, 0, SEEK_SET) != 0) {
|
||||
fclose(f);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
data = QOI_MALLOC(size);
|
||||
if (!data) {
|
||||
fclose(f);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bytes_read = fread(data, 1, size, f);
|
||||
fclose(f);
|
||||
pixels = (bytes_read != size) ? NULL : qoi_decode(data, bytes_read, desc, channels);
|
||||
QOI_FREE(data);
|
||||
return pixels;
|
||||
}
|
||||
|
||||
#endif /* QOI_NO_STDIO */
|
||||
#endif /* QOI_IMPLEMENTATION */
|
610
external/qoi/qoi/qoibench.c
vendored
Normal file
610
external/qoi/qoi/qoibench.c
vendored
Normal file
@ -0,0 +1,610 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2021, Dominic Szablewski - https://phoboslab.org
|
||||
SPDX-License-Identifier: MIT
|
||||
|
||||
|
||||
Simple benchmark suite for png, stbi and qoi
|
||||
|
||||
Requires libpng, "stb_image.h" and "stb_image_write.h"
|
||||
Compile with:
|
||||
gcc qoibench.c -std=gnu99 -lpng -O3 -o qoibench
|
||||
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <dirent.h>
|
||||
#include <png.h>
|
||||
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#define STBI_ONLY_PNG
|
||||
#define STBI_NO_LINEAR
|
||||
#include "stb_image.h"
|
||||
|
||||
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
||||
#include "stb_image_write.h"
|
||||
|
||||
#define QOI_IMPLEMENTATION
|
||||
#include "qoi.h"
|
||||
|
||||
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Cross platform high resolution timer
|
||||
// From https://gist.github.com/ForeverZer0/0a4f80fc02b96e19380ebb7a3debbee5
|
||||
|
||||
#include <stdint.h>
|
||||
#if defined(__linux)
|
||||
#define HAVE_POSIX_TIMER
|
||||
#include <time.h>
|
||||
#ifdef CLOCK_MONOTONIC
|
||||
#define CLOCKID CLOCK_MONOTONIC
|
||||
#else
|
||||
#define CLOCKID CLOCK_REALTIME
|
||||
#endif
|
||||
#elif defined(__APPLE__)
|
||||
#define HAVE_MACH_TIMER
|
||||
#include <mach/mach_time.h>
|
||||
#elif defined(_WIN32)
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
static uint64_t ns() {
|
||||
static uint64_t is_init = 0;
|
||||
#if defined(__APPLE__)
|
||||
static mach_timebase_info_data_t info;
|
||||
if (0 == is_init) {
|
||||
mach_timebase_info(&info);
|
||||
is_init = 1;
|
||||
}
|
||||
uint64_t now;
|
||||
now = mach_absolute_time();
|
||||
now *= info.numer;
|
||||
now /= info.denom;
|
||||
return now;
|
||||
#elif defined(__linux)
|
||||
static struct timespec linux_rate;
|
||||
if (0 == is_init) {
|
||||
clock_getres(CLOCKID, &linux_rate);
|
||||
is_init = 1;
|
||||
}
|
||||
uint64_t now;
|
||||
struct timespec spec;
|
||||
clock_gettime(CLOCKID, &spec);
|
||||
now = spec.tv_sec * 1.0e9 + spec.tv_nsec;
|
||||
return now;
|
||||
#elif defined(_WIN32)
|
||||
static LARGE_INTEGER win_frequency;
|
||||
if (0 == is_init) {
|
||||
QueryPerformanceFrequency(&win_frequency);
|
||||
is_init = 1;
|
||||
}
|
||||
LARGE_INTEGER now;
|
||||
QueryPerformanceCounter(&now);
|
||||
return (uint64_t) ((1e9 * now.QuadPart) / win_frequency.QuadPart);
|
||||
#endif
|
||||
}
|
||||
|
||||
#define STRINGIFY(x) #x
|
||||
#define TOSTRING(x) STRINGIFY(x)
|
||||
#define ERROR(...) printf("abort at line " TOSTRING(__LINE__) ": " __VA_ARGS__); printf("\n"); exit(1)
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// libpng encode/decode wrappers
|
||||
// Seriously, who thought this was a good abstraction for an API to read/write
|
||||
// images?
|
||||
|
||||
typedef struct {
|
||||
int size;
|
||||
int capacity;
|
||||
unsigned char *data;
|
||||
} libpng_write_t;
|
||||
|
||||
void libpng_encode_callback(png_structp png_ptr, png_bytep data, png_size_t length) {
|
||||
libpng_write_t *write_data = (libpng_write_t*)png_get_io_ptr(png_ptr);
|
||||
if (write_data->size + length >= write_data->capacity) {
|
||||
ERROR("PNG write");
|
||||
}
|
||||
memcpy(write_data->data + write_data->size, data, length);
|
||||
write_data->size += length;
|
||||
}
|
||||
|
||||
void *libpng_encode(void *pixels, int w, int h, int channels, int *out_len) {
|
||||
png_structp png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
||||
if (!png) {
|
||||
ERROR("png_create_write_struct");
|
||||
}
|
||||
|
||||
png_infop info = png_create_info_struct(png);
|
||||
if (!info) {
|
||||
ERROR("png_create_info_struct");
|
||||
}
|
||||
|
||||
if (setjmp(png_jmpbuf(png))) {
|
||||
ERROR("png_jmpbuf");
|
||||
}
|
||||
|
||||
// Output is 8bit depth, RGBA format.
|
||||
png_set_IHDR(
|
||||
png,
|
||||
info,
|
||||
w, h,
|
||||
8,
|
||||
channels == 3 ? PNG_COLOR_TYPE_RGB : PNG_COLOR_TYPE_RGBA,
|
||||
PNG_INTERLACE_NONE,
|
||||
PNG_COMPRESSION_TYPE_DEFAULT,
|
||||
PNG_FILTER_TYPE_DEFAULT
|
||||
);
|
||||
|
||||
png_bytep row_pointers[h];
|
||||
for(int y = 0; y < h; y++){
|
||||
row_pointers[y] = ((unsigned char *)pixels + y * w * channels);
|
||||
}
|
||||
|
||||
libpng_write_t write_data = {
|
||||
.size = 0,
|
||||
.capacity = w * h * channels,
|
||||
.data = malloc(w * h * channels)
|
||||
};
|
||||
|
||||
png_set_rows(png, info, row_pointers);
|
||||
png_set_write_fn(png, &write_data, libpng_encode_callback, NULL);
|
||||
png_write_png(png, info, PNG_TRANSFORM_IDENTITY, NULL);
|
||||
|
||||
png_destroy_write_struct(&png, &info);
|
||||
|
||||
*out_len = write_data.size;
|
||||
return write_data.data;
|
||||
}
|
||||
|
||||
|
||||
typedef struct {
|
||||
int pos;
|
||||
int size;
|
||||
unsigned char *data;
|
||||
} libpng_read_t;
|
||||
|
||||
void png_decode_callback(png_structp png, png_bytep data, png_size_t length) {
|
||||
libpng_read_t *read_data = (libpng_read_t*)png_get_io_ptr(png);
|
||||
if (read_data->pos + length > read_data->size) {
|
||||
ERROR("PNG read %ld bytes at pos %d (size: %d)", length, read_data->pos, read_data->size);
|
||||
}
|
||||
memcpy(data, read_data->data + read_data->pos, length);
|
||||
read_data->pos += length;
|
||||
}
|
||||
|
||||
void png_warning_callback(png_structp png_ptr, png_const_charp warning_msg) {
|
||||
// Ignore warnings about sRGB profiles and such.
|
||||
}
|
||||
|
||||
void *libpng_decode(void *data, int size, int *out_w, int *out_h) {
|
||||
png_structp png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, png_warning_callback);
|
||||
if (!png) {
|
||||
ERROR("png_create_read_struct");
|
||||
}
|
||||
|
||||
png_infop info = png_create_info_struct(png);
|
||||
if (!info) {
|
||||
ERROR("png_create_info_struct");
|
||||
}
|
||||
|
||||
libpng_read_t read_data = {
|
||||
.pos = 0,
|
||||
.size = size,
|
||||
.data = data
|
||||
};
|
||||
|
||||
png_set_read_fn(png, &read_data, png_decode_callback);
|
||||
png_set_sig_bytes(png, 0);
|
||||
png_read_info(png, info);
|
||||
|
||||
png_uint_32 w, h;
|
||||
int bitDepth, colorType, interlaceType;
|
||||
png_get_IHDR(png, info, &w, &h, &bitDepth, &colorType, &interlaceType, NULL, NULL);
|
||||
|
||||
// 16 bit -> 8 bit
|
||||
png_set_strip_16(png);
|
||||
|
||||
// 1, 2, 4 bit -> 8 bit
|
||||
if (bitDepth < 8) {
|
||||
png_set_packing(png);
|
||||
}
|
||||
|
||||
if (colorType & PNG_COLOR_MASK_PALETTE) {
|
||||
png_set_expand(png);
|
||||
}
|
||||
|
||||
if (!(colorType & PNG_COLOR_MASK_COLOR)) {
|
||||
png_set_gray_to_rgb(png);
|
||||
}
|
||||
|
||||
// set paletted or RGB images with transparency to full alpha so we get RGBA
|
||||
if (png_get_valid(png, info, PNG_INFO_tRNS)) {
|
||||
png_set_tRNS_to_alpha(png);
|
||||
}
|
||||
|
||||
// make sure every pixel has an alpha value
|
||||
if (!(colorType & PNG_COLOR_MASK_ALPHA)) {
|
||||
png_set_filler(png, 255, PNG_FILLER_AFTER);
|
||||
}
|
||||
|
||||
png_read_update_info(png, info);
|
||||
|
||||
unsigned char* out = malloc(w * h * 4);
|
||||
*out_w = w;
|
||||
*out_h = h;
|
||||
|
||||
// png_uint_32 rowBytes = png_get_rowbytes(png, info);
|
||||
png_bytep row_pointers[h];
|
||||
for (png_uint_32 row = 0; row < h; row++ ) {
|
||||
row_pointers[row] = (png_bytep)(out + (row * w * 4));
|
||||
}
|
||||
|
||||
png_read_image(png, row_pointers);
|
||||
png_read_end(png, info);
|
||||
png_destroy_read_struct( &png, &info, NULL);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// stb_image encode callback
|
||||
|
||||
void stbi_write_callback(void *context, void *data, int size) {
|
||||
int *encoded_size = (int *)context;
|
||||
*encoded_size += size;
|
||||
// In theory we'd need to do another malloc(), memcpy() and free() here to
|
||||
// be fair to the other decode functions...
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// function to load a whole file into memory
|
||||
|
||||
void *fload(const char *path, int *out_size) {
|
||||
FILE *fh = fopen(path, "rb");
|
||||
if (!fh) {
|
||||
ERROR("Can't open file");
|
||||
}
|
||||
|
||||
fseek(fh, 0, SEEK_END);
|
||||
int size = ftell(fh);
|
||||
fseek(fh, 0, SEEK_SET);
|
||||
|
||||
void *buffer = malloc(size);
|
||||
if (!buffer) {
|
||||
ERROR("Malloc for %d bytes failed", size);
|
||||
}
|
||||
|
||||
if (!fread(buffer, size, 1, fh)) {
|
||||
ERROR("Can't read file %s", path);
|
||||
}
|
||||
fclose(fh);
|
||||
|
||||
*out_size = size;
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// benchmark runner
|
||||
|
||||
|
||||
int opt_runs = 1;
|
||||
int opt_nopng = 0;
|
||||
int opt_nowarmup = 0;
|
||||
int opt_noverify = 0;
|
||||
int opt_nodecode = 0;
|
||||
int opt_noencode = 0;
|
||||
int opt_norecurse = 0;
|
||||
int opt_onlytotals = 0;
|
||||
|
||||
enum {
|
||||
LIBPNG,
|
||||
STBI,
|
||||
QOI,
|
||||
BENCH_COUNT /* must be the last element */
|
||||
};
|
||||
static const char *const lib_names[BENCH_COUNT] = {
|
||||
// NOTE: pad with spaces so everything lines up properly
|
||||
[LIBPNG] = "libpng: ",
|
||||
[STBI] = "stbi: ",
|
||||
[QOI] = "qoi: ",
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
uint64_t size;
|
||||
uint64_t encode_time;
|
||||
uint64_t decode_time;
|
||||
} benchmark_lib_result_t;
|
||||
|
||||
typedef struct {
|
||||
int count;
|
||||
uint64_t raw_size;
|
||||
uint64_t px;
|
||||
int w;
|
||||
int h;
|
||||
benchmark_lib_result_t libs[BENCH_COUNT];
|
||||
} benchmark_result_t;
|
||||
|
||||
|
||||
void benchmark_print_result(benchmark_result_t res) {
|
||||
res.px /= res.count;
|
||||
res.raw_size /= res.count;
|
||||
|
||||
double px = res.px;
|
||||
printf(" decode ms encode ms decode mpps encode mpps size kb rate\n");
|
||||
for (int i = 0; i < BENCH_COUNT; ++i) {
|
||||
if (opt_nopng && (i == LIBPNG || i == STBI)) {
|
||||
continue;
|
||||
}
|
||||
res.libs[i].encode_time /= res.count;
|
||||
res.libs[i].decode_time /= res.count;
|
||||
res.libs[i].size /= res.count;
|
||||
printf(
|
||||
"%s %8.1f %8.1f %8.2f %8.2f %8ld %4.1f%%\n",
|
||||
lib_names[i],
|
||||
(double)res.libs[i].decode_time/1000000.0,
|
||||
(double)res.libs[i].encode_time/1000000.0,
|
||||
(res.libs[i].decode_time > 0 ? px / ((double)res.libs[i].decode_time/1000.0) : 0),
|
||||
(res.libs[i].encode_time > 0 ? px / ((double)res.libs[i].encode_time/1000.0) : 0),
|
||||
res.libs[i].size/1024,
|
||||
((double)res.libs[i].size/(double)res.raw_size) * 100.0
|
||||
);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
// Run __VA_ARGS__ a number of times and measure the time taken. The first
|
||||
// run is ignored.
|
||||
#define BENCHMARK_FN(NOWARMUP, RUNS, AVG_TIME, ...) \
|
||||
do { \
|
||||
uint64_t time = 0; \
|
||||
for (int i = NOWARMUP; i <= RUNS; i++) { \
|
||||
uint64_t time_start = ns(); \
|
||||
__VA_ARGS__ \
|
||||
uint64_t time_end = ns(); \
|
||||
if (i > 0) { \
|
||||
time += time_end - time_start; \
|
||||
} \
|
||||
} \
|
||||
AVG_TIME = time / RUNS; \
|
||||
} while (0)
|
||||
|
||||
|
||||
benchmark_result_t benchmark_image(const char *path) {
|
||||
int encoded_png_size;
|
||||
int encoded_qoi_size;
|
||||
int w;
|
||||
int h;
|
||||
int channels;
|
||||
|
||||
// Load the encoded PNG, encoded QOI and raw pixels into memory
|
||||
if(!stbi_info(path, &w, &h, &channels)) {
|
||||
ERROR("Error decoding header %s", path);
|
||||
}
|
||||
|
||||
if (channels != 3) {
|
||||
channels = 4;
|
||||
}
|
||||
|
||||
void *pixels = (void *)stbi_load(path, &w, &h, NULL, channels);
|
||||
void *encoded_png = fload(path, &encoded_png_size);
|
||||
void *encoded_qoi = qoi_encode(pixels, &(qoi_desc){
|
||||
.width = w,
|
||||
.height = h,
|
||||
.channels = channels,
|
||||
.colorspace = QOI_SRGB
|
||||
}, &encoded_qoi_size);
|
||||
|
||||
if (!pixels || !encoded_qoi || !encoded_png) {
|
||||
ERROR("Error encoding %s", path);
|
||||
}
|
||||
|
||||
// Verify QOI Output
|
||||
|
||||
if (!opt_noverify) {
|
||||
qoi_desc dc;
|
||||
void *pixels_qoi = qoi_decode(encoded_qoi, encoded_qoi_size, &dc, channels);
|
||||
if (memcmp(pixels, pixels_qoi, w * h * channels) != 0) {
|
||||
ERROR("QOI roundtrip pixel mismatch for %s", path);
|
||||
}
|
||||
free(pixels_qoi);
|
||||
}
|
||||
|
||||
|
||||
|
||||
benchmark_result_t res = {0};
|
||||
res.count = 1;
|
||||
res.raw_size = w * h * channels;
|
||||
res.px = w * h;
|
||||
res.w = w;
|
||||
res.h = h;
|
||||
|
||||
|
||||
// Decoding
|
||||
|
||||
if (!opt_nodecode) {
|
||||
if (!opt_nopng) {
|
||||
BENCHMARK_FN(opt_nowarmup, opt_runs, res.libs[LIBPNG].decode_time, {
|
||||
int dec_w, dec_h;
|
||||
void *dec_p = libpng_decode(encoded_png, encoded_png_size, &dec_w, &dec_h);
|
||||
free(dec_p);
|
||||
});
|
||||
|
||||
BENCHMARK_FN(opt_nowarmup, opt_runs, res.libs[STBI].decode_time, {
|
||||
int dec_w, dec_h, dec_channels;
|
||||
void *dec_p = stbi_load_from_memory(encoded_png, encoded_png_size, &dec_w, &dec_h, &dec_channels, 4);
|
||||
free(dec_p);
|
||||
});
|
||||
}
|
||||
|
||||
BENCHMARK_FN(opt_nowarmup, opt_runs, res.libs[QOI].decode_time, {
|
||||
qoi_desc desc;
|
||||
void *dec_p = qoi_decode(encoded_qoi, encoded_qoi_size, &desc, 4);
|
||||
free(dec_p);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// Encoding
|
||||
if (!opt_noencode) {
|
||||
if (!opt_nopng) {
|
||||
BENCHMARK_FN(opt_nowarmup, opt_runs, res.libs[LIBPNG].encode_time, {
|
||||
int enc_size;
|
||||
void *enc_p = libpng_encode(pixels, w, h, channels, &enc_size);
|
||||
res.libs[LIBPNG].size = enc_size;
|
||||
free(enc_p);
|
||||
});
|
||||
|
||||
BENCHMARK_FN(opt_nowarmup, opt_runs, res.libs[STBI].encode_time, {
|
||||
int enc_size = 0;
|
||||
stbi_write_png_to_func(stbi_write_callback, &enc_size, w, h, channels, pixels, 0);
|
||||
res.libs[STBI].size = enc_size;
|
||||
});
|
||||
}
|
||||
|
||||
BENCHMARK_FN(opt_nowarmup, opt_runs, res.libs[QOI].encode_time, {
|
||||
int enc_size;
|
||||
void *enc_p = qoi_encode(pixels, &(qoi_desc){
|
||||
.width = w,
|
||||
.height = h,
|
||||
.channels = channels,
|
||||
.colorspace = QOI_SRGB
|
||||
}, &enc_size);
|
||||
res.libs[QOI].size = enc_size;
|
||||
free(enc_p);
|
||||
});
|
||||
}
|
||||
|
||||
free(pixels);
|
||||
free(encoded_png);
|
||||
free(encoded_qoi);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void benchmark_directory(const char *path, benchmark_result_t *grand_total) {
|
||||
DIR *dir = opendir(path);
|
||||
if (!dir) {
|
||||
ERROR("Couldn't open directory %s", path);
|
||||
}
|
||||
|
||||
struct dirent *file;
|
||||
|
||||
if (!opt_norecurse) {
|
||||
for (int i = 0; (file = readdir(dir)) != NULL; i++) {
|
||||
if (
|
||||
file->d_type & DT_DIR &&
|
||||
strcmp(file->d_name, ".") != 0 &&
|
||||
strcmp(file->d_name, "..") != 0
|
||||
) {
|
||||
char subpath[1024];
|
||||
snprintf(subpath, 1024, "%s/%s", path, file->d_name);
|
||||
benchmark_directory(subpath, grand_total);
|
||||
}
|
||||
}
|
||||
rewinddir(dir);
|
||||
}
|
||||
|
||||
benchmark_result_t dir_total = {0};
|
||||
|
||||
int has_shown_head = 0;
|
||||
for (int i = 0; (file = readdir(dir)) != NULL; i++) {
|
||||
if (strcmp(file->d_name + strlen(file->d_name) - 4, ".png") != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!has_shown_head) {
|
||||
has_shown_head = 1;
|
||||
printf("## Benchmarking %s/*.png -- %d runs\n\n", path, opt_runs);
|
||||
}
|
||||
|
||||
char *file_path = malloc(strlen(file->d_name) + strlen(path)+8);
|
||||
sprintf(file_path, "%s/%s", path, file->d_name);
|
||||
|
||||
benchmark_result_t res = benchmark_image(file_path);
|
||||
|
||||
if (!opt_onlytotals) {
|
||||
printf("## %s size: %dx%d\n", file_path, res.w, res.h);
|
||||
benchmark_print_result(res);
|
||||
}
|
||||
|
||||
free(file_path);
|
||||
|
||||
dir_total.count++;
|
||||
dir_total.raw_size += res.raw_size;
|
||||
dir_total.px += res.px;
|
||||
for (int i = 0; i < BENCH_COUNT; ++i) {
|
||||
dir_total.libs[i].encode_time += res.libs[i].encode_time;
|
||||
dir_total.libs[i].decode_time += res.libs[i].decode_time;
|
||||
dir_total.libs[i].size += res.libs[i].size;
|
||||
}
|
||||
|
||||
grand_total->count++;
|
||||
grand_total->raw_size += res.raw_size;
|
||||
grand_total->px += res.px;
|
||||
for (int i = 0; i < BENCH_COUNT; ++i) {
|
||||
grand_total->libs[i].encode_time += res.libs[i].encode_time;
|
||||
grand_total->libs[i].decode_time += res.libs[i].decode_time;
|
||||
grand_total->libs[i].size += res.libs[i].size;
|
||||
}
|
||||
}
|
||||
closedir(dir);
|
||||
|
||||
if (dir_total.count > 0) {
|
||||
printf("## Total for %s\n", path);
|
||||
benchmark_print_result(dir_total);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
if (argc < 3) {
|
||||
printf("Usage: qoibench <iterations> <directory> [options]\n");
|
||||
printf("Options:\n");
|
||||
printf(" --nowarmup ... don't perform a warmup run\n");
|
||||
printf(" --nopng ...... don't run png encode/decode\n");
|
||||
printf(" --noverify ... don't verify qoi roundtrip\n");
|
||||
printf(" --noencode ... don't run encoders\n");
|
||||
printf(" --nodecode ... don't run decoders\n");
|
||||
printf(" --norecurse .. don't descend into directories\n");
|
||||
printf(" --onlytotals . don't print individual image results\n");
|
||||
printf("Examples\n");
|
||||
printf(" qoibench 10 images/textures/\n");
|
||||
printf(" qoibench 1 images/textures/ --nopng --nowarmup\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for (int i = 3; i < argc; i++) {
|
||||
if (strcmp(argv[i], "--nowarmup") == 0) { opt_nowarmup = 1; }
|
||||
else if (strcmp(argv[i], "--nopng") == 0) { opt_nopng = 1; }
|
||||
else if (strcmp(argv[i], "--noverify") == 0) { opt_noverify = 1; }
|
||||
else if (strcmp(argv[i], "--noencode") == 0) { opt_noencode = 1; }
|
||||
else if (strcmp(argv[i], "--nodecode") == 0) { opt_nodecode = 1; }
|
||||
else if (strcmp(argv[i], "--norecurse") == 0) { opt_norecurse = 1; }
|
||||
else if (strcmp(argv[i], "--onlytotals") == 0) { opt_onlytotals = 1; }
|
||||
else { ERROR("Unknown option %s", argv[i]); }
|
||||
}
|
||||
|
||||
opt_runs = atoi(argv[1]);
|
||||
if (opt_runs <=0) {
|
||||
ERROR("Invalid number of runs %d", opt_runs);
|
||||
}
|
||||
|
||||
benchmark_result_t grand_total = {0};
|
||||
benchmark_directory(argv[2], &grand_total);
|
||||
|
||||
if (grand_total.count > 0) {
|
||||
printf("# Grand total for %s\n", argv[2]);
|
||||
benchmark_print_result(grand_total);
|
||||
}
|
||||
else {
|
||||
printf("No images found in %s\n", argv[2]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
91
external/qoi/qoi/qoiconv.c
vendored
Normal file
91
external/qoi/qoi/qoiconv.c
vendored
Normal file
@ -0,0 +1,91 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2021, Dominic Szablewski - https://phoboslab.org
|
||||
SPDX-License-Identifier: MIT
|
||||
|
||||
|
||||
Command line tool to convert between png <> qoi format
|
||||
|
||||
Requires:
|
||||
-"stb_image.h" (https://github.com/nothings/stb/blob/master/stb_image.h)
|
||||
-"stb_image_write.h" (https://github.com/nothings/stb/blob/master/stb_image_write.h)
|
||||
-"qoi.h" (https://github.com/phoboslab/qoi/blob/master/qoi.h)
|
||||
|
||||
Compile with:
|
||||
gcc qoiconv.c -std=c99 -O3 -o qoiconv
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#define STBI_ONLY_PNG
|
||||
#define STBI_NO_LINEAR
|
||||
#include "stb_image.h"
|
||||
|
||||
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
||||
#include "stb_image_write.h"
|
||||
|
||||
#define QOI_IMPLEMENTATION
|
||||
#include "qoi.h"
|
||||
|
||||
|
||||
#define STR_ENDS_WITH(S, E) (strcmp(S + strlen(S) - (sizeof(E)-1), E) == 0)
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
if (argc < 3) {
|
||||
puts("Usage: qoiconv <infile> <outfile>");
|
||||
puts("Examples:");
|
||||
puts(" qoiconv input.png output.qoi");
|
||||
puts(" qoiconv input.qoi output.png");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void *pixels = NULL;
|
||||
int w, h, channels;
|
||||
if (STR_ENDS_WITH(argv[1], ".png")) {
|
||||
if(!stbi_info(argv[1], &w, &h, &channels)) {
|
||||
printf("Couldn't read header %s\n", argv[1]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Force all odd encodings to be RGBA
|
||||
if(channels != 3) {
|
||||
channels = 4;
|
||||
}
|
||||
|
||||
pixels = (void *)stbi_load(argv[1], &w, &h, NULL, channels);
|
||||
}
|
||||
else if (STR_ENDS_WITH(argv[1], ".qoi")) {
|
||||
qoi_desc desc;
|
||||
pixels = qoi_read(argv[1], &desc, 0);
|
||||
channels = desc.channels;
|
||||
w = desc.width;
|
||||
h = desc.height;
|
||||
}
|
||||
|
||||
if (pixels == NULL) {
|
||||
printf("Couldn't load/decode %s\n", argv[1]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int encoded = 0;
|
||||
if (STR_ENDS_WITH(argv[2], ".png")) {
|
||||
encoded = stbi_write_png(argv[2], w, h, channels, pixels, 0);
|
||||
}
|
||||
else if (STR_ENDS_WITH(argv[2], ".qoi")) {
|
||||
encoded = qoi_write(argv[2], pixels, &(qoi_desc){
|
||||
.width = w,
|
||||
.height = h,
|
||||
.channels = channels,
|
||||
.colorspace = QOI_SRGB
|
||||
});
|
||||
}
|
||||
|
||||
if (!encoded) {
|
||||
printf("Couldn't write/encode %s\n", argv[2]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
free(pixels);
|
||||
return 0;
|
||||
}
|
32
external/qoi/qoi/qoifuzz.c
vendored
Normal file
32
external/qoi/qoi/qoifuzz.c
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2021, Dominic Szablewski - https://phoboslab.org
|
||||
SPDX-License-Identifier: MIT
|
||||
|
||||
|
||||
clang fuzzing harness for qoi_decode
|
||||
|
||||
Compile and run with:
|
||||
clang -fsanitize=address,fuzzer -g -O0 qoifuzz.c && ./a.out
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#define QOI_IMPLEMENTATION
|
||||
#include "qoi.h"
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||
int w, h;
|
||||
if (size < 4) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
qoi_desc desc;
|
||||
void* decoded = qoi_decode((void*)(data + 4), (int)(size - 4), &desc, *((int *)data));
|
||||
if (decoded != NULL) {
|
||||
free(decoded);
|
||||
}
|
||||
return 0;
|
||||
}
|
2
external/solanaceae_contact
vendored
2
external/solanaceae_contact
vendored
Submodule external/solanaceae_contact updated: 2d73c7272c...e40271670b
2
external/solanaceae_message3
vendored
2
external/solanaceae_message3
vendored
Submodule external/solanaceae_message3 updated: 002aa00279...e6f4f18f00
2
external/solanaceae_plugin
vendored
2
external/solanaceae_plugin
vendored
Submodule external/solanaceae_plugin updated: 87b3d15a2b...82cfb6d492
2
external/solanaceae_tox
vendored
2
external/solanaceae_tox
vendored
Submodule external/solanaceae_tox updated: b2a3cb7052...ce81ef7cf7
2
external/solanaceae_toxcore
vendored
2
external/solanaceae_toxcore
vendored
Submodule external/solanaceae_toxcore updated: fa4298d790...cf3679018b
2
external/solanaceae_util
vendored
2
external/solanaceae_util
vendored
Submodule external/solanaceae_util updated: db57a7c5e9...d304d719e9
14
external/stb/stb/README.md
vendored
14
external/stb/stb/README.md
vendored
@ -5,16 +5,18 @@ stb
|
||||
|
||||
single-file public domain (or MIT licensed) libraries for C/C++
|
||||
|
||||
# This project discusses security-relevant bugs in public in Github Issues and Pull Requests, and it may take significant time for security fixes to be implemented or merged. If this poses an unreasonable risk to your project, do not use stb libraries.
|
||||
|
||||
Noteworthy:
|
||||
|
||||
* image loader: [stb_image.h](stb_image.h)
|
||||
* image writer: [stb_image_write.h](stb_image_write.h)
|
||||
* image resizer: [stb_image_resize.h](stb_image_resize.h)
|
||||
* image resizer: [stb_image_resize2.h](stb_image_resize2.h)
|
||||
* font text rasterizer: [stb_truetype.h](stb_truetype.h)
|
||||
* typesafe containers: [stb_ds.h](stb_ds.h)
|
||||
|
||||
Most libraries by stb, except: stb_dxt by Fabian "ryg" Giesen, stb_image_resize
|
||||
by Jorge L. "VinoBS" Rodriguez, and stb_sprintf by Jeff Roberts.
|
||||
Most libraries by stb, except: stb_dxt by Fabian "ryg" Giesen, original stb_image_resize
|
||||
by Jorge L. "VinoBS" Rodriguez, and stb_image_resize2 and stb_sprintf by Jeff Roberts.
|
||||
|
||||
<a name="stb_libs"></a>
|
||||
|
||||
@ -22,10 +24,10 @@ library | lastest version | category | LoC | description
|
||||
--------------------- | ---- | -------- | --- | --------------------------------
|
||||
**[stb_vorbis.c](stb_vorbis.c)** | 1.22 | audio | 5584 | decode ogg vorbis files from file/memory to float/16-bit signed output
|
||||
**[stb_hexwave.h](stb_hexwave.h)** | 0.5 | audio | 680 | audio waveform synthesizer
|
||||
**[stb_image.h](stb_image.h)** | 2.28 | graphics | 7987 | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC
|
||||
**[stb_image.h](stb_image.h)** | 2.29 | graphics | 7985 | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC
|
||||
**[stb_truetype.h](stb_truetype.h)** | 1.26 | graphics | 5077 | parse, decode, and rasterize characters from truetype fonts
|
||||
**[stb_image_write.h](stb_image_write.h)** | 1.16 | graphics | 1724 | image writing to disk: PNG, TGA, BMP
|
||||
**[stb_image_resize.h](stb_image_resize.h)** | 0.97 | graphics | 2634 | resize images larger/smaller with good quality
|
||||
**[stb_image_resize2.h](stb_image_resize2.h)** | 2.04 | graphics | 10325 | resize images larger/smaller with good quality
|
||||
**[stb_rect_pack.h](stb_rect_pack.h)** | 1.01 | graphics | 623 | simple 2D rectangle packer with decent quality
|
||||
**[stb_perlin.h](stb_perlin.h)** | 0.5 | graphics | 428 | perlin's revised simplex noise w/ different seeds
|
||||
**[stb_ds.h](stb_ds.h)** | 0.67 | utility | 1895 | typesafe dynamic array and hash tables for C, will compile in C++
|
||||
@ -43,7 +45,7 @@ library | lastest version | category | LoC | description
|
||||
**[stb_include.h](stb_include.h)** | 0.02 | misc | 295 | implement recursive #include support, particularly for GLSL
|
||||
|
||||
Total libraries: 21
|
||||
Total lines of C code: 43117
|
||||
Total lines of C code: 50806
|
||||
|
||||
|
||||
FAQ
|
||||
|
3
external/stb/stb/stb_image.h
vendored
3
external/stb/stb/stb_image.h
vendored
@ -1,4 +1,4 @@
|
||||
/* stb_image - v2.28 - public domain image loader - http://nothings.org/stb
|
||||
/* stb_image - v2.29 - public domain image loader - http://nothings.org/stb
|
||||
no warranty implied; use at your own risk
|
||||
|
||||
Do this:
|
||||
@ -48,6 +48,7 @@ LICENSE
|
||||
|
||||
RECENT REVISION HISTORY:
|
||||
|
||||
2.29 (2023-05-xx) optimizations
|
||||
2.28 (2023-01-29) many error fixes, security errors, just tons of stuff
|
||||
2.27 (2021-07-11) document stbi_info better, 16-bit PNM support, bug fixes
|
||||
2.26 (2020-07-13) many minor fixes
|
||||
|
10325
external/stb/stb/stb_image_resize2.h
vendored
Normal file
10325
external/stb/stb/stb_image_resize2.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
224
external/stb/stb/stb_image_resize_test/dotimings.c
vendored
Normal file
224
external/stb/stb/stb_image_resize_test/dotimings.c
vendored
Normal file
@ -0,0 +1,224 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
#define stop() __debugbreak()
|
||||
#include <windows.h>
|
||||
#define int64 __int64
|
||||
#pragma warning(disable:4127)
|
||||
|
||||
#define get_milliseconds GetTickCount
|
||||
|
||||
#else
|
||||
|
||||
#define stop() __builtin_trap()
|
||||
#define int64 long long
|
||||
|
||||
typedef unsigned int U32;
|
||||
typedef unsigned long long U64;
|
||||
|
||||
#include <time.h>
|
||||
static int get_milliseconds()
|
||||
{
|
||||
struct timespec ts;
|
||||
clock_gettime( CLOCK_MONOTONIC, &ts );
|
||||
return (U32) ( ( ((U64)(U32)ts.tv_sec) * 1000LL ) + (U64)(((U32)ts.tv_nsec+500000)/1000000) );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(TIME_SIMD)
|
||||
// default for most platforms
|
||||
#elif defined(TIME_SCALAR)
|
||||
#define STBIR_NO_SIMD
|
||||
#else
|
||||
#error You must define TIME_SIMD or TIME_SCALAR when compiling this file.
|
||||
#endif
|
||||
|
||||
#define STBIR_PROFILE
|
||||
#define STB_IMAGE_RESIZE_IMPLEMENTATION
|
||||
#define STBIR__V_FIRST_INFO_BUFFER v_info
|
||||
#include "stb_image_resize2.h" // new one!
|
||||
|
||||
#if defined(TIME_SIMD) && !defined(STBIR_SIMD)
|
||||
#error Timing SIMD, but scalar was ON!
|
||||
#endif
|
||||
|
||||
#if defined(TIME_SCALAR) && defined(STBIR_SIMD)
|
||||
#error Timing scalar, but SIMD was ON!
|
||||
#endif
|
||||
|
||||
#define HEADER 32
|
||||
|
||||
|
||||
static int file_write( const char *filename, void * buffer, size_t size )
|
||||
{
|
||||
FILE * f = fopen( filename, "wb" );
|
||||
if ( f == 0 ) return 0;
|
||||
if ( fwrite( buffer, 1, size, f) != size ) return 0;
|
||||
fclose(f);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int64 nresize( void * o, int ox, int oy, int op, void * i, int ix, int iy, int ip, int buf, int type, int edg, int flt )
|
||||
{
|
||||
STBIR_RESIZE resize;
|
||||
int t;
|
||||
int64 b;
|
||||
|
||||
stbir_resize_init( &resize, i, ix, iy, ip, o, ox, oy, op, buf, type );
|
||||
stbir_set_edgemodes( &resize, edg, edg );
|
||||
stbir_set_filters( &resize, flt, flt );
|
||||
|
||||
stbir_build_samplers_with_splits( &resize, 1 );
|
||||
|
||||
b = 0x7fffffffffffffffULL;
|
||||
for( t = 0 ; t < 16 ; t++ )
|
||||
{
|
||||
STBIR_PROFILE_INFO profile;
|
||||
int64 v;
|
||||
if(!stbir_resize_extended( &resize ) )
|
||||
stop();
|
||||
stbir_resize_extended_profile_info( &profile, &resize );
|
||||
v = profile.clocks[1]+profile.clocks[2];
|
||||
if ( v < b )
|
||||
{
|
||||
b = v;
|
||||
t = 0;
|
||||
}
|
||||
}
|
||||
|
||||
stbir_free_samplers( &resize );
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
|
||||
#define INSIZES 5
|
||||
#define TYPESCOUNT 5
|
||||
#define NUM 64
|
||||
|
||||
static const int sizes[INSIZES]={63,126,252,520,772};
|
||||
static const int types[TYPESCOUNT]={STBIR_1CHANNEL,STBIR_2CHANNEL,STBIR_RGB,STBIR_4CHANNEL,STBIR_RGBA};
|
||||
static const int effective[TYPESCOUNT]={1,2,3,4,7};
|
||||
|
||||
int main( int argc, char ** argv )
|
||||
{
|
||||
unsigned char * input;
|
||||
unsigned char * output;
|
||||
int dimensionx, dimensiony;
|
||||
int scalex, scaley;
|
||||
int totalms;
|
||||
int timing_count;
|
||||
int ir;
|
||||
int * file;
|
||||
int * ts;
|
||||
int64 totalcycles;
|
||||
|
||||
if ( argc != 6 )
|
||||
{
|
||||
printf("command: dotimings x_samps y_samps x_scale y_scale outfilename\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
input = malloc( 4*1200*1200 );
|
||||
memset( input, 0x80, 4*1200*1200 );
|
||||
output = malloc( 4*10000*10000ULL );
|
||||
|
||||
dimensionx = atoi( argv[1] );
|
||||
dimensiony = atoi( argv[2] );
|
||||
scalex = atoi( argv[3] );
|
||||
scaley = atoi( argv[4] );
|
||||
|
||||
timing_count = dimensionx * dimensiony * INSIZES * TYPESCOUNT;
|
||||
|
||||
file = malloc( sizeof(int) * ( 2 * timing_count + HEADER ) );
|
||||
ts = file + HEADER;
|
||||
|
||||
totalms = get_milliseconds();
|
||||
totalcycles = STBIR_PROFILE_FUNC();
|
||||
for( ir = 0 ; ir < INSIZES ; ir++ )
|
||||
{
|
||||
int ix, iy, ty;
|
||||
ix = iy = sizes[ir];
|
||||
|
||||
for( ty = 0 ; ty < TYPESCOUNT ; ty++ )
|
||||
{
|
||||
int h, hh;
|
||||
|
||||
h = 1;
|
||||
for( hh = 0 ; hh < dimensiony; hh++ )
|
||||
{
|
||||
int ww, w = 1;
|
||||
for( ww = 0 ; ww < dimensionx; ww++ )
|
||||
{
|
||||
int64 VF, HF;
|
||||
int good;
|
||||
|
||||
v_info.control_v_first = 2; // vertical first
|
||||
VF = nresize( output, w, h, (w*4*1)&~3, input, ix, iy, ix*4*1, types[ty], STBIR_TYPE_UINT8, STBIR_EDGE_CLAMP, STBIR_FILTER_MITCHELL );
|
||||
v_info.control_v_first = 1; // horizonal first
|
||||
HF = nresize( output, w, h, (w*4*1)&~3, input, ix, iy, ix*4*1, types[ty], STBIR_TYPE_UINT8, STBIR_EDGE_CLAMP, STBIR_FILTER_MITCHELL );
|
||||
|
||||
good = ( ((HF<=VF) && (!v_info.v_first)) || ((VF<=HF) && (v_info.v_first)));
|
||||
|
||||
// printf("\r%d,%d, %d,%d, %d, %I64d,%I64d, // Good: %c(%c-%d) CompEst: %.1f %.1f\n", ix, iy, w, h, ty, VF, HF, good?'y':'n', v_info.v_first?'v':'h', v_info.v_resize_classification, v_info.v_cost,v_info.h_cost );
|
||||
ts[0] = (int)VF;
|
||||
ts[1] = (int)HF;
|
||||
|
||||
ts += 2;
|
||||
|
||||
w += scalex;
|
||||
}
|
||||
printf(".");
|
||||
h += scaley;
|
||||
}
|
||||
}
|
||||
}
|
||||
totalms = get_milliseconds() - totalms;
|
||||
totalcycles = STBIR_PROFILE_FUNC() - totalcycles;
|
||||
|
||||
printf("\n");
|
||||
|
||||
file[0] = 'VFT1';
|
||||
|
||||
#if defined(_x86_64) || defined( __x86_64__ ) || defined( _M_X64 ) || defined(__x86_64) || defined(__SSE2__) || defined( _M_IX86_FP ) || defined(__i386) || defined( __i386__ ) || defined( _M_IX86 ) || defined( _X86_ )
|
||||
file[1] = 1; // x64
|
||||
#elif defined( _M_AMD64 ) || defined( __aarch64__ ) || defined( __arm64__ ) || defined(__ARM_NEON__) || defined(__ARM_NEON) || defined(__arm__) || defined( _M_ARM )
|
||||
file[1] = 2; // arm
|
||||
#else
|
||||
file[1] = 99; // who knows???
|
||||
#endif
|
||||
|
||||
#ifdef STBIR_SIMD8
|
||||
file[2] = 2; // simd-8
|
||||
#elif defined( STBIR_SIMD )
|
||||
file[2] = 1; // simd-4
|
||||
#else
|
||||
file[2] = 0; // nosimd
|
||||
#endif
|
||||
|
||||
file[3] = dimensionx; // dimx
|
||||
file[4] = dimensiony; // dimy
|
||||
file[5] = TYPESCOUNT; // channel types
|
||||
file[ 6] = types[0]; file[7] = types[1]; file[8] = types[2]; file[9] = types[3]; file[10] = types[4]; // buffer_type
|
||||
file[11] = effective[0]; file[12] = effective[1]; file[13] = effective[2]; file[14] = effective[3]; file[15] = effective[4]; // effective channels
|
||||
file[16] = INSIZES; // resizes
|
||||
file[17] = sizes[0]; file[18] = sizes[0]; // input sizes (w x h)
|
||||
file[19] = sizes[1]; file[20] = sizes[1];
|
||||
file[21] = sizes[2]; file[22] = sizes[2];
|
||||
file[23] = sizes[3]; file[24] = sizes[3];
|
||||
file[25] = sizes[4]; file[26] = sizes[4];
|
||||
file[27] = scalex; file[28] = scaley; // scale the dimx and dimy amount ( for(i=0;i<dimx) outputx = 1 + i*scalex; )
|
||||
file[29] = totalms;
|
||||
((int64*)(file+30))[0] = totalcycles;
|
||||
|
||||
if ( !file_write( argv[5], file, sizeof(int) * ( 2 * timing_count + HEADER ) ) )
|
||||
printf( "Error writing file: %s\n", argv[5] );
|
||||
else
|
||||
printf( "Successfully wrote timing file: %s\n", argv[5] );
|
||||
|
||||
return 0;
|
||||
}
|
2738
external/stb/stb/stb_image_resize_test/old_image_resize.h
vendored
Normal file
2738
external/stb/stb/stb_image_resize_test/old_image_resize.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
56
external/stb/stb/stb_image_resize_test/oldir.c
vendored
Normal file
56
external/stb/stb/stb_image_resize_test/oldir.c
vendored
Normal file
@ -0,0 +1,56 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define stop() __debugbreak()
|
||||
#else
|
||||
#define stop() __builtin_trap()
|
||||
#endif
|
||||
|
||||
//#define HEAVYTM
|
||||
#include "tm.h"
|
||||
|
||||
#define STBIR_SATURATE_INT
|
||||
#define STB_IMAGE_RESIZE_STATIC
|
||||
#define STB_IMAGE_RESIZE_IMPLEMENTATION
|
||||
#include "old_image_resize.h"
|
||||
|
||||
|
||||
static int types[4] = { STBIR_TYPE_UINT8, STBIR_TYPE_UINT8, STBIR_TYPE_UINT16, STBIR_TYPE_FLOAT };
|
||||
static int edges[4] = { STBIR_EDGE_CLAMP, STBIR_EDGE_REFLECT, STBIR_EDGE_ZERO, STBIR_EDGE_WRAP };
|
||||
static int flts[5] = { STBIR_FILTER_BOX, STBIR_FILTER_TRIANGLE, STBIR_FILTER_CUBICBSPLINE, STBIR_FILTER_CATMULLROM, STBIR_FILTER_MITCHELL };
|
||||
static int channels[20] = { 1, 2, 3, 4, 4,4, 2,2, 4,4, 2,2, 4,4, 2,2, 4,4, 2,2 };
|
||||
static int alphapos[20] = { -1, -1, -1, -1, 3,0, 1,0, 3,0, 1,0, 3,0, 1,0, 3,0, 1,0 };
|
||||
|
||||
|
||||
void oresize( void * o, int ox, int oy, int op, void * i, int ix, int iy, int ip, int buf, int type, int edg, int flt )
|
||||
{
|
||||
int t = types[type];
|
||||
int ic = channels[buf];
|
||||
int alpha = alphapos[buf];
|
||||
int e = edges[edg];
|
||||
int f = flts[flt];
|
||||
int space = ( type == 1 ) ? STBIR_COLORSPACE_SRGB : 0;
|
||||
int flags = ( buf >= 16 ) ? STBIR_FLAG_ALPHA_PREMULTIPLIED : ( ( buf >= 12 ) ? STBIR_FLAG_ALPHA_OUT_PREMULTIPLIED : ( ( buf >= 8 ) ? (STBIR_FLAG_ALPHA_PREMULTIPLIED|STBIR_FLAG_ALPHA_OUT_PREMULTIPLIED) : 0 ) );
|
||||
stbir_uint64 start;
|
||||
|
||||
ENTER( "Resize (old)" );
|
||||
start = tmGetAccumulationStart( tm_mask );
|
||||
|
||||
if(!stbir_resize( i, ix, iy, ip, o, ox, oy, op, t, ic, alpha, flags, e, e, f, f, space, 0 ) )
|
||||
stop();
|
||||
|
||||
#ifdef STBIR_PROFILE
|
||||
tmEmitAccumulationZone( 0, 0, (tm_uint64 *)&start, 0, oldprofile.named.setup, "Setup (old)" );
|
||||
tmEmitAccumulationZone( 0, 0, (tm_uint64 *)&start, 0, oldprofile.named.filters, "Filters (old)" );
|
||||
tmEmitAccumulationZone( 0, 0, (tm_uint64 *)&start, 0, oldprofile.named.looping, "Looping (old)" );
|
||||
tmEmitAccumulationZone( 0, 0, (tm_uint64 *)&start, 0, oldprofile.named.vertical, "Vertical (old)" );
|
||||
tmEmitAccumulationZone( 0, 0, (tm_uint64 *)&start, 0, oldprofile.named.horizontal, "Horizontal (old)" );
|
||||
tmEmitAccumulationZone( 0, 0, (tm_uint64 *)&start, 0, oldprofile.named.decode, "Scanline input (old)" );
|
||||
tmEmitAccumulationZone( 0, 0, (tm_uint64 *)&start, 0, oldprofile.named.encode, "Scanline output (old)" );
|
||||
tmEmitAccumulationZone( 0, 0, (tm_uint64 *)&start, 0, oldprofile.named.alpha, "Alpha weighting (old)" );
|
||||
tmEmitAccumulationZone( 0, 0, (tm_uint64 *)&start, 0, oldprofile.named.unalpha, "Alpha unweighting (old)" );
|
||||
#endif
|
||||
|
||||
LEAVE();
|
||||
}
|
992
external/stb/stb/stb_image_resize_test/stbirtest.c
vendored
Normal file
992
external/stb/stb/stb_image_resize_test/stbirtest.c
vendored
Normal file
@ -0,0 +1,992 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
//#define HEAVYTM
|
||||
#include "tm.h"
|
||||
|
||||
#ifdef RADUSETM3
|
||||
tm_api * g_tm_api;
|
||||
//#define PROFILE_MODE
|
||||
#endif
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define stop() __debugbreak()
|
||||
#include <windows.h>
|
||||
#define int64 __int64
|
||||
#define uint64 unsigned __int64
|
||||
#else
|
||||
#define stop() __builtin_trap()
|
||||
#define int64 long long
|
||||
#define uint64 unsigned long long
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable:4127)
|
||||
#endif
|
||||
|
||||
//#define NOCOMP
|
||||
|
||||
|
||||
//#define PROFILE_NEW_ONLY
|
||||
//#define PROFILE_MODE
|
||||
|
||||
|
||||
#if defined(_x86_64) || defined( __x86_64__ ) || defined( _M_X64 ) || defined(__x86_64) || defined(__SSE2__) || defined(STBIR_SSE) || defined( _M_IX86_FP ) || defined(__i386) || defined( __i386__ ) || defined( _M_IX86 ) || defined( _X86_ )
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
uint64 __rdtsc();
|
||||
#define __cycles() __rdtsc()
|
||||
|
||||
#else // non msvc
|
||||
|
||||
static inline uint64 __cycles()
|
||||
{
|
||||
unsigned int lo, hi;
|
||||
asm volatile ("rdtsc" : "=a" (lo), "=d" (hi) );
|
||||
return ( ( (uint64) hi ) << 32 ) | ( (uint64) lo );
|
||||
}
|
||||
|
||||
#endif // msvc
|
||||
|
||||
#elif defined( _M_ARM64 ) || defined( __aarch64__ ) || defined( __arm64__ ) || defined(__ARM_NEON__)
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
#define __cycles() _ReadStatusReg(ARM64_CNTVCT)
|
||||
|
||||
#else
|
||||
|
||||
static inline uint64 __cycles()
|
||||
{
|
||||
uint64 tsc;
|
||||
asm volatile("mrs %0, cntvct_el0" : "=r" (tsc));
|
||||
return tsc;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#else // x64, arm
|
||||
|
||||
#error Unknown platform for timing.
|
||||
|
||||
#endif //x64 and
|
||||
|
||||
|
||||
#ifdef PROFILE_MODE
|
||||
|
||||
#define STBIR_ASSERT(cond)
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef _DEBUG
|
||||
#undef STBIR_ASSERT
|
||||
#define STBIR_ASSERT(cond) { if (!(cond)) stop(); }
|
||||
#endif
|
||||
|
||||
|
||||
#define SHRINKBYW 2
|
||||
#define ZOOMBYW 2
|
||||
#define SHRINKBYH 2
|
||||
#define ZOOMBYH 2
|
||||
|
||||
|
||||
int mem_count = 0;
|
||||
|
||||
#ifdef TEST_WITH_VALLOC
|
||||
|
||||
#define STBIR__SEPARATE_ALLOCATIONS
|
||||
|
||||
#if TEST_WITH_LIMIT_AT_FRONT
|
||||
|
||||
void * wmalloc(SIZE_T size)
|
||||
{
|
||||
static unsigned int pagesize=0;
|
||||
void* p;
|
||||
SIZE_T s;
|
||||
|
||||
// get the page size, if we haven't yet
|
||||
if (pagesize==0)
|
||||
{
|
||||
SYSTEM_INFO si;
|
||||
GetSystemInfo(&si);
|
||||
pagesize=si.dwPageSize;
|
||||
}
|
||||
|
||||
// we need room for the size, 8 bytes to hide the original pointer and a
|
||||
// validation dword, and enough data to completely fill one page
|
||||
s=(size+(pagesize-1))&~(pagesize-1);
|
||||
|
||||
// allocate the size plus a page (for the guard)
|
||||
p=VirtualAlloc(0,(SIZE_T)s,MEM_RESERVE|MEM_COMMIT,PAGE_READWRITE);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
void wfree(void * ptr)
|
||||
{
|
||||
if (ptr)
|
||||
{
|
||||
if ( ((ptrdiff_t)ptr) & 4095 ) stop();
|
||||
if ( VirtualFree(ptr,0,MEM_RELEASE) == 0 ) stop();
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void * wmalloc(SIZE_T size)
|
||||
{
|
||||
static unsigned int pagesize=0;
|
||||
void* p;
|
||||
SIZE_T s;
|
||||
|
||||
// get the page size, if we haven't yet
|
||||
if (pagesize==0)
|
||||
{
|
||||
SYSTEM_INFO si;
|
||||
GetSystemInfo(&si);
|
||||
pagesize=si.dwPageSize;
|
||||
}
|
||||
|
||||
// we need room for the size, 8 bytes to hide the original pointer and a
|
||||
// validation dword, and enough data to completely fill one page
|
||||
s=(size+16+(pagesize-1))&~(pagesize-1);
|
||||
|
||||
// allocate the size plus a page (for the guard)
|
||||
p=VirtualAlloc(0,(SIZE_T)(s+pagesize+pagesize),MEM_RESERVE|MEM_COMMIT,PAGE_READWRITE);
|
||||
|
||||
if (p)
|
||||
{
|
||||
DWORD oldprot;
|
||||
void* orig=p;
|
||||
|
||||
// protect the first page
|
||||
VirtualProtect(((char*)p),pagesize,PAGE_NOACCESS,&oldprot);
|
||||
|
||||
// protect the final page
|
||||
VirtualProtect(((char*)p)+s+pagesize,pagesize,PAGE_NOACCESS,&oldprot);
|
||||
|
||||
// now move the returned pointer so that it bumps right up against the
|
||||
// the next (protected) page (this may result in unaligned return
|
||||
// addresses - pre-align the sizes if you always want aligned ptrs)
|
||||
//#define ERROR_ON_FRONT
|
||||
#ifdef ERROR_ON_FRONT
|
||||
p=((char*)p)+pagesize+16;
|
||||
#else
|
||||
p=((char*)p)+(s-size)+pagesize;
|
||||
#endif
|
||||
|
||||
// hide the validation value and the original pointer (which we'll
|
||||
// need used for freeing) right behind the returned pointer
|
||||
((unsigned int*)p)[-1]=0x98765432;
|
||||
((void**)p)[-2]=orig;
|
||||
++mem_count;
|
||||
//printf("aloc: %p bytes: %d\n",p,(int)size);
|
||||
return(p);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void wfree(void * ptr)
|
||||
{
|
||||
if (ptr)
|
||||
{
|
||||
int err=0;
|
||||
|
||||
// is this one of our allocations?
|
||||
if (((((unsigned int*)ptr)[-1])!=0x98765432) || ((((void**)ptr)[-2])==0))
|
||||
{
|
||||
err=1;
|
||||
}
|
||||
|
||||
if (err)
|
||||
{
|
||||
__debugbreak();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
// back up to find the original pointer
|
||||
void* p=((void**)ptr)[-2];
|
||||
|
||||
// clear the validation value and the original pointer
|
||||
((unsigned int*)ptr)[-1]=0;
|
||||
((void**)ptr)[-2]=0;
|
||||
|
||||
//printf("free: %p\n",ptr);
|
||||
|
||||
--mem_count;
|
||||
|
||||
// now free the pages
|
||||
if (p)
|
||||
VirtualFree(p,0,MEM_RELEASE);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#define STBIR_MALLOC(size,user_data) ((void)(user_data), wmalloc(size))
|
||||
#define STBIR_FREE(ptr,user_data) ((void)(user_data), wfree(ptr))
|
||||
|
||||
#endif
|
||||
|
||||
#define STBIR_PROFILE
|
||||
//#define STBIR_NO_SIMD
|
||||
//#define STBIR_AVX
|
||||
//#define STBIR_AVX2
|
||||
#define STB_IMAGE_RESIZE_IMPLEMENTATION
|
||||
#include "stb_image_resize2.h" // new one!
|
||||
|
||||
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
||||
#include "stb_image_write.h"
|
||||
|
||||
int tsizes[5] = { 1, 1, 2, 4, 2 };
|
||||
int ttypes[5] = { STBIR_TYPE_UINT8, STBIR_TYPE_UINT8_SRGB, STBIR_TYPE_UINT16, STBIR_TYPE_FLOAT, STBIR_TYPE_HALF_FLOAT };
|
||||
|
||||
int cedges[4] = { STBIR_EDGE_CLAMP, STBIR_EDGE_REFLECT, STBIR_EDGE_ZERO, STBIR_EDGE_WRAP };
|
||||
int flts[5] = { STBIR_FILTER_BOX, STBIR_FILTER_TRIANGLE, STBIR_FILTER_CUBICBSPLINE, STBIR_FILTER_CATMULLROM, STBIR_FILTER_MITCHELL };
|
||||
int buffers[20] = { STBIR_1CHANNEL, STBIR_2CHANNEL, STBIR_RGB, STBIR_4CHANNEL,
|
||||
STBIR_BGRA, STBIR_ARGB, STBIR_RA, STBIR_AR,
|
||||
STBIR_RGBA_PM, STBIR_ARGB_PM, STBIR_RA_PM, STBIR_AR_PM,
|
||||
STBIR_RGBA, STBIR_ARGB, STBIR_RA, STBIR_AR,
|
||||
STBIR_RGBA_PM, STBIR_ARGB_PM, STBIR_RA_PM, STBIR_AR_PM,
|
||||
};
|
||||
int obuffers[20] = { STBIR_1CHANNEL, STBIR_2CHANNEL, STBIR_RGB, STBIR_4CHANNEL,
|
||||
STBIR_BGRA, STBIR_ARGB, STBIR_RA, STBIR_AR,
|
||||
STBIR_RGBA_PM, STBIR_ARGB_PM, STBIR_RA_PM, STBIR_AR_PM,
|
||||
STBIR_RGBA_PM, STBIR_ARGB_PM, STBIR_RA_PM, STBIR_AR_PM,
|
||||
STBIR_RGBA, STBIR_ARGB, STBIR_RA, STBIR_AR,
|
||||
};
|
||||
|
||||
int bchannels[20] = { 1, 2, 3, 4, 4,4, 2,2, 4,4, 2,2, 4,4, 2,2, 4,4, 2,2 };
|
||||
int alphapos[20] = { -1, -1, -1, -1, 3,0, 1,0, 3,0, 1,0, 3,0, 1,0,3,0, 1,0 };
|
||||
|
||||
|
||||
char const * buffstrs[20] = { "1ch", "2ch", "3ch", "4ch", "RGBA", "ARGB", "RA", "AR", "RGBA_both_pre", "ARGB_both_pre", "RA_both_pre", "AR_both_pre", "RGBA_out_pre", "ARGB_out_pre", "RA_out_pre", "AR_out_pre", "RGBA_in_pre", "ARGB_in_pre", "RA_in_pre", "AR_in_pre" };
|
||||
char const * typestrs[5] = { "Bytes", "BytesSRGB", "Shorts", "Floats", "Half Floats"};
|
||||
char const * edgestrs[4] = { "Clamp", "Reflect", "Zero", "Wrap" };
|
||||
char const * fltstrs[5] = { "Box", "Triangle", "Cubic", "Catmullrom", "Mitchell" };
|
||||
|
||||
#ifdef STBIR_PROFILE
|
||||
static void do_acc_zones( STBIR_PROFILE_INFO * profile )
|
||||
{
|
||||
stbir_uint32 j;
|
||||
stbir_uint64 start = tmGetAccumulationStart( tm_mask ); start=start;
|
||||
|
||||
for( j = 0 ; j < profile->count ; j++ )
|
||||
{
|
||||
if ( profile->clocks[j] )
|
||||
tmEmitAccumulationZone( 0, 0, (tm_uint64*)&start, 0, profile->clocks[j], profile->descriptions[j] );
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define do_acc_zones(...)
|
||||
#endif
|
||||
|
||||
int64 vert;
|
||||
|
||||
//#define WINTHREADTEST
|
||||
#ifdef WINTHREADTEST
|
||||
|
||||
static STBIR_RESIZE * thread_resize;
|
||||
static LONG which;
|
||||
static int threads_started = 0;
|
||||
static HANDLE threads[32];
|
||||
static HANDLE starts,stops;
|
||||
|
||||
static DWORD resize_shim( LPVOID p )
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
LONG wh;
|
||||
|
||||
WaitForSingleObject( starts, INFINITE );
|
||||
|
||||
wh = InterlockedAdd( &which, 1 ) - 1;
|
||||
|
||||
ENTER( "Split %d", wh );
|
||||
stbir_resize_split( thread_resize, wh, 1 );
|
||||
#ifdef STBIR_PROFILE
|
||||
{ STBIR_PROFILE_INFO profile; stbir_resize_split_profile_info( &profile, thread_resize, wh, 1 ); do_acc_zones( &profile ); vert = profile.clocks[1]; }
|
||||
#endif
|
||||
LEAVE();
|
||||
|
||||
ReleaseSemaphore( stops, 1, 0 );
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void nresize( void * o, int ox, int oy, int op, void * i, int ix, int iy, int ip, int buf, int type, int edg, int flt )
|
||||
{
|
||||
STBIR_RESIZE resize;
|
||||
|
||||
stbir_resize_init( &resize, i, ix, iy, ip, o, ox, oy, op, buffers[buf], ttypes[type] );
|
||||
stbir_set_pixel_layouts( &resize, buffers[buf], obuffers[buf] );
|
||||
stbir_set_edgemodes( &resize, cedges[edg], cedges[edg] );
|
||||
stbir_set_filters( &resize, flts[flt], /*STBIR_FILTER_POINT_SAMPLE */ flts[flt] );
|
||||
//stbir_set_input_subrect( &resize, 0.55f,0.333f,0.75f,0.50f);
|
||||
//stbir_set_output_pixel_subrect( &resize, 00, 00, ox/2,oy/2);
|
||||
//stbir_set_pixel_subrect(&resize, 1430,1361,30,30);
|
||||
|
||||
ENTER( "Resize" );
|
||||
|
||||
#ifndef WINTHREADTEST
|
||||
|
||||
ENTER( "Filters" );
|
||||
stbir_build_samplers_with_splits( &resize, 1 );
|
||||
#ifdef STBIR_PROFILE
|
||||
{ STBIR_PROFILE_INFO profile; stbir_resize_build_profile_info( &profile, &resize ); do_acc_zones( &profile ); }
|
||||
#endif
|
||||
LEAVE();
|
||||
|
||||
ENTER( "Resize" );
|
||||
if(!stbir_resize_extended( &resize ) )
|
||||
stop();
|
||||
#ifdef STBIR_PROFILE
|
||||
{ STBIR_PROFILE_INFO profile; stbir_resize_extended_profile_info( &profile, &resize ); do_acc_zones( &profile ); vert = profile.clocks[1]; }
|
||||
#endif
|
||||
LEAVE();
|
||||
|
||||
#else
|
||||
{
|
||||
int c, cnt;
|
||||
|
||||
ENTER( "Filters" );
|
||||
cnt = stbir_build_samplers_with_splits( &resize, 4 );
|
||||
#ifdef STBIR_PROFILE
|
||||
{ STBIR_PROFILE_INFO profile; stbir_resize_build_profile_info( &profile, &resize ); do_acc_zones( &profile ); }
|
||||
#endif
|
||||
LEAVE();
|
||||
|
||||
ENTER( "Thread start" );
|
||||
if ( threads_started == 0 )
|
||||
{
|
||||
starts = CreateSemaphore( 0, 0, 32, 0 );
|
||||
stops = CreateSemaphore( 0, 0, 32, 0 );
|
||||
}
|
||||
for( c = threads_started ; c < cnt ; c++ )
|
||||
threads[ c ] = CreateThread( 0, 2048*1024, resize_shim, 0, 0, 0 );
|
||||
|
||||
threads_started = cnt;
|
||||
thread_resize = &resize;
|
||||
which = 0;
|
||||
LEAVE();
|
||||
|
||||
// starts the threads
|
||||
ReleaseSemaphore( starts, cnt, 0 );
|
||||
|
||||
ENTER( "Wait" );
|
||||
for( c = 0 ; c < cnt; c++ )
|
||||
WaitForSingleObject( stops, INFINITE );
|
||||
LEAVE();
|
||||
}
|
||||
#endif
|
||||
|
||||
ENTER( "Free" );
|
||||
stbir_free_samplers( &resize );
|
||||
LEAVE();
|
||||
LEAVE();
|
||||
}
|
||||
|
||||
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#include "stb_image.h"
|
||||
|
||||
extern void oresize( void * o, int ox, int oy, int op, void * i, int ix, int iy, int ip, int buf, int type, int edg, int flt );
|
||||
|
||||
|
||||
|
||||
#define TYPESTART 0
|
||||
#define TYPEEND 4
|
||||
|
||||
#define LAYOUTSTART 0
|
||||
#define LAYOUTEND 19
|
||||
|
||||
#define SIZEWSTART 0
|
||||
#define SIZEWEND 2
|
||||
|
||||
#define SIZEHSTART 0
|
||||
#define SIZEHEND 2
|
||||
|
||||
#define EDGESTART 0
|
||||
#define EDGEEND 3
|
||||
|
||||
#define FILTERSTART 0
|
||||
#define FILTEREND 4
|
||||
|
||||
#define HEIGHTSTART 0
|
||||
#define HEIGHTEND 2
|
||||
|
||||
#define WIDTHSTART 0
|
||||
#define WIDTHEND 2
|
||||
|
||||
|
||||
|
||||
|
||||
static void * convert8to16( unsigned char * i, int w, int h, int c )
|
||||
{
|
||||
unsigned short * ret;
|
||||
int p;
|
||||
|
||||
ret = malloc( w*h*c*sizeof(short) );
|
||||
for(p = 0 ; p < (w*h*c) ; p++ )
|
||||
{
|
||||
ret[p]=(short)((((int)i[p])<<8)+i[p]);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void * convert8tof( unsigned char * i, int w, int h, int c )
|
||||
{
|
||||
float * ret;
|
||||
int p;
|
||||
|
||||
ret = malloc( w*h*c*sizeof(float) );
|
||||
for(p = 0 ; p < (w*h*c) ; p++ )
|
||||
{
|
||||
ret[p]=((float)i[p])*(1.0f/255.0f);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void * convert8tohf( unsigned char * i, int w, int h, int c )
|
||||
{
|
||||
stbir__FP16 * ret;
|
||||
int p;
|
||||
|
||||
ret = malloc( w*h*c*sizeof(stbir__FP16) );
|
||||
for(p = 0 ; p < (w*h*c) ; p++ )
|
||||
{
|
||||
ret[p]=stbir__float_to_half(((float)i[p])*(1.0f/255.0f));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void * convert8tohff( unsigned char * i, int w, int h, int c )
|
||||
{
|
||||
float * ret;
|
||||
int p;
|
||||
|
||||
ret = malloc( w*h*c*sizeof(float) );
|
||||
for(p = 0 ; p < (w*h*c) ; p++ )
|
||||
{
|
||||
ret[p]=stbir__half_to_float(stbir__float_to_half(((float)i[p])*(1.0f/255.0f)));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int isprime( int v )
|
||||
{
|
||||
int i;
|
||||
|
||||
if ( v <= 3 )
|
||||
return ( v > 1 );
|
||||
if ( ( v & 1 ) == 0 )
|
||||
return 0;
|
||||
if ( ( v % 3 ) == 0 )
|
||||
return 0;
|
||||
i = 5;
|
||||
while ( (i*i) <= v )
|
||||
{
|
||||
if ( ( v % i ) == 0 )
|
||||
return 0;
|
||||
if ( ( v % ( i + 2 ) ) == 0 )
|
||||
return 0;
|
||||
i += 6;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int getprime( int v )
|
||||
{
|
||||
int i;
|
||||
i = 0;
|
||||
for(;;)
|
||||
{
|
||||
if ( i >= v )
|
||||
return v; // can't find any, just return orig
|
||||
if (isprime(v - i))
|
||||
return v - i;
|
||||
if (isprime(v + i))
|
||||
return v + i;
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int main( int argc, char ** argv )
|
||||
{
|
||||
int ix, iy, ic;
|
||||
unsigned char * input[6];
|
||||
char * ir1;
|
||||
char * ir2;
|
||||
int szhs[3];
|
||||
int szws[3];
|
||||
int aw, ah, ac;
|
||||
unsigned char * correctalpha;
|
||||
int layouts, types, heights, widths, edges, filters;
|
||||
|
||||
if ( argc != 2 )
|
||||
{
|
||||
printf("command: stbirtest [imagefile]\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
SetupTM( "127.0.0.1" );
|
||||
|
||||
correctalpha = stbi_load( "correctalpha.png", &aw, &ah, &ac, 0 );
|
||||
|
||||
input[0] = stbi_load( argv[1], &ix, &iy, &ic, 0 );
|
||||
input[1] = input[0];
|
||||
input[2] = convert8to16( input[0], ix, iy, ic );
|
||||
input[3] = convert8tof( input[0], ix, iy, ic );
|
||||
input[4] = convert8tohf( input[0], ix, iy, ic );
|
||||
input[5] = convert8tohff( input[0], ix, iy, ic );
|
||||
|
||||
printf("Input %dx%d (%d channels)\n",ix,iy,ic);
|
||||
|
||||
ir1 = malloc( 4 * 4 * 3000 * 3000ULL );
|
||||
ir2 = malloc( 4 * 4 * 3000 * 3000ULL );
|
||||
|
||||
szhs[0] = getprime( iy/SHRINKBYH );
|
||||
szhs[1] = iy;
|
||||
szhs[2] = getprime( iy*ZOOMBYH );
|
||||
|
||||
szws[0] = getprime( ix/SHRINKBYW );
|
||||
szws[1] = ix;
|
||||
szws[2] = getprime( ix*ZOOMBYW );
|
||||
|
||||
#if 1
|
||||
for( types = TYPESTART ; types <= TYPEEND ; types++ )
|
||||
#else
|
||||
for( types = 1 ; types <= 1 ; types++ )
|
||||
#endif
|
||||
{
|
||||
ENTER( "Test type: %s",typestrs[types]);
|
||||
#if 1
|
||||
for( layouts = LAYOUTSTART ; layouts <= LAYOUTEND ; layouts++ )
|
||||
#else
|
||||
for( layouts = 16; layouts <= 16 ; layouts++ )
|
||||
#endif
|
||||
{
|
||||
ENTER( "Test layout: %s",buffstrs[layouts]);
|
||||
|
||||
#if 0
|
||||
for( heights = HEIGHTSTART ; heights <= HEIGHTEND ; heights++ )
|
||||
{
|
||||
int w, h = szhs[heights];
|
||||
#else
|
||||
for( heights = 0 ; heights <= 11 ; heights++ )
|
||||
{
|
||||
static int szhsz[12]={32, 200, 350, 400, 450, 509, 532, 624, 700, 824, 1023, 2053 };
|
||||
int w, h = szhsz[heights];
|
||||
#endif
|
||||
|
||||
ENTER( "Test height: %d %s %d",iy,(h<iy)?"Down":((h>iy)?"Up":"Same"),h);
|
||||
|
||||
#if 0
|
||||
for( widths = WIDTHSTART ; widths <= WIDTHEND ; widths++ )
|
||||
{
|
||||
w = szws[widths];
|
||||
#else
|
||||
for( widths = 0 ; widths <= 12 ; widths++ )
|
||||
{
|
||||
static int szwsz[13]={2, 32, 200, 350, 400, 450, 509, 532, 624, 700, 824, 1023, 2053 };
|
||||
w = szwsz[widths];
|
||||
#endif
|
||||
|
||||
ENTER( "Test width: %d %s %d",ix, (w<ix)?"Down":((w>ix)?"Up":"Same"), w);
|
||||
|
||||
#if 0
|
||||
for( edges = EDGESTART ; edges <= EDGEEND ; edges++ )
|
||||
#else
|
||||
for( edges = 0 ; edges <= 0 ; edges++ )
|
||||
#endif
|
||||
{
|
||||
ENTER( "Test edge: %s",edgestrs[edges]);
|
||||
#if 0
|
||||
for( filters = FILTERSTART ; filters <= FILTEREND ; filters++ )
|
||||
#else
|
||||
for( filters = 3 ; filters <= 3 ; filters++ )
|
||||
#endif
|
||||
{
|
||||
int op, opw, np,npw, c, a;
|
||||
#ifdef COMPARE_SAME
|
||||
int oldtypes = types;
|
||||
#else
|
||||
int oldtypes = (types==4)?3:types;
|
||||
#endif
|
||||
|
||||
ENTER( "Test filter: %s",fltstrs[filters]);
|
||||
{
|
||||
c = bchannels[layouts];
|
||||
a = alphapos[layouts];
|
||||
|
||||
op = w*tsizes[oldtypes]*c + 60;
|
||||
opw = w*tsizes[oldtypes]*c;
|
||||
|
||||
np = w*tsizes[types]*c + 60;
|
||||
npw = w*tsizes[types]*c;
|
||||
|
||||
printf( "%s:layout: %s w: %d h: %d edge: %s filt: %s\n", typestrs[types],buffstrs[layouts], w, h, edgestrs[edges], fltstrs[filters] );
|
||||
|
||||
|
||||
// clear pixel area to different, right edge to zero
|
||||
#ifndef NOCLEAR
|
||||
ENTER( "Test clear padding" );
|
||||
{
|
||||
int d;
|
||||
for( d = 0 ; d < h ; d++ )
|
||||
{
|
||||
int oofs = d * op;
|
||||
int nofs = d * np;
|
||||
memset( ir1 + oofs, 192, opw );
|
||||
memset( ir1 + oofs+opw, 79, op-opw );
|
||||
memset( ir2 + nofs, 255, npw );
|
||||
memset( ir2 + nofs+npw, 79, np-npw );
|
||||
}
|
||||
}
|
||||
LEAVE();
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef COMPARE_SAME
|
||||
#define TIMINGS 1
|
||||
#else
|
||||
#define TIMINGS 1
|
||||
#endif
|
||||
ENTER( "Test both" );
|
||||
{
|
||||
#ifndef PROFILE_NEW_ONLY
|
||||
{
|
||||
int ttt, max = 0x7fffffff;
|
||||
ENTER( "Test old" );
|
||||
for( ttt = 0 ; ttt < TIMINGS ; ttt++ )
|
||||
{
|
||||
int64 m = __cycles();
|
||||
|
||||
oresize( ir1, w, h, op,
|
||||
#ifdef COMPARE_SAME
|
||||
input[types],
|
||||
#else
|
||||
input[(types==4)?5:types],
|
||||
#endif
|
||||
ix, iy, ix*ic*tsizes[oldtypes], layouts, oldtypes, edges, filters );
|
||||
|
||||
m = __cycles() - m;
|
||||
if ( ( (int)m ) < max )
|
||||
max = (int) m;
|
||||
}
|
||||
LEAVE();
|
||||
printf("old: %d\n", max );
|
||||
}
|
||||
#endif
|
||||
|
||||
{
|
||||
int ttt, max = 0x7fffffff, maxv = 0x7fffffff;
|
||||
ENTER( "Test new" );
|
||||
for( ttt = 0 ; ttt < TIMINGS ; ttt++ )
|
||||
{
|
||||
int64 m = __cycles();
|
||||
|
||||
nresize( ir2, w, h, np, input[types], ix, iy, ix*ic*tsizes[types], layouts, types, edges, filters );
|
||||
|
||||
m = __cycles() - m;
|
||||
if ( ( (int)m ) < max )
|
||||
max = (int) m;
|
||||
if ( ( (int)vert ) < maxv )
|
||||
maxv = (int) vert;
|
||||
}
|
||||
LEAVE(); // test new
|
||||
printf("new: %d (v: %d)\n", max, maxv );
|
||||
}
|
||||
}
|
||||
LEAVE(); // test both
|
||||
|
||||
if ( mem_count!= 0 )
|
||||
stop();
|
||||
|
||||
#ifndef NOCOMP
|
||||
ENTER( "Test compare" );
|
||||
{
|
||||
int x,y,ch;
|
||||
int nums = 0;
|
||||
for( y = 0 ; y < h ; y++ )
|
||||
{
|
||||
for( x = 0 ; x < w ; x++ )
|
||||
{
|
||||
switch(types)
|
||||
{
|
||||
case 0:
|
||||
case 1: //SRGB
|
||||
{
|
||||
unsigned char * p1 = (unsigned char *)&ir1[y*op+x*c];
|
||||
unsigned char * p2 = (unsigned char *)&ir2[y*np+x*c];
|
||||
for( ch = 0 ; ch < c ; ch++ )
|
||||
{
|
||||
float pp1,pp2,d;
|
||||
float av = (a==-1)?1.0f:((float)p1[a]/255.0f);
|
||||
|
||||
pp1 = p1[ch];
|
||||
pp2 = p2[ch];
|
||||
|
||||
// compare in premult space
|
||||
#ifndef COMPARE_SAME
|
||||
if ( ( ( layouts >=4 ) && ( layouts <= 7 ) ) || ( ( layouts >=16 ) && ( layouts <= 19 ) ) )
|
||||
{
|
||||
pp1 *= av;
|
||||
pp2 *= av;
|
||||
}
|
||||
#endif
|
||||
|
||||
d = pp1 - pp2;
|
||||
if ( d < 0 ) d = -d;
|
||||
|
||||
#ifdef COMPARE_SAME
|
||||
if ( d > 0 )
|
||||
#else
|
||||
if ( d > 1 )
|
||||
#endif
|
||||
{
|
||||
printf("Error at %d x %d (chan %d) (d: %g a: %g) [%d %d %d %d] [%d %d %d %d]\n",x,y,ch, d,av, p1[0],p1[1],p1[2],p1[3], p2[0],p2[1],p2[2],p2[3]);
|
||||
++nums;
|
||||
if ( nums > 16 ) goto ex;
|
||||
//if (d) exit(1);
|
||||
//goto ex;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
{
|
||||
unsigned short * p1 = (unsigned short *)&ir1[y*op+x*c*sizeof(short)];
|
||||
unsigned short * p2 = (unsigned short *)&ir2[y*np+x*c*sizeof(short)];
|
||||
for( ch = 0 ; ch < c ; ch++ )
|
||||
{
|
||||
float thres,pp1,pp2,d;
|
||||
float av = (a==-1)?1.0f:((float)p1[a]/65535.0f);
|
||||
|
||||
pp1 = p1[ch];
|
||||
pp2 = p2[ch];
|
||||
|
||||
// compare in premult space
|
||||
#ifndef COMPARE_SAME
|
||||
if ( ( ( layouts >=4 ) && ( layouts <= 7 ) ) || ( ( layouts >= 16 ) && ( layouts <= 19 ) ) )
|
||||
{
|
||||
pp1 *= av;
|
||||
pp2 *= av;
|
||||
}
|
||||
#endif
|
||||
|
||||
d = pp1 - pp2;
|
||||
if ( d < 0 ) d = -d;
|
||||
|
||||
thres=((float)p1[ch]*0.007f)+2.0f;
|
||||
if (thres<4) thres = 4;
|
||||
|
||||
#ifdef COMPARE_SAME
|
||||
if ( d > 0 )
|
||||
#else
|
||||
if ( d > thres)
|
||||
#endif
|
||||
{
|
||||
printf("Error at %d x %d (chan %d) %d %d [df: %g th: %g al: %g] (%d %d %d %d) (%d %d %d %d)\n",x,y,ch, p1[ch],p2[ch],d,thres,av,p1[0],p1[1],p1[2],p1[3],p2[0],p2[1],p2[2],p2[3]);
|
||||
++nums;
|
||||
if ( nums > 16 ) goto ex;
|
||||
//if (d) exit(1);
|
||||
//goto ex;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 3:
|
||||
{
|
||||
float * p1 = (float *)&ir1[y*op+x*c*sizeof(float)];
|
||||
float * p2 = (float *)&ir2[y*np+x*c*sizeof(float)];
|
||||
for( ch = 0 ; ch < c ; ch++ )
|
||||
{
|
||||
float pp1 = p1[ch], pp2 = p2[ch];
|
||||
float av = (a==-1)?1.0f:p1[a];
|
||||
float thres, d;
|
||||
|
||||
// clamp
|
||||
if (pp1<=0.0f) pp1 = 0;
|
||||
if (pp2<=0.0f) pp2 = 0;
|
||||
if (av<=0.0f) av = 0;
|
||||
if (pp1>1.0f) pp1 = 1.0f;
|
||||
if (pp2>1.0f) pp2 = 1.0f;
|
||||
if (av>1.0f) av = 1.0f;
|
||||
|
||||
// compare in premult space
|
||||
#ifndef COMPARE_SAME
|
||||
if ( ( ( layouts >=4 ) && ( layouts <= 7 ) ) || ( ( layouts >= 16 ) && ( layouts <= 19 ) ) )
|
||||
{
|
||||
pp1 *= av;
|
||||
pp2 *= av;
|
||||
}
|
||||
#endif
|
||||
|
||||
d = pp1 - pp2;
|
||||
if ( d < 0 ) d = -d;
|
||||
|
||||
thres=(p1[ch]*0.002f)+0.0002f;
|
||||
if ( thres < 0 ) thres = -thres;
|
||||
|
||||
#ifdef COMPARE_SAME
|
||||
if ( d != 0.0f )
|
||||
#else
|
||||
if ( d > thres )
|
||||
#endif
|
||||
{
|
||||
printf("Error at %d x %d (chan %d) %g %g [df: %g th: %g al: %g] (%g %g %g %g) (%g %g %g %g)\n",x,y,ch, p1[ch],p2[ch],d,thres,av,p1[0],p1[1],p1[2],p1[3],p2[0],p2[1],p2[2],p2[3]);
|
||||
++nums;
|
||||
if ( nums > 16 ) goto ex;
|
||||
//if (d) exit(1);
|
||||
//goto ex;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 4:
|
||||
{
|
||||
#ifdef COMPARE_SAME
|
||||
stbir__FP16 * p1 = (stbir__FP16 *)&ir1[y*op+x*c*sizeof(stbir__FP16)];
|
||||
#else
|
||||
float * p1 = (float *)&ir1[y*op+x*c*sizeof(float)];
|
||||
#endif
|
||||
stbir__FP16 * p2 = (stbir__FP16 *)&ir2[y*np+x*c*sizeof(stbir__FP16)];
|
||||
for( ch = 0 ; ch < c ; ch++ )
|
||||
{
|
||||
#ifdef COMPARE_SAME
|
||||
float pp1 = stbir__half_to_float(p1[ch]);
|
||||
float av = (a==-1)?1.0f:stbir__half_to_float(p1[a]);
|
||||
#else
|
||||
float pp1 = stbir__half_to_float(stbir__float_to_half(p1[ch]));
|
||||
float av = (a==-1)?1.0f:stbir__half_to_float(stbir__float_to_half(p1[a]));
|
||||
#endif
|
||||
float pp2 = stbir__half_to_float(p2[ch]);
|
||||
float d, thres;
|
||||
|
||||
// clamp
|
||||
if (pp1<=0.0f) pp1 = 0;
|
||||
if (pp2<=0.0f) pp2 = 0;
|
||||
if (av<=0.0f) av = 0;
|
||||
if (pp1>1.0f) pp1 = 1.0f;
|
||||
if (pp2>1.0f) pp2 = 1.0f;
|
||||
if (av>1.0f) av = 1.0f;
|
||||
|
||||
thres=(pp1*0.002f)+0.0002f;
|
||||
|
||||
// compare in premult space
|
||||
#ifndef COMPARE_SAME
|
||||
if ( ( ( layouts >=4 ) && ( layouts <= 7 ) ) || ( ( layouts >= 16 ) && ( layouts <= 19 ) ) )
|
||||
{
|
||||
pp1 *= av;
|
||||
pp2 *= av;
|
||||
}
|
||||
#endif
|
||||
|
||||
d = pp1 - pp2;
|
||||
if ( d < 0 ) d = -d;
|
||||
|
||||
|
||||
#ifdef COMPARE_SAME
|
||||
if ( d != 0.0f )
|
||||
#else
|
||||
if ( d > thres )
|
||||
#endif
|
||||
{
|
||||
printf("Error at %d x %d (chan %d) %g %g [df: %g th: %g al: %g] (%g %g %g %g) (%g %g %g %g)\n",x,y,ch,
|
||||
#ifdef COMPARE_SAME
|
||||
stbir__half_to_float(p1[ch]),
|
||||
#else
|
||||
p1[ch],
|
||||
#endif
|
||||
stbir__half_to_float(p2[ch]),
|
||||
d,thres,av,
|
||||
#ifdef COMPARE_SAME
|
||||
stbir__half_to_float(p1[0]),stbir__half_to_float(p1[1]),stbir__half_to_float(p1[2]),stbir__half_to_float(p1[3]),
|
||||
#else
|
||||
p1[0],p1[1],p1[2],p1[3],
|
||||
#endif
|
||||
stbir__half_to_float(p2[0]),stbir__half_to_float(p2[1]),stbir__half_to_float(p2[2]),stbir__half_to_float(p2[3]) );
|
||||
++nums;
|
||||
if ( nums > 16 ) goto ex;
|
||||
//if (d) exit(1);
|
||||
//goto ex;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for( x = (w*c)*tsizes[oldtypes]; x < op; x++ )
|
||||
{
|
||||
if ( ir1[y*op+x] != 79 )
|
||||
{
|
||||
printf("Margin error at %d x %d %d (should be 79) OLD!\n",x,y,(unsigned char)ir1[y*op+x]);
|
||||
goto ex;
|
||||
}
|
||||
}
|
||||
|
||||
for( x = (w*c)*tsizes[types]; x < np; x++ )
|
||||
{
|
||||
if ( ir2[y*np+x] != 79 )
|
||||
{
|
||||
printf("Margin error at %d x %d %d (should be 79) NEW\n",x,y,(unsigned char)ir2[y*np+x]);
|
||||
goto ex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ex:
|
||||
ENTER( "OUTPUT IMAGES" );
|
||||
printf(" tot pix: %d, errs: %d\n", w*h*c,nums );
|
||||
|
||||
if (nums)
|
||||
{
|
||||
stbi_write_png("old.png", w, h, c, ir1, op);
|
||||
stbi_write_png("new.png", w, h, c, ir2, np);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
LEAVE(); // output images
|
||||
}
|
||||
LEAVE(); //test compare
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
}
|
||||
LEAVE(); // test filter
|
||||
}
|
||||
LEAVE(); // test edge
|
||||
}
|
||||
LEAVE(); // test width
|
||||
}
|
||||
LEAVE(); // test height
|
||||
}
|
||||
LEAVE(); // test type
|
||||
}
|
||||
LEAVE(); // test layout
|
||||
}
|
||||
|
||||
CloseTM();
|
||||
return 0;
|
||||
}
|
999
external/stb/stb/stb_image_resize_test/vf_train.c
vendored
Normal file
999
external/stb/stb/stb_image_resize_test/vf_train.c
vendored
Normal file
@ -0,0 +1,999 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define stop() __debugbreak()
|
||||
#include <windows.h>
|
||||
#define int64 __int64
|
||||
|
||||
#pragma warning(disable:4127)
|
||||
|
||||
#define STBIR__WEIGHT_TABLES
|
||||
#define STBIR_PROFILE
|
||||
#define STB_IMAGE_RESIZE_IMPLEMENTATION
|
||||
#include "stb_image_resize2.h"
|
||||
|
||||
static int * file_read( char const * filename )
|
||||
{
|
||||
size_t s;
|
||||
int * m;
|
||||
FILE * f = fopen( filename, "rb" );
|
||||
if ( f == 0 ) return 0;
|
||||
|
||||
fseek( f, 0, SEEK_END);
|
||||
s = ftell( f );
|
||||
fseek( f, 0, SEEK_SET);
|
||||
m = malloc( s + 4 );
|
||||
m[0] = (int)s;
|
||||
fread( m+1, 1, s, f);
|
||||
fclose(f);
|
||||
|
||||
return( m );
|
||||
}
|
||||
|
||||
typedef struct fileinfo
|
||||
{
|
||||
int * timings;
|
||||
int timing_count;
|
||||
int dimensionx, dimensiony;
|
||||
int numtypes;
|
||||
int * types;
|
||||
int * effective;
|
||||
int cpu;
|
||||
int simd;
|
||||
int numinputrects;
|
||||
int * inputrects;
|
||||
int outputscalex, outputscaley;
|
||||
int milliseconds;
|
||||
int64 cycles;
|
||||
double scale_time;
|
||||
int bitmapx, bitmapy;
|
||||
char const * filename;
|
||||
} fileinfo;
|
||||
|
||||
int numfileinfo;
|
||||
fileinfo fi[256];
|
||||
unsigned char * bitmap;
|
||||
int bitmapw, bitmaph, bitmapp;
|
||||
|
||||
static int use_timing_file( char const * filename, int index )
|
||||
{
|
||||
int * base = file_read( filename );
|
||||
int * file = base;
|
||||
|
||||
if ( base == 0 ) return 0;
|
||||
|
||||
++file; // skip file image size;
|
||||
if ( *file++ != 'VFT1' ) return 0;
|
||||
fi[index].cpu = *file++;
|
||||
fi[index].simd = *file++;
|
||||
fi[index].dimensionx = *file++;
|
||||
fi[index].dimensiony = *file++;
|
||||
fi[index].numtypes = *file++;
|
||||
fi[index].types = file; file += fi[index].numtypes;
|
||||
fi[index].effective = file; file += fi[index].numtypes;
|
||||
fi[index].numinputrects = *file++;
|
||||
fi[index].inputrects = file; file += fi[index].numinputrects * 2;
|
||||
fi[index].outputscalex = *file++;
|
||||
fi[index].outputscaley = *file++;
|
||||
fi[index].milliseconds = *file++;
|
||||
fi[index].cycles = ((int64*)file)[0]; file += 2;
|
||||
fi[index].filename = filename;
|
||||
|
||||
fi[index].timings = file;
|
||||
fi[index].timing_count = (int) ( ( base[0] - ( ((char*)file - (char*)base - sizeof(int) ) ) ) / (sizeof(int)*2) );
|
||||
|
||||
fi[index].scale_time = (double)fi[index].milliseconds / (double)fi[index].cycles;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int vert_first( float weights_table[STBIR_RESIZE_CLASSIFICATIONS][4], int ox, int oy, int ix, int iy, int filter, STBIR__V_FIRST_INFO * v_info )
|
||||
{
|
||||
float h_scale=(float)ox/(float)(ix);
|
||||
float v_scale=(float)oy/(float)(iy);
|
||||
stbir__support_callback * support = stbir__builtin_supports[filter];
|
||||
int vertical_filter_width = stbir__get_filter_pixel_width(support,v_scale,0);
|
||||
int vertical_gather = ( v_scale >= ( 1.0f - stbir__small_float ) ) || ( vertical_filter_width <= STBIR_FORCE_GATHER_FILTER_SCANLINES_AMOUNT );
|
||||
|
||||
return stbir__should_do_vertical_first( weights_table, stbir__get_filter_pixel_width(support,h_scale,0), h_scale, ox, vertical_filter_width, v_scale, oy, vertical_gather, v_info );
|
||||
}
|
||||
|
||||
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
||||
#include "stb_image_write.h"
|
||||
|
||||
static void alloc_bitmap()
|
||||
{
|
||||
int findex;
|
||||
int x = 0, y = 0;
|
||||
int w = 0, h = 0;
|
||||
|
||||
for( findex = 0 ; findex < numfileinfo ; findex++ )
|
||||
{
|
||||
int nx, ny;
|
||||
int thisw, thish;
|
||||
|
||||
thisw = ( fi[findex].dimensionx * fi[findex].numtypes ) + ( fi[findex].numtypes - 1 );
|
||||
thish = ( fi[findex].dimensiony * fi[findex].numinputrects ) + ( fi[findex].numinputrects - 1 );
|
||||
|
||||
for(;;)
|
||||
{
|
||||
nx = x + ((x)?4:0) + thisw;
|
||||
ny = y + ((y)?4:0) + thish;
|
||||
if ( ( nx <= 3600 ) || ( x == 0 ) )
|
||||
{
|
||||
fi[findex].bitmapx = x + ((x)?4:0);
|
||||
fi[findex].bitmapy = y + ((y)?4:0);
|
||||
x = nx;
|
||||
if ( x > w ) w = x;
|
||||
if ( ny > h ) h = ny;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
x = 0;
|
||||
y = h;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
w = (w+3) & ~3;
|
||||
bitmapw = w;
|
||||
bitmaph = h;
|
||||
bitmapp = w * 3; // RGB
|
||||
bitmap = malloc( bitmapp * bitmaph );
|
||||
|
||||
memset( bitmap, 0, bitmapp * bitmaph );
|
||||
}
|
||||
|
||||
static void build_bitmap( float weights[STBIR_RESIZE_CLASSIFICATIONS][4], int do_channel_count_index, int findex )
|
||||
{
|
||||
static int colors[STBIR_RESIZE_CLASSIFICATIONS];
|
||||
STBIR__V_FIRST_INFO v_info = {0};
|
||||
|
||||
int * ts;
|
||||
int ir;
|
||||
unsigned char * bitm = bitmap + ( fi[findex].bitmapx*3 ) + ( fi[findex].bitmapy*bitmapp) ;
|
||||
|
||||
for( ir = 0; ir < STBIR_RESIZE_CLASSIFICATIONS ; ir++ ) colors[ ir ] = 127*ir/STBIR_RESIZE_CLASSIFICATIONS+128;
|
||||
|
||||
ts = fi[findex].timings;
|
||||
|
||||
for( ir = 0 ; ir < fi[findex].numinputrects ; ir++ )
|
||||
{
|
||||
int ix, iy, chanind;
|
||||
ix = fi[findex].inputrects[ir*2];
|
||||
iy = fi[findex].inputrects[ir*2+1];
|
||||
|
||||
for( chanind = 0 ; chanind < fi[findex].numtypes ; chanind++ )
|
||||
{
|
||||
int ofs, h, hh;
|
||||
|
||||
// just do the type that we're on
|
||||
if ( chanind != do_channel_count_index )
|
||||
{
|
||||
ts += 2 * fi[findex].dimensionx * fi[findex].dimensiony;
|
||||
continue;
|
||||
}
|
||||
|
||||
// bitmap offset
|
||||
ofs=chanind*(fi[findex].dimensionx+1)*3+ir*(fi[findex].dimensiony+1)*bitmapp;
|
||||
|
||||
h = 1;
|
||||
for( hh = 0 ; hh < fi[findex].dimensiony; hh++ )
|
||||
{
|
||||
int ww, w = 1;
|
||||
for( ww = 0 ; ww < fi[findex].dimensionx; ww++ )
|
||||
{
|
||||
int good, v_first, VF, HF;
|
||||
|
||||
VF = ts[0];
|
||||
HF = ts[1];
|
||||
|
||||
v_first = vert_first( weights, w, h, ix, iy, STBIR_FILTER_MITCHELL, &v_info );
|
||||
|
||||
good = ( ((HF<=VF) && (!v_first)) || ((VF<=HF) && (v_first)));
|
||||
|
||||
if ( good )
|
||||
{
|
||||
bitm[ofs+2] = 0;
|
||||
bitm[ofs+1] = (unsigned char)colors[v_info.v_resize_classification];
|
||||
}
|
||||
else
|
||||
{
|
||||
double r;
|
||||
|
||||
if ( HF < VF )
|
||||
r = (double)(VF-HF)/(double)HF;
|
||||
else
|
||||
r = (double)(HF-VF)/(double)VF;
|
||||
|
||||
if ( r > 0.4f) r = 0.4;
|
||||
r *= 1.0f/0.4f;
|
||||
|
||||
bitm[ofs+2] = (char)(255.0f*r);
|
||||
bitm[ofs+1] = (char)(((float)colors[v_info.v_resize_classification])*(1.0f-r));
|
||||
}
|
||||
bitm[ofs] = 0;
|
||||
|
||||
ofs += 3;
|
||||
ts += 2;
|
||||
w += fi[findex].outputscalex;
|
||||
}
|
||||
ofs += bitmapp - fi[findex].dimensionx*3;
|
||||
h += fi[findex].outputscaley;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void build_comp_bitmap( float weights[STBIR_RESIZE_CLASSIFICATIONS][4], int do_channel_count_index )
|
||||
{
|
||||
int * ts0;
|
||||
int * ts1;
|
||||
int ir;
|
||||
unsigned char * bitm = bitmap + ( fi[0].bitmapx*3 ) + ( fi[0].bitmapy*bitmapp) ;
|
||||
|
||||
ts0 = fi[0].timings;
|
||||
ts1 = fi[1].timings;
|
||||
|
||||
for( ir = 0 ; ir < fi[0].numinputrects ; ir++ )
|
||||
{
|
||||
int ix, iy, chanind;
|
||||
ix = fi[0].inputrects[ir*2];
|
||||
iy = fi[0].inputrects[ir*2+1];
|
||||
|
||||
for( chanind = 0 ; chanind < fi[0].numtypes ; chanind++ )
|
||||
{
|
||||
int ofs, h, hh;
|
||||
|
||||
// just do the type that we're on
|
||||
if ( chanind != do_channel_count_index )
|
||||
{
|
||||
ts0 += 2 * fi[0].dimensionx * fi[0].dimensiony;
|
||||
ts1 += 2 * fi[0].dimensionx * fi[0].dimensiony;
|
||||
continue;
|
||||
}
|
||||
|
||||
// bitmap offset
|
||||
ofs=chanind*(fi[0].dimensionx+1)*3+ir*(fi[0].dimensiony+1)*bitmapp;
|
||||
|
||||
h = 1;
|
||||
for( hh = 0 ; hh < fi[0].dimensiony; hh++ )
|
||||
{
|
||||
int ww, w = 1;
|
||||
for( ww = 0 ; ww < fi[0].dimensionx; ww++ )
|
||||
{
|
||||
int v_first, time0, time1;
|
||||
|
||||
v_first = vert_first( weights, w, h, ix, iy, STBIR_FILTER_MITCHELL, 0 );
|
||||
|
||||
time0 = ( v_first ) ? ts0[0] : ts0[1];
|
||||
time1 = ( v_first ) ? ts1[0] : ts1[1];
|
||||
|
||||
if ( time0 < time1 )
|
||||
{
|
||||
double r = (double)(time1-time0)/(double)time0;
|
||||
if ( r > 0.4f) r = 0.4;
|
||||
r *= 1.0f/0.4f;
|
||||
bitm[ofs+2] = 0;
|
||||
bitm[ofs+1] = (char)(255.0f*r);
|
||||
bitm[ofs] = (char)(64.0f*(1.0f-r));
|
||||
}
|
||||
else
|
||||
{
|
||||
double r = (double)(time0-time1)/(double)time1;
|
||||
if ( r > 0.4f) r = 0.4;
|
||||
r *= 1.0f/0.4f;
|
||||
bitm[ofs+2] = (char)(255.0f*r);
|
||||
bitm[ofs+1] = 0;
|
||||
bitm[ofs] = (char)(64.0f*(1.0f-r));
|
||||
}
|
||||
ofs += 3;
|
||||
ts0 += 2;
|
||||
ts1 += 2;
|
||||
w += fi[0].outputscalex;
|
||||
}
|
||||
ofs += bitmapp - fi[0].dimensionx*3;
|
||||
h += fi[0].outputscaley;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void write_bitmap()
|
||||
{
|
||||
stbi_write_png( "results.png", bitmapp / 3, bitmaph, 3|STB_IMAGE_BGR, bitmap, bitmapp );
|
||||
}
|
||||
|
||||
|
||||
static void calc_errors( float weights_table[STBIR_RESIZE_CLASSIFICATIONS][4], int * curtot, double * curerr, int do_channel_count_index )
|
||||
{
|
||||
int th, findex;
|
||||
STBIR__V_FIRST_INFO v_info = {0};
|
||||
|
||||
for(th=0;th<STBIR_RESIZE_CLASSIFICATIONS;th++)
|
||||
{
|
||||
curerr[th]=0;
|
||||
curtot[th]=0;
|
||||
}
|
||||
|
||||
for( findex = 0 ; findex < numfileinfo ; findex++ )
|
||||
{
|
||||
int * ts;
|
||||
int ir;
|
||||
ts = fi[findex].timings;
|
||||
|
||||
for( ir = 0 ; ir < fi[findex].numinputrects ; ir++ )
|
||||
{
|
||||
int ix, iy, chanind;
|
||||
ix = fi[findex].inputrects[ir*2];
|
||||
iy = fi[findex].inputrects[ir*2+1];
|
||||
|
||||
for( chanind = 0 ; chanind < fi[findex].numtypes ; chanind++ )
|
||||
{
|
||||
int h, hh;
|
||||
|
||||
// just do the type that we're on
|
||||
if ( chanind != do_channel_count_index )
|
||||
{
|
||||
ts += 2 * fi[findex].dimensionx * fi[findex].dimensiony;
|
||||
continue;
|
||||
}
|
||||
|
||||
h = 1;
|
||||
for( hh = 0 ; hh < fi[findex].dimensiony; hh++ )
|
||||
{
|
||||
int ww, w = 1;
|
||||
for( ww = 0 ; ww < fi[findex].dimensionx; ww++ )
|
||||
{
|
||||
int good, v_first, VF, HF;
|
||||
|
||||
VF = ts[0];
|
||||
HF = ts[1];
|
||||
|
||||
v_first = vert_first( weights_table, w, h, ix, iy, STBIR_FILTER_MITCHELL, &v_info );
|
||||
|
||||
good = ( ((HF<=VF) && (!v_first)) || ((VF<=HF) && (v_first)));
|
||||
|
||||
if ( !good )
|
||||
{
|
||||
double diff;
|
||||
if ( VF < HF )
|
||||
diff = ((double)HF-(double)VF) * fi[findex].scale_time;
|
||||
else
|
||||
diff = ((double)VF-(double)HF) * fi[findex].scale_time;
|
||||
|
||||
curtot[v_info.v_resize_classification] += 1;
|
||||
curerr[v_info.v_resize_classification] += diff;
|
||||
}
|
||||
|
||||
ts += 2;
|
||||
w += fi[findex].outputscalex;
|
||||
}
|
||||
h += fi[findex].outputscaley;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define TRIESPERWEIGHT 32
|
||||
#define MAXRANGE ((TRIESPERWEIGHT+1) * (TRIESPERWEIGHT+1) * (TRIESPERWEIGHT+1) * (TRIESPERWEIGHT+1) - 1)
|
||||
|
||||
static void expand_to_floats( float * weights, int range )
|
||||
{
|
||||
weights[0] = (float)( range % (TRIESPERWEIGHT+1) ) / (float)TRIESPERWEIGHT;
|
||||
weights[1] = (float)( range/(TRIESPERWEIGHT+1) % (TRIESPERWEIGHT+1) ) / (float)TRIESPERWEIGHT;
|
||||
weights[2] = (float)( range/(TRIESPERWEIGHT+1)/(TRIESPERWEIGHT+1) % (TRIESPERWEIGHT+1) ) / (float)TRIESPERWEIGHT;
|
||||
weights[3] = (float)( range/(TRIESPERWEIGHT+1)/(TRIESPERWEIGHT+1)/(TRIESPERWEIGHT+1) % (TRIESPERWEIGHT+1) ) / (float)TRIESPERWEIGHT;
|
||||
}
|
||||
|
||||
static char const * expand_to_string( int range )
|
||||
{
|
||||
static char str[128];
|
||||
int w0,w1,w2,w3;
|
||||
w0 = range % (TRIESPERWEIGHT+1);
|
||||
w1 = range/(TRIESPERWEIGHT+1) % (TRIESPERWEIGHT+1);
|
||||
w2 = range/(TRIESPERWEIGHT+1)/(TRIESPERWEIGHT+1) % (TRIESPERWEIGHT+1);
|
||||
w3 = range/(TRIESPERWEIGHT+1)/(TRIESPERWEIGHT+1)/(TRIESPERWEIGHT+1) % (TRIESPERWEIGHT+1);
|
||||
sprintf( str, "[ %2d/%d %2d/%d %2d/%d %2d/%d ]",w0,TRIESPERWEIGHT,w1,TRIESPERWEIGHT,w2,TRIESPERWEIGHT,w3,TRIESPERWEIGHT );
|
||||
return str;
|
||||
}
|
||||
|
||||
static void print_weights( float weights[STBIR_RESIZE_CLASSIFICATIONS][4], int channel_count_index, int * tots, double * errs )
|
||||
{
|
||||
int th;
|
||||
printf("ChInd: %d Weights:\n",channel_count_index);
|
||||
for(th=0;th<STBIR_RESIZE_CLASSIFICATIONS;th++)
|
||||
{
|
||||
float * w = weights[th];
|
||||
printf(" %d: [%1.5f %1.5f %1.5f %1.5f] (%d %.4f)\n",th, w[0], w[1], w[2], w[3], tots[th], errs[th] );
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static int windowranges[ 16 ];
|
||||
static int windowstatus = 0;
|
||||
static DWORD trainstart = 0;
|
||||
|
||||
static void opt_channel( float best_output_weights[STBIR_RESIZE_CLASSIFICATIONS][4], int channel_count_index )
|
||||
{
|
||||
int newbest = 0;
|
||||
float weights[STBIR_RESIZE_CLASSIFICATIONS][4] = {0};
|
||||
double besterr[STBIR_RESIZE_CLASSIFICATIONS];
|
||||
int besttot[STBIR_RESIZE_CLASSIFICATIONS];
|
||||
int best[STBIR_RESIZE_CLASSIFICATIONS]={0};
|
||||
|
||||
double curerr[STBIR_RESIZE_CLASSIFICATIONS];
|
||||
int curtot[STBIR_RESIZE_CLASSIFICATIONS];
|
||||
int th, range;
|
||||
DWORD lasttick = 0;
|
||||
|
||||
for(th=0;th<STBIR_RESIZE_CLASSIFICATIONS;th++)
|
||||
{
|
||||
besterr[th]=1000000000000.0;
|
||||
besttot[th]=0x7fffffff;
|
||||
}
|
||||
|
||||
newbest = 0;
|
||||
|
||||
// try the whole range
|
||||
range = MAXRANGE;
|
||||
do
|
||||
{
|
||||
for(th=0;th<STBIR_RESIZE_CLASSIFICATIONS;th++)
|
||||
expand_to_floats( weights[th], range );
|
||||
|
||||
calc_errors( weights, curtot, curerr, channel_count_index );
|
||||
|
||||
for(th=0;th<STBIR_RESIZE_CLASSIFICATIONS;th++)
|
||||
{
|
||||
if ( curerr[th] < besterr[th] )
|
||||
{
|
||||
besterr[th] = curerr[th];
|
||||
besttot[th] = curtot[th];
|
||||
best[th] = range;
|
||||
expand_to_floats( best_output_weights[th], best[th] );
|
||||
newbest = 1;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
DWORD t = GetTickCount();
|
||||
if ( range == 0 )
|
||||
goto do_bitmap;
|
||||
|
||||
if ( newbest )
|
||||
{
|
||||
if ( ( GetTickCount() - lasttick ) > 200 )
|
||||
{
|
||||
int findex;
|
||||
|
||||
do_bitmap:
|
||||
lasttick = t;
|
||||
newbest = 0;
|
||||
|
||||
for( findex = 0 ; findex < numfileinfo ; findex++ )
|
||||
build_bitmap( best_output_weights, channel_count_index, findex );
|
||||
|
||||
lasttick = GetTickCount();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
windowranges[ channel_count_index ] = range;
|
||||
|
||||
// advance all the weights and loop
|
||||
--range;
|
||||
} while( ( range >= 0 ) && ( !windowstatus ) );
|
||||
|
||||
// if we hit here, then we tried all weights for this opt, so save them
|
||||
}
|
||||
|
||||
static void print_struct( float weight[5][STBIR_RESIZE_CLASSIFICATIONS][4], char const * name )
|
||||
{
|
||||
printf("\n\nstatic float %s[5][STBIR_RESIZE_CLASSIFICATIONS][4]=\n{", name );
|
||||
{
|
||||
int i;
|
||||
for(i=0;i<5;i++)
|
||||
{
|
||||
int th;
|
||||
for(th=0;th<STBIR_RESIZE_CLASSIFICATIONS;th++)
|
||||
{
|
||||
int j;
|
||||
printf("\n ");
|
||||
for(j=0;j<4;j++)
|
||||
printf("%1.5ff, ", weight[i][th][j] );
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
printf("\n};\n");
|
||||
}
|
||||
}
|
||||
|
||||
static float retrain_weights[5][STBIR_RESIZE_CLASSIFICATIONS][4];
|
||||
|
||||
static DWORD __stdcall retrain_shim( LPVOID p )
|
||||
{
|
||||
int chanind = (int) (size_t)p;
|
||||
opt_channel( retrain_weights[chanind], chanind );
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char const * gettime( int ms )
|
||||
{
|
||||
static char time[32];
|
||||
if (ms > 60000)
|
||||
sprintf( time, "%dm %ds",ms/60000, (ms/1000)%60 );
|
||||
else
|
||||
sprintf( time, "%ds",ms/1000 );
|
||||
return time;
|
||||
}
|
||||
|
||||
static BITMAPINFOHEADER bmiHeader;
|
||||
static DWORD extrawindoww, extrawindowh;
|
||||
static HINSTANCE instance;
|
||||
static int curzoom = 1;
|
||||
|
||||
static LRESULT WINAPI WindowProc( HWND window,
|
||||
UINT message,
|
||||
WPARAM wparam,
|
||||
LPARAM lparam )
|
||||
{
|
||||
switch( message )
|
||||
{
|
||||
case WM_CHAR:
|
||||
if ( wparam != 27 )
|
||||
break;
|
||||
// falls through
|
||||
|
||||
case WM_CLOSE:
|
||||
{
|
||||
int i;
|
||||
int max = 0;
|
||||
|
||||
for( i = 0 ; i < fi[0].numtypes ; i++ )
|
||||
if( windowranges[i] > max ) max = windowranges[i];
|
||||
|
||||
if ( ( max == 0 ) || ( MessageBox( window, "Cancel before training is finished?", "Vertical First Training", MB_OKCANCEL|MB_ICONSTOP ) == IDOK ) )
|
||||
{
|
||||
for( i = 0 ; i < fi[0].numtypes ; i++ )
|
||||
if( windowranges[i] > max ) max = windowranges[i];
|
||||
if ( max )
|
||||
windowstatus = 1;
|
||||
DestroyWindow( window );
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
case WM_PAINT:
|
||||
{
|
||||
PAINTSTRUCT ps;
|
||||
HDC dc;
|
||||
|
||||
dc = BeginPaint( window, &ps );
|
||||
StretchDIBits( dc,
|
||||
0, 0, bitmapw*curzoom, bitmaph*curzoom,
|
||||
0, 0, bitmapw, bitmaph,
|
||||
bitmap, (BITMAPINFO*)&bmiHeader, DIB_RGB_COLORS, SRCCOPY );
|
||||
|
||||
PatBlt( dc, bitmapw*curzoom, 0, 4096, 4096, WHITENESS );
|
||||
PatBlt( dc, 0, bitmaph*curzoom, 4096, 4096, WHITENESS );
|
||||
|
||||
SetTextColor( dc, RGB(0,0,0) );
|
||||
SetBkColor( dc, RGB(255,255,255) );
|
||||
SetBkMode( dc, OPAQUE );
|
||||
|
||||
{
|
||||
int i, l = 0, max = 0;
|
||||
char buf[1024];
|
||||
RECT rc;
|
||||
POINT p;
|
||||
|
||||
for( i = 0 ; i < fi[0].numtypes ; i++ )
|
||||
{
|
||||
l += sprintf( buf + l, "channels: %d %s\n", fi[0].effective[i], windowranges[i] ? expand_to_string( windowranges[i] ) : "Done." );
|
||||
if ( windowranges[i] > max ) max = windowranges[i];
|
||||
}
|
||||
|
||||
rc.left = 32; rc.top = bitmaph*curzoom+10;
|
||||
rc.right = 512; rc.bottom = rc.top + 512;
|
||||
DrawText( dc, buf, -1, &rc, DT_TOP );
|
||||
|
||||
l = 0;
|
||||
if ( max == 0 )
|
||||
{
|
||||
static DWORD traindone = 0;
|
||||
if ( traindone == 0 ) traindone = GetTickCount();
|
||||
l = sprintf( buf, "Finished in %s.", gettime( traindone - trainstart ) );
|
||||
}
|
||||
else if ( max != MAXRANGE )
|
||||
l = sprintf( buf, "Done in %s...", gettime( (int) ( ( ( (int64)max * ( (int64)GetTickCount() - (int64)trainstart ) ) ) / (int64) ( MAXRANGE - max ) ) ) );
|
||||
|
||||
GetCursorPos( &p );
|
||||
ScreenToClient( window, &p );
|
||||
|
||||
if ( ( p.x >= 0 ) && ( p.y >= 0 ) && ( p.x < (bitmapw*curzoom) ) && ( p.y < (bitmaph*curzoom) ) )
|
||||
{
|
||||
int findex;
|
||||
int x, y, w, h, sx, sy, ix, iy, ox, oy;
|
||||
int ir, chanind;
|
||||
int * ts;
|
||||
char badstr[64];
|
||||
STBIR__V_FIRST_INFO v_info={0};
|
||||
|
||||
p.x /= curzoom;
|
||||
p.y /= curzoom;
|
||||
|
||||
for( findex = 0 ; findex < numfileinfo ; findex++ )
|
||||
{
|
||||
x = fi[findex].bitmapx;
|
||||
y = fi[findex].bitmapy;
|
||||
w = x + ( fi[findex].dimensionx + 1 ) * fi[findex].numtypes;
|
||||
h = y + ( fi[findex].dimensiony + 1 ) * fi[findex].numinputrects;
|
||||
|
||||
if ( ( p.x >= x ) && ( p.y >= y ) && ( p.x < w ) && ( p.y < h ) )
|
||||
goto found;
|
||||
}
|
||||
goto nope;
|
||||
|
||||
found:
|
||||
|
||||
ir = ( p.y - y ) / ( fi[findex].dimensiony + 1 );
|
||||
sy = ( p.y - y ) % ( fi[findex].dimensiony + 1 );
|
||||
if ( sy >= fi[findex].dimensiony ) goto nope;
|
||||
|
||||
chanind = ( p.x - x ) / ( fi[findex].dimensionx + 1 );
|
||||
sx = ( p.x - x ) % ( fi[findex].dimensionx + 1 );
|
||||
if ( sx >= fi[findex].dimensionx ) goto nope;
|
||||
|
||||
ix = fi[findex].inputrects[ir*2];
|
||||
iy = fi[findex].inputrects[ir*2+1];
|
||||
|
||||
ts = fi[findex].timings + ( ( fi[findex].dimensionx * fi[findex].dimensiony * fi[findex].numtypes * ir ) + ( fi[findex].dimensionx * fi[findex].dimensiony * chanind ) + ( fi[findex].dimensionx * sy ) + sx ) * 2;
|
||||
|
||||
ox = 1+fi[findex].outputscalex*sx;
|
||||
oy = 1+fi[findex].outputscaley*sy;
|
||||
|
||||
if ( windowstatus != 2 )
|
||||
{
|
||||
int VF, HF, v_first, good;
|
||||
VF = ts[0];
|
||||
HF = ts[1];
|
||||
|
||||
v_first = vert_first( retrain_weights[chanind], ox, oy, ix, iy, STBIR_FILTER_MITCHELL, &v_info );
|
||||
|
||||
good = ( ((HF<=VF) && (!v_first)) || ((VF<=HF) && (v_first)));
|
||||
|
||||
if ( good )
|
||||
badstr[0] = 0;
|
||||
else
|
||||
{
|
||||
double r;
|
||||
|
||||
if ( HF < VF )
|
||||
r = (double)(VF-HF)/(double)HF;
|
||||
else
|
||||
r = (double)(HF-VF)/(double)VF;
|
||||
sprintf( badstr, " %.1f%% off", r*100 );
|
||||
}
|
||||
sprintf( buf + l, "\n\n%s\nCh: %d Resize: %dx%d to %dx%d\nV: %d H: %d Order: %c (%s%s)\nClass: %d Scale: %.2f %s", fi[findex].filename,fi[findex].effective[chanind], ix,iy,ox,oy, VF, HF, v_first?'V':'H', good?"Good":"Wrong", badstr, v_info.v_resize_classification, (double)oy/(double)iy, v_info.is_gather ? "Gather" : "Scatter" );
|
||||
}
|
||||
else
|
||||
{
|
||||
int v_first, time0, time1;
|
||||
float (* weights)[4] = stbir__compute_weights[chanind];
|
||||
int * ts1;
|
||||
char b0[32], b1[32];
|
||||
|
||||
ts1 = fi[1].timings + ( ts - fi[0].timings );
|
||||
|
||||
v_first = vert_first( weights, ox, oy, ix, iy, STBIR_FILTER_MITCHELL, &v_info );
|
||||
|
||||
time0 = ( v_first ) ? ts[0] : ts[1];
|
||||
time1 = ( v_first ) ? ts1[0] : ts1[1];
|
||||
|
||||
b0[0] = b1[0] = 0;
|
||||
if ( time0 < time1 )
|
||||
sprintf( b0," (%.f%% better)", ((double)time1-(double)time0)*100.0f/(double)time0);
|
||||
else
|
||||
sprintf( b1," (%.f%% better)", ((double)time0-(double)time1)*100.0f/(double)time1);
|
||||
|
||||
sprintf( buf + l, "\n\n0: %s\n1: %s\nCh: %d Resize: %dx%d to %dx%d\nClass: %d Scale: %.2f %s\nTime0: %d%s\nTime1: %d%s", fi[0].filename, fi[1].filename, fi[0].effective[chanind], ix,iy,ox,oy, v_info.v_resize_classification, (double)oy/(double)iy, v_info.is_gather ? "Gather" : "Scatter", time0, b0, time1, b1 );
|
||||
}
|
||||
}
|
||||
nope:
|
||||
|
||||
rc.left = 32+320; rc.right = 512+320;
|
||||
SetTextColor( dc, RGB(0,0,128) );
|
||||
DrawText( dc, buf, -1, &rc, DT_TOP );
|
||||
|
||||
}
|
||||
EndPaint( window, &ps );
|
||||
return 0;
|
||||
}
|
||||
|
||||
case WM_TIMER:
|
||||
InvalidateRect( window, 0, 0 );
|
||||
return 0;
|
||||
|
||||
case WM_DESTROY:
|
||||
PostQuitMessage( 0 );
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
return DefWindowProc( window, message, wparam, lparam );
|
||||
}
|
||||
|
||||
static void SetHighDPI(void)
|
||||
{
|
||||
typedef HRESULT WINAPI setdpitype(int v);
|
||||
HMODULE h=LoadLibrary("Shcore.dll");
|
||||
if (h)
|
||||
{
|
||||
setdpitype * sd = (setdpitype*)GetProcAddress(h,"SetProcessDpiAwareness");
|
||||
if (sd )
|
||||
sd(1);
|
||||
}
|
||||
}
|
||||
|
||||
static void draw_window()
|
||||
{
|
||||
WNDCLASS wc;
|
||||
HWND w;
|
||||
MSG msg;
|
||||
|
||||
instance = GetModuleHandle(NULL);
|
||||
|
||||
wc.style = 0;
|
||||
wc.lpfnWndProc = WindowProc;
|
||||
wc.cbClsExtra = 0;
|
||||
wc.cbWndExtra = 0;
|
||||
wc.hInstance = instance;
|
||||
wc.hIcon = 0;
|
||||
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
|
||||
wc.hbrBackground = 0;
|
||||
wc.lpszMenuName = 0;
|
||||
wc.lpszClassName = "WHTrain";
|
||||
|
||||
if ( !RegisterClass( &wc ) )
|
||||
exit(1);
|
||||
|
||||
SetHighDPI();
|
||||
|
||||
bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
||||
bmiHeader.biWidth = bitmapp/3;
|
||||
bmiHeader.biHeight = -bitmaph;
|
||||
bmiHeader.biPlanes = 1;
|
||||
bmiHeader.biBitCount = 24;
|
||||
bmiHeader.biCompression = BI_RGB;
|
||||
|
||||
w = CreateWindow( "WHTrain",
|
||||
"Vertical First Training",
|
||||
WS_CAPTION | WS_POPUP| WS_CLIPCHILDREN |
|
||||
WS_SYSMENU | WS_MINIMIZEBOX | WS_SIZEBOX,
|
||||
CW_USEDEFAULT,CW_USEDEFAULT,
|
||||
CW_USEDEFAULT,CW_USEDEFAULT,
|
||||
0, 0, instance, 0 );
|
||||
|
||||
{
|
||||
RECT r, c;
|
||||
GetWindowRect( w, &r );
|
||||
GetClientRect( w, &c );
|
||||
extrawindoww = ( r.right - r.left ) - ( c.right - c.left );
|
||||
extrawindowh = ( r.bottom - r.top ) - ( c.bottom - c.top );
|
||||
SetWindowPos( w, 0, 0, 0, bitmapw * curzoom + extrawindoww, bitmaph * curzoom + extrawindowh + 164, SWP_NOMOVE );
|
||||
}
|
||||
|
||||
ShowWindow( w, SW_SHOWNORMAL );
|
||||
SetTimer( w, 1, 250, 0 );
|
||||
|
||||
{
|
||||
BOOL ret;
|
||||
while( ( ret = GetMessage( &msg, w, 0, 0 ) ) != 0 )
|
||||
{
|
||||
if ( ret == -1 )
|
||||
break;
|
||||
TranslateMessage( &msg );
|
||||
DispatchMessage( &msg );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void retrain()
|
||||
{
|
||||
HANDLE threads[ 16 ];
|
||||
int chanind;
|
||||
|
||||
trainstart = GetTickCount();
|
||||
for( chanind = 0 ; chanind < fi[0].numtypes ; chanind++ )
|
||||
threads[ chanind ] = CreateThread( 0, 2048*1024, retrain_shim, (LPVOID)(size_t)chanind, 0, 0 );
|
||||
|
||||
draw_window();
|
||||
|
||||
for( chanind = 0 ; chanind < fi[0].numtypes ; chanind++ )
|
||||
{
|
||||
WaitForSingleObject( threads[ chanind ], INFINITE );
|
||||
CloseHandle( threads[ chanind ] );
|
||||
}
|
||||
|
||||
write_bitmap();
|
||||
|
||||
print_struct( retrain_weights, "retained_weights" );
|
||||
if ( windowstatus ) printf( "CANCELLED!\n" );
|
||||
}
|
||||
|
||||
static void info()
|
||||
{
|
||||
int findex;
|
||||
|
||||
// display info about each input file
|
||||
for( findex = 0 ; findex < numfileinfo ; findex++ )
|
||||
{
|
||||
int i, h,m,s;
|
||||
if ( findex ) printf( "\n" );
|
||||
printf( "Timing file: %s\n", fi[findex].filename );
|
||||
printf( "CPU type: %d %s\n", fi[findex].cpu, fi[findex].simd?(fi[findex].simd==2?"SIMD8":"SIMD4"):"Scalar" );
|
||||
h = fi[findex].milliseconds/3600000;
|
||||
m = (fi[findex].milliseconds-h*3600000)/60000;
|
||||
s = (fi[findex].milliseconds-h*3600000-m*60000)/1000;
|
||||
printf( "Total time in test: %dh %dm %ds Cycles/sec: %.f\n", h,m,s, 1000.0/fi[findex].scale_time );
|
||||
printf( "Each tile of samples is %dx%d, and is scaled by %dx%d.\n", fi[findex].dimensionx,fi[findex].dimensiony, fi[findex].outputscalex,fi[findex].outputscaley );
|
||||
printf( "So the x coords are: " );
|
||||
for( i=0; i < fi[findex].dimensionx ; i++ ) printf( "%d ",1+i*fi[findex].outputscalex );
|
||||
printf( "\n" );
|
||||
printf( "And the y coords are: " );
|
||||
for( i=0; i < fi[findex].dimensiony ; i++ ) printf( "%d ",1+i*fi[findex].outputscaley );
|
||||
printf( "\n" );
|
||||
printf( "There are %d channel counts and they are: ", fi[findex].numtypes );
|
||||
for( i=0; i < fi[findex].numtypes ; i++ ) printf( "%d ",fi[findex].effective[i] );
|
||||
printf( "\n" );
|
||||
printf( "There are %d input rect sizes and they are: ", fi[findex].numinputrects );
|
||||
for( i=0; i < fi[findex].numtypes ; i++ ) printf( "%dx%d ",fi[findex].inputrects[i*2],fi[findex].inputrects[i*2+1] );
|
||||
printf( "\n" );
|
||||
}
|
||||
}
|
||||
|
||||
static void current( int do_win, int do_bitmap )
|
||||
{
|
||||
int i, findex;
|
||||
|
||||
trainstart = GetTickCount();
|
||||
|
||||
// clear progress
|
||||
memset( windowranges, 0, sizeof( windowranges ) );
|
||||
// copy in appropriate weights
|
||||
memcpy( retrain_weights, stbir__compute_weights, sizeof( retrain_weights ) );
|
||||
|
||||
// build and print current errors and build current bitmap
|
||||
for( i = 0 ; i < fi[0].numtypes ; i++ )
|
||||
{
|
||||
double curerr[STBIR_RESIZE_CLASSIFICATIONS];
|
||||
int curtot[STBIR_RESIZE_CLASSIFICATIONS];
|
||||
float (* weights)[4] = retrain_weights[i];
|
||||
|
||||
calc_errors( weights, curtot, curerr, i );
|
||||
if ( !do_bitmap )
|
||||
print_weights( weights, i, curtot, curerr );
|
||||
|
||||
for( findex = 0 ; findex < numfileinfo ; findex++ )
|
||||
build_bitmap( weights, i, findex );
|
||||
}
|
||||
|
||||
if ( do_win )
|
||||
draw_window();
|
||||
|
||||
if ( do_bitmap )
|
||||
write_bitmap();
|
||||
}
|
||||
|
||||
static void compare()
|
||||
{
|
||||
int i;
|
||||
|
||||
trainstart = GetTickCount();
|
||||
windowstatus = 2; // comp mode
|
||||
|
||||
// clear progress
|
||||
memset( windowranges, 0, sizeof( windowranges ) );
|
||||
|
||||
if ( ( fi[0].numtypes != fi[1].numtypes ) || ( fi[0].numinputrects != fi[1].numinputrects ) ||
|
||||
( fi[0].dimensionx != fi[1].dimensionx ) || ( fi[0].dimensiony != fi[1].dimensiony ) ||
|
||||
( fi[0].outputscalex != fi[1].outputscalex ) || ( fi[0].outputscaley != fi[1].outputscaley ) )
|
||||
{
|
||||
err:
|
||||
printf( "Timing files don't match.\n" );
|
||||
exit(5);
|
||||
}
|
||||
|
||||
for( i=0; i < fi[0].numtypes ; i++ )
|
||||
{
|
||||
if ( fi[0].effective[i] != fi[1].effective[i] ) goto err;
|
||||
if ( fi[0].inputrects[i*2] != fi[1].inputrects[i*2] ) goto err;
|
||||
if ( fi[0].inputrects[i*2+1] != fi[1].inputrects[i*2+1] ) goto err;
|
||||
}
|
||||
|
||||
alloc_bitmap( 1 );
|
||||
|
||||
for( i = 0 ; i < fi[0].numtypes ; i++ )
|
||||
{
|
||||
float (* weights)[4] = stbir__compute_weights[i];
|
||||
build_comp_bitmap( weights, i );
|
||||
}
|
||||
|
||||
draw_window();
|
||||
}
|
||||
|
||||
static void load_files( char ** args, int count )
|
||||
{
|
||||
int i;
|
||||
|
||||
if ( count == 0 )
|
||||
{
|
||||
printf( "No timing files listed!" );
|
||||
exit(3);
|
||||
}
|
||||
|
||||
for ( i = 0 ; i < count ; i++ )
|
||||
{
|
||||
if ( !use_timing_file( args[i], i ) )
|
||||
{
|
||||
printf( "Bad timing file %s\n", args[i] );
|
||||
exit(2);
|
||||
}
|
||||
}
|
||||
numfileinfo = count;
|
||||
}
|
||||
|
||||
int main( int argc, char ** argv )
|
||||
{
|
||||
int check;
|
||||
if ( argc < 3 )
|
||||
{
|
||||
err:
|
||||
printf( "vf_train retrain [timing_filenames....] - recalcs weights for all the files on the command line.\n");
|
||||
printf( "vf_train info [timing_filenames....] - shows info about each timing file.\n");
|
||||
printf( "vf_train check [timing_filenames...] - show results for the current weights for all files listed.\n");
|
||||
printf( "vf_train compare <timing file1> <timing file2> - compare two timing files (must only be two files and same resolution).\n");
|
||||
printf( "vf_train bitmap [timing_filenames...] - write out results.png, comparing against the current weights for all files listed.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
check = ( strcmp( argv[1], "check" ) == 0 );
|
||||
if ( ( check ) || ( strcmp( argv[1], "bitmap" ) == 0 ) )
|
||||
{
|
||||
load_files( argv + 2, argc - 2 );
|
||||
alloc_bitmap( numfileinfo );
|
||||
current( check, !check );
|
||||
}
|
||||
else if ( strcmp( argv[1], "info" ) == 0 )
|
||||
{
|
||||
load_files( argv + 2, argc - 2 );
|
||||
info();
|
||||
}
|
||||
else if ( strcmp( argv[1], "compare" ) == 0 )
|
||||
{
|
||||
if ( argc != 4 )
|
||||
{
|
||||
printf( "You must specify two files to compare.\n" );
|
||||
exit(4);
|
||||
}
|
||||
|
||||
load_files( argv + 2, argc - 2 );
|
||||
compare();
|
||||
}
|
||||
else if ( strcmp( argv[1], "retrain" ) == 0 )
|
||||
{
|
||||
load_files( argv + 2, argc - 2 );
|
||||
alloc_bitmap( numfileinfo );
|
||||
retrain();
|
||||
}
|
||||
else
|
||||
{
|
||||
goto err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
13
external/stb/stb/tests/resample_test.cpp
vendored
13
external/stb/stb/tests/resample_test.cpp
vendored
@ -64,7 +64,7 @@ void stbir_progress(float p)
|
||||
#define STBIR_PROGRESS_REPORT stbir_progress
|
||||
#define STB_IMAGE_RESIZE_IMPLEMENTATION
|
||||
#define STB_IMAGE_RESIZE_STATIC
|
||||
#include "stb_image_resize.h"
|
||||
#include "stb_image_resize2.h"
|
||||
|
||||
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
||||
#include "stb_image_write.h"
|
||||
@ -143,7 +143,7 @@ void resizer(int argc, char **argv)
|
||||
out_h = h*3;
|
||||
output_pixels = (unsigned char*) malloc(out_w*out_h*n);
|
||||
//stbir_resize_uint8_srgb(input_pixels, w, h, 0, output_pixels, out_w, out_h, 0, n, -1,0);
|
||||
stbir_resize_uint8(input_pixels, w, h, 0, output_pixels, out_w, out_h, 0, n);
|
||||
stbir_resize_uint8_linear(input_pixels, w, h, 0, output_pixels, out_w, out_h, 0, (stbir_pixel_layout) n);
|
||||
stbi_write_png("output.png", out_w, out_h, n, output_pixels, 0);
|
||||
exit(0);
|
||||
}
|
||||
@ -171,9 +171,9 @@ void performance(int argc, char **argv)
|
||||
output_pixels = (unsigned char*) malloc(out_w*out_h*n);
|
||||
for (i=0; i < count; ++i)
|
||||
if (srgb)
|
||||
stbir_resize_uint8_srgb(input_pixels, w, h, 0, output_pixels, out_w, out_h, 0, n,-1,0);
|
||||
stbir_resize_uint8_srgb(input_pixels, w, h, 0, output_pixels, out_w, out_h, 0, (stbir_pixel_layout) n);
|
||||
else
|
||||
stbir_resize(input_pixels, w, h, 0, output_pixels, out_w, out_h, 0, STBIR_TYPE_UINT8, n,-1, 0, STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_FILTER_DEFAULT, STBIR_FILTER_DEFAULT, STBIR_COLORSPACE_LINEAR, NULL);
|
||||
stbir_resize_uint8_linear(input_pixels, w, h, 0, output_pixels, out_w, out_h, 0, (stbir_pixel_layout) n);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
@ -188,6 +188,7 @@ int main(int argc, char** argv)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
void resize_image(const char* filename, float width_percent, float height_percent, stbir_filter filter, stbir_edge edge, stbir_colorspace colorspace, const char* output_filename)
|
||||
{
|
||||
int w, h, n;
|
||||
@ -1120,3 +1121,7 @@ void test_suite(int argc, char **argv)
|
||||
resize_image("gamma_2.2.jpg", .5f, .5f, STBIR_FILTER_CATMULLROM, STBIR_EDGE_REFLECT, STBIR_COLORSPACE_SRGB, "test-output/gamma_2.2.jpg");
|
||||
resize_image("gamma_dalai_lama_gray.jpg", .5f, .5f, STBIR_FILTER_CATMULLROM, STBIR_EDGE_REFLECT, STBIR_COLORSPACE_SRGB, "test-output/gamma_dalai_lama_gray.jpg");
|
||||
}
|
||||
#endif
|
||||
void test_suite(int argc, char **argv)
|
||||
{
|
||||
}
|
||||
|
2
external/stb/stb/tests/resize.dsp
vendored
2
external/stb/stb/tests/resize.dsp
vendored
@ -88,7 +88,7 @@ SOURCE=.\resample_test.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\stb_image_resize.h
|
||||
SOURCE=..\stb_image_resize2.h
|
||||
# End Source File
|
||||
# End Target
|
||||
# End Project
|
||||
|
4
external/stb/stb/tests/stb.dsp
vendored
4
external/stb/stb/tests/stb.dsp
vendored
@ -130,10 +130,6 @@ SOURCE=..\stb_image.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\stb_image_resize.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\stb_image_write.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
5
external/stb/stb/tests/test_c_compilation.c
vendored
5
external/stb/stb/tests/test_c_compilation.c
vendored
@ -1,3 +1,6 @@
|
||||
#define STB_IMAGE_RESIZE_IMPLEMENTATION
|
||||
#include "stb_image_resize2.h"
|
||||
|
||||
#define STB_SPRINTF_IMPLEMENTATION
|
||||
#include "stb_sprintf.h"
|
||||
|
||||
@ -7,7 +10,6 @@
|
||||
#define STB_DIVIDE_IMPLEMENTATION
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#define STB_HERRINGBONE_WANG_TILE_IMEPLEMENTATIOn
|
||||
#define STB_IMAGE_RESIZE_IMPLEMENTATION
|
||||
#define STB_RECT_PACK_IMPLEMENTATION
|
||||
#define STB_VOXEL_RENDER_IMPLEMENTATION
|
||||
#define STB_EASY_FONT_IMPLEMENTATION
|
||||
@ -20,7 +22,6 @@
|
||||
#include "stb_perlin.h"
|
||||
#include "stb_c_lexer.h"
|
||||
#include "stb_divide.h"
|
||||
#include "stb_image_resize.h"
|
||||
#include "stb_rect_pack.h"
|
||||
#include "stb_dxt.h"
|
||||
#include "stb_include.h"
|
||||
|
@ -70,7 +70,7 @@ void my_free(void *) { }
|
||||
#include "stb_leakcheck.h"
|
||||
|
||||
#define STB_IMAGE_RESIZE_IMPLEMENTATION
|
||||
#include "stb_image_resize.h"
|
||||
#include "stb_image_resize2.h"
|
||||
|
||||
//#include "stretchy_buffer.h" // deprecating
|
||||
|
||||
|
8
external/stb/stb/tools/README.header.md
vendored
8
external/stb/stb/tools/README.header.md
vendored
@ -3,16 +3,18 @@ stb
|
||||
|
||||
single-file public domain (or MIT licensed) libraries for C/C++
|
||||
|
||||
# This project discusses security-relevant bugs in public in Github Issues and Pull Requests, and it may take significant time for security fixes to be implemented or merged. If this poses an unreasonable risk to your project, do not use stb libraries.
|
||||
|
||||
Noteworthy:
|
||||
|
||||
* image loader: [stb_image.h](stb_image.h)
|
||||
* image writer: [stb_image_write.h](stb_image_write.h)
|
||||
* image resizer: [stb_image_resize.h](stb_image_resize.h)
|
||||
* image resizer: [stb_image_resize2.h](stb_image_resize2.h)
|
||||
* font text rasterizer: [stb_truetype.h](stb_truetype.h)
|
||||
* typesafe containers: [stb_ds.h](stb_ds.h)
|
||||
|
||||
Most libraries by stb, except: stb_dxt by Fabian "ryg" Giesen, stb_image_resize
|
||||
by Jorge L. "VinoBS" Rodriguez, and stb_sprintf by Jeff Roberts.
|
||||
Most libraries by stb, except: stb_dxt by Fabian "ryg" Giesen, original stb_image_resize
|
||||
by Jorge L. "VinoBS" Rodriguez, and stb_image_resize2 and stb_sprintf by Jeff Roberts.
|
||||
|
||||
<a name="stb_libs"></a>
|
||||
|
||||
|
2
external/stb/stb/tools/README.list
vendored
2
external/stb/stb/tools/README.list
vendored
@ -3,7 +3,7 @@ stb_hexwave.h | audio | audio waveform synthesizer
|
||||
stb_image.h | graphics | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC
|
||||
stb_truetype.h | graphics | parse, decode, and rasterize characters from truetype fonts
|
||||
stb_image_write.h | graphics | image writing to disk: PNG, TGA, BMP
|
||||
stb_image_resize.h | graphics | resize images larger/smaller with good quality
|
||||
stb_image_resize2.h | graphics | resize images larger/smaller with good quality
|
||||
stb_rect_pack.h | graphics | simple 2D rectangle packer with decent quality
|
||||
stb_perlin.h | graphics | perlin's revised simplex noise w/ different seeds
|
||||
stb_ds.h | utility | typesafe dynamic array and hash tables for C, will compile in C++
|
||||
|
8
external/toxcore/CMakeLists.txt
vendored
8
external/toxcore/CMakeLists.txt
vendored
@ -19,6 +19,8 @@ add_library(toxcore STATIC
|
||||
${TOX_DIR}toxcore/ccompat.h
|
||||
${TOX_DIR}toxcore/crypto_core.c
|
||||
${TOX_DIR}toxcore/crypto_core.h
|
||||
${TOX_DIR}toxcore/crypto_core_pack.c
|
||||
${TOX_DIR}toxcore/crypto_core_pack.h
|
||||
${TOX_DIR}toxcore/DHT.c
|
||||
${TOX_DIR}toxcore/DHT.h
|
||||
${TOX_DIR}toxcore/events/conference_connected.c
|
||||
@ -27,6 +29,7 @@ add_library(toxcore STATIC
|
||||
${TOX_DIR}toxcore/events/conference_peer_list_changed.c
|
||||
${TOX_DIR}toxcore/events/conference_peer_name.c
|
||||
${TOX_DIR}toxcore/events/conference_title.c
|
||||
${TOX_DIR}toxcore/events/dht_get_nodes_response.c
|
||||
${TOX_DIR}toxcore/events/events_alloc.c
|
||||
${TOX_DIR}toxcore/events/events_alloc.h
|
||||
${TOX_DIR}toxcore/events/file_chunk_request.c
|
||||
@ -209,8 +212,3 @@ add_executable(DHT_Bootstrap EXCLUDE_FROM_ALL
|
||||
)
|
||||
target_link_libraries(DHT_Bootstrap toxcore)
|
||||
|
||||
add_executable(mono_time_test
|
||||
./mono_time_test.cc
|
||||
)
|
||||
target_link_libraries(mono_time_test toxcore)
|
||||
target_compile_features(mono_time_test PUBLIC cxx_std_11)
|
||||
|
32
external/toxcore/c-toxcore/.cirrus.yml
vendored
32
external/toxcore/c-toxcore/.cirrus.yml
vendored
@ -27,6 +27,7 @@ bazel-dbg_task:
|
||||
- cd /src/workspace && bazel test -k
|
||||
--build_tag_filters=-haskell
|
||||
--test_tag_filters=-haskell
|
||||
--remote_http_cache=http://$CIRRUS_HTTP_CACHE_HOST
|
||||
--
|
||||
//c-toxcore/...
|
||||
-//c-toxcore/auto_tests:tcp_relay_test # TODO(robinlinden): Why does this pass locally but not in Cirrus?
|
||||
@ -47,13 +48,30 @@ cimple_task:
|
||||
//c-toxcore/...
|
||||
|
||||
freebsd_task:
|
||||
container:
|
||||
image: toxchat/freebsd:latest
|
||||
cpu: 2
|
||||
memory: 4G
|
||||
kvm: true
|
||||
freebsd_instance:
|
||||
image_family: freebsd-14-0
|
||||
configure_script:
|
||||
- PAGER=cat ASSUME_ALWAYS_YES=YES pkg install
|
||||
cmake
|
||||
git
|
||||
gmake
|
||||
googletest
|
||||
libconfig
|
||||
libsodium
|
||||
libvpx
|
||||
opus
|
||||
pkgconf
|
||||
- git submodule update --init --recursive
|
||||
- cd .. && mv cirrus-ci-build /work/c-toxcore && mkdir cirrus-ci-build
|
||||
test_all_script:
|
||||
- cd /work/c-toxcore && .github/scripts/cmake-freebsd
|
||||
- |
|
||||
# TODO(iphydf): Investigate FreeBSD failures on these tests.
|
||||
sed -Ei -e '/\(dht_getnodes_api\)/s/^/#/' auto_tests/CMakeLists.txt
|
||||
cmake . \
|
||||
-DMIN_LOGGER_LEVEL=TRACE \
|
||||
-DMUST_BUILD_TOXAV=ON \
|
||||
-DNON_HERMETIC_TESTS=ON \
|
||||
-DTEST_TIMEOUT_SECONDS=50 \
|
||||
-DUSE_IPV6=OFF \
|
||||
-DAUTOTEST=ON
|
||||
cmake --build . --target install
|
||||
ctest -j50 --output-on-failure --rerun-failed --repeat until-pass:6
|
||||
|
10
external/toxcore/c-toxcore/.clang-tidy
vendored
10
external/toxcore/c-toxcore/.clang-tidy
vendored
@ -21,7 +21,7 @@ CheckOptions:
|
||||
- key: readability-identifier-naming.MacroDefinitionCase
|
||||
value: UPPER_CASE
|
||||
- key: readability-identifier-naming.MacroDefinitionIgnoredRegexp
|
||||
value: "^_.*|nullable|non_null|nullptr|static_assert|ck_.*"
|
||||
value: "^_.*|bitwise|force|nullable|non_null|nullptr|static_assert|ck_.*"
|
||||
- key: readability-identifier-naming.ParameterCase
|
||||
value: lower_case
|
||||
- key: readability-identifier-naming.StructCase
|
||||
@ -36,12 +36,14 @@ CheckOptions:
|
||||
value: lower_case
|
||||
|
||||
- key: llvmlibc-restrict-system-libc-headers.Includes
|
||||
value: "arpa/inet.h,assert.h,ctype.h,errno.h,fcntl.h,getopt.h,libconfig.h,limits.h,linux/if.h,math.h,netdb.h,netinet/in.h,opus.h,pthread.h,signal.h,sodium/crypto_scalarmult_curve25519.h,sodium.h,sodium/randombytes.h,stdarg.h,stdbool.h,stddef.h,stdint.h,stdio.h,stdlib.h,string.h,sys/ioctl.h,syslog.h,sys/resource.h,sys/socket.h,sys/stat.h,sys/time.h,sys/types.h,time.h,unistd.h,vpx/vp8cx.h,vpx/vp8dx.h,vpx/vpx_decoder.h,vpx/vpx_encoder.h,vpx/vpx_image.h"
|
||||
value: "alloca.h,arpa/inet.h,assert.h,ctype.h,errno.h,fcntl.h,getopt.h,libconfig.h,limits.h,linux/if.h,math.h,netdb.h,netinet/in.h,opus.h,pthread.h,signal.h,sodium/crypto_scalarmult_curve25519.h,sodium.h,sodium/randombytes.h,stdarg.h,stdbool.h,stddef.h,stdint.h,stdio.h,stdlib.h,string.h,sys/ioctl.h,syslog.h,sys/resource.h,sys/socket.h,sys/stat.h,sys/time.h,sys/types.h,time.h,unistd.h,vpx/vp8cx.h,vpx/vp8dx.h,vpx/vpx_decoder.h,vpx/vpx_encoder.h,vpx/vpx_image.h"
|
||||
- key: hicpp-signed-bitwise.IgnorePositiveIntegerLiterals
|
||||
value: true
|
||||
- key: concurrency-mt-unsafe.FunctionSet
|
||||
value: posix
|
||||
- key: misc-include-cleaner.IgnoreHeaders
|
||||
value: "pthread.h;stdbool.h;stddef.h;stdint.;stdint.h;stdint...;cstdint;sodium.*;sys/.*;unistd.h;opus.*;vpx.*;attributes.h;tox_struct.h"
|
||||
- key: readability-function-cognitive-complexity.Threshold
|
||||
value: 153 # TODO(iphydf): Decrease. tox_new is the highest at the moment.
|
||||
- key: cppcoreguidelines-avoid-do-while.IgnoreMacros
|
||||
value: true
|
||||
- key: readability-simplify-boolean-expr.SimplifyDeMorgan
|
||||
value: false
|
||||
|
@ -18,7 +18,7 @@ docker run \
|
||||
-e ENABLE_ARCH_i686="$i686" \
|
||||
-e ENABLE_ARCH_x86_64="$x86_64" \
|
||||
-e ENABLE_TEST=true \
|
||||
-e EXTRA_CMAKE_FLAGS="-DBOOTSTRAP_DAEMON=OFF -DMIN_LOGGER_LEVEL=DEBUG -DTEST_TIMEOUT_SECONDS=90 -DAUTOTEST=ON" \
|
||||
-e EXTRA_CMAKE_FLAGS="-DBOOTSTRAP_DAEMON=OFF -DMIN_LOGGER_LEVEL=DEBUG -DTEST_TIMEOUT_SECONDS=90 -DAUTOTEST=ON -DUSE_IPV6=OFF" \
|
||||
-e CMAKE_C_FLAGS="$C_FLAGS" \
|
||||
-e CMAKE_CXX_FLAGS="$CXX_FLAGS" \
|
||||
-e CMAKE_EXE_LINKER_FLAGS="$LD_FLAGS" \
|
||||
@ -26,4 +26,6 @@ docker run \
|
||||
-v "$PWD:/toxcore" \
|
||||
-v "$PWD/result:/prefix" \
|
||||
--rm \
|
||||
-t \
|
||||
--pull never \
|
||||
"toxchat/windows:$WINDOWS_ARCH"
|
||||
|
@ -3,10 +3,11 @@
|
||||
set -exu -o pipefail
|
||||
|
||||
LOCAL="${1:-}"
|
||||
CHECK="${2:-}"
|
||||
|
||||
readarray -t FILES <<<"$(git ls-files)"
|
||||
|
||||
if ! tar c "${FILES[@]}" | docker build -f other/bootstrap_daemon/docker/Dockerfile -t toxchat/bootstrap-node - 2>&1 | tee docker-build.log; then
|
||||
if ! tar c "${FILES[@]}" | docker build --build-arg="CHECK=$CHECK" -f other/bootstrap_daemon/docker/Dockerfile -t toxchat/bootstrap-node - 2>&1 | tee docker-build.log; then
|
||||
grep -o "::error.*::[a-f0-9]* /usr/local/bin/tox-bootstrapd" docker-build.log
|
||||
false
|
||||
fi
|
||||
|
@ -15,16 +15,24 @@ jobs:
|
||||
|
||||
analysis:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
tool: [autotools, clang-tidy, compcert, cppcheck, doxygen, infer, misra, tcc, tokstyle]
|
||||
tool: [autotools, clang-tidy, compcert, cppcheck, doxygen, goblint, infer, freebsd, misra, modules, pkgsrc, rpm, slimcc, sparse, tcc, tokstyle]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
- name: Docker Build
|
||||
uses: docker/build-push-action@v4
|
||||
with:
|
||||
file: other/docker/${{ matrix.tool }}/Dockerfile
|
||||
driver: docker
|
||||
- name: Build toxchat/c-toxcore:sources
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
file: other/docker/sources/sources.Dockerfile
|
||||
tags: toxchat/c-toxcore:sources
|
||||
- name: Docker Build
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
file: other/docker/${{ matrix.tool }}/${{ matrix.tool }}.Dockerfile
|
||||
|
||||
coverage-linux:
|
||||
runs-on: ubuntu-latest
|
||||
@ -75,7 +83,7 @@ jobs:
|
||||
- name: Build and test
|
||||
run: .github/scripts/cmake-osx
|
||||
|
||||
build-msvc:
|
||||
build-windows-msvc:
|
||||
strategy:
|
||||
matrix:
|
||||
version: [2019, 2022]
|
||||
@ -102,17 +110,77 @@ jobs:
|
||||
cd _build
|
||||
ctest -j50 --output-on-failure --rerun-failed --repeat until-pass:6 --build-config Debug
|
||||
|
||||
build-windows:
|
||||
strategy:
|
||||
matrix:
|
||||
bits: [32, 64]
|
||||
build-netbsd:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Cross compilation
|
||||
run: .github/scripts/cmake-win${{ matrix.bits }} script
|
||||
- name: Test in NetBSD
|
||||
id: test
|
||||
uses: vmactions/netbsd-vm@v1
|
||||
with:
|
||||
usesh: true
|
||||
copyback: false
|
||||
prepare:
|
||||
/usr/sbin/pkg_add
|
||||
cmake
|
||||
googletest
|
||||
libconfig
|
||||
libopus
|
||||
libsodium
|
||||
libvpx
|
||||
pkg-config
|
||||
|
||||
run: |
|
||||
# TODO(iphydf): Investigate NetBSD failures on these tests.
|
||||
sed -Ei -e '/\((TCP|dht_getnodes_api)\)/s/^/#/' auto_tests/CMakeLists.txt
|
||||
cmake . \
|
||||
-DMIN_LOGGER_LEVEL=TRACE \
|
||||
-DMUST_BUILD_TOXAV=ON \
|
||||
-DNON_HERMETIC_TESTS=ON \
|
||||
-DTEST_TIMEOUT_SECONDS=90 \
|
||||
-DUSE_IPV6=OFF \
|
||||
-DAUTOTEST=ON
|
||||
cmake --build . --target install
|
||||
ctest -j50 --output-on-failure --rerun-failed --repeat until-pass:6
|
||||
|
||||
build-freebsd:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Test in FreeBSD
|
||||
id: test
|
||||
uses: vmactions/freebsd-vm@v1
|
||||
with:
|
||||
usesh: true
|
||||
copyback: false
|
||||
prepare:
|
||||
PAGER=cat ASSUME_ALWAYS_YES=YES pkg install
|
||||
cmake
|
||||
git
|
||||
gmake
|
||||
googletest
|
||||
libconfig
|
||||
libsodium
|
||||
libvpx
|
||||
opus
|
||||
pkgconf
|
||||
|
||||
run: |
|
||||
# TODO(iphydf): Investigate FreeBSD failures on these tests.
|
||||
sed -Ei -e '/\(dht_getnodes_api\)/s/^/#/' auto_tests/CMakeLists.txt
|
||||
cmake . \
|
||||
-DMIN_LOGGER_LEVEL=TRACE \
|
||||
-DMUST_BUILD_TOXAV=ON \
|
||||
-DNON_HERMETIC_TESTS=ON \
|
||||
-DTEST_TIMEOUT_SECONDS=50 \
|
||||
-DUSE_IPV6=OFF \
|
||||
-DAUTOTEST=ON
|
||||
cmake --build . --target install
|
||||
ctest -j50 --output-on-failure --rerun-failed --repeat until-pass:6
|
||||
|
||||
mypy:
|
||||
runs-on: ubuntu-latest
|
||||
|
@ -8,7 +8,7 @@ jobs:
|
||||
latest:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Install libraries
|
||||
|
@ -25,7 +25,9 @@ jobs:
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Docker Build
|
||||
run: .github/scripts/tox-bootstrapd-docker local
|
||||
run: .github/scripts/tox-bootstrapd-docker local "$CHECK"
|
||||
env:
|
||||
CHECK: "${{ contains(github.event.pull_request.title, 'chore: Release ') && 'sha256sum' || 'echo' }}"
|
||||
- name: Push latest image to DockerHub
|
||||
if: ${{ github.event_name == 'push' }}
|
||||
run: docker push toxchat/bootstrap-node:latest
|
||||
@ -46,7 +48,7 @@ jobs:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v4
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: "{{defaultContext}}:other/bootstrap_daemon/websocket"
|
||||
push: ${{ github.event_name == 'push' }}
|
||||
@ -67,7 +69,7 @@ jobs:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v4
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: "."
|
||||
file: .clusterfuzzlite/Dockerfile
|
||||
@ -88,7 +90,7 @@ jobs:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v4
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
file: testing/Dockerfile
|
||||
push: ${{ github.event_name == 'push' }}
|
||||
@ -108,7 +110,7 @@ jobs:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v4
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
file: other/emscripten/Dockerfile
|
||||
push: ${{ github.event_name == 'push' }}
|
||||
@ -121,21 +123,14 @@ jobs:
|
||||
steps:
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
with:
|
||||
driver: docker
|
||||
- name: Login to DockerHub
|
||||
if: ${{ github.event_name == 'push' }}
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
- name: Build toxchat/c-toxcore:sources
|
||||
uses: docker/build-push-action@v4
|
||||
with:
|
||||
file: other/docker/sources/Dockerfile
|
||||
tags: toxchat/c-toxcore:sources
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v4
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
file: other/docker/esp32/Dockerfile
|
||||
push: ${{ github.event_name == 'push' }}
|
||||
@ -143,9 +138,15 @@ jobs:
|
||||
cache-from: type=registry,ref=toxchat/c-toxcore:esp32
|
||||
cache-to: type=inline
|
||||
|
||||
docker-win32:
|
||||
docker-windows-mingw:
|
||||
strategy:
|
||||
matrix:
|
||||
bits: [32, 64]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
- name: Login to DockerHub
|
||||
@ -154,39 +155,27 @@ jobs:
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v4
|
||||
- name: Build and store to local Docker daemon
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: "{{defaultContext}}:other/docker/windows"
|
||||
push: ${{ github.event_name == 'push' }}
|
||||
tags: toxchat/windows:win32
|
||||
cache-from: type=registry,ref=toxchat/windows:win32
|
||||
cache-to: type=inline
|
||||
context: other/docker/windows
|
||||
load: true
|
||||
tags: toxchat/windows:win${{ matrix.bits }}
|
||||
cache-from: type=registry,ref=toxchat/windows:win${{ matrix.bits }}
|
||||
build-args: |
|
||||
SUPPORT_ARCH_i686=true
|
||||
SUPPORT_ARCH_x86_64=false
|
||||
SUPPORT_ARCH_i686=${{ matrix.bits == '32' }}
|
||||
SUPPORT_ARCH_x86_64=${{ matrix.bits == '64' }}
|
||||
SUPPORT_TEST=true
|
||||
|
||||
docker-win64:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
- name: Login to DockerHub
|
||||
- name: Push the stored image to Dockerhub
|
||||
if: ${{ github.event_name == 'push' }}
|
||||
uses: docker/login-action@v3
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v4
|
||||
with:
|
||||
context: "{{defaultContext}}:other/docker/windows"
|
||||
context: other/docker/windows
|
||||
push: ${{ github.event_name == 'push' }}
|
||||
tags: toxchat/windows:win64
|
||||
cache-from: type=registry,ref=toxchat/windows:win64
|
||||
cache-to: type=inline
|
||||
tags: toxchat/windows:win${{ matrix.bits }}
|
||||
build-args: |
|
||||
SUPPORT_ARCH_i686=false
|
||||
SUPPORT_ARCH_x86_64=true
|
||||
SUPPORT_ARCH_i686=${{ matrix.bits == '32' }}
|
||||
SUPPORT_ARCH_x86_64=${{ matrix.bits == '64' }}
|
||||
SUPPORT_TEST=true
|
||||
- name: Cross-compile
|
||||
run: .github/scripts/cmake-win${{ matrix.bits }} script
|
||||
|
@ -11,7 +11,7 @@ jobs:
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
- name: Docker Build
|
||||
uses: docker/build-push-action@v4
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
file: other/docker/alpine-s390x/Dockerfile
|
||||
|
||||
@ -29,14 +29,14 @@ jobs:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
- name: Build toxchat/c-toxcore:sources
|
||||
uses: docker/build-push-action@v4
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
file: other/docker/sources/Dockerfile
|
||||
file: other/docker/sources/sources.Dockerfile
|
||||
tags: toxchat/c-toxcore:sources
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v4
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
file: other/docker/coverage/Dockerfile
|
||||
file: other/docker/coverage/coverage.Dockerfile
|
||||
push: ${{ github.event_name == 'push' }}
|
||||
tags: toxchat/c-toxcore:coverage
|
||||
cache-from: type=registry,ref=toxchat/c-toxcore:coverage
|
||||
|
13
external/toxcore/c-toxcore/.restyled.yaml
vendored
13
external/toxcore/c-toxcore/.restyled.yaml
vendored
@ -1,20 +1,25 @@
|
||||
---
|
||||
exclude:
|
||||
- "**/*.api.h"
|
||||
# shfmt doesn't support this file
|
||||
# shfmt doesn't support this file.
|
||||
- "other/analysis/run-clang-tidy"
|
||||
# Generated file.
|
||||
- "CHANGELOG.md"
|
||||
|
||||
restylers:
|
||||
- astyle:
|
||||
image: restyled/restyler-astyle:d7967bcb8b622a98524b7df1da1b02652114cf9a
|
||||
arguments: ["--options=other/astyle/astylerc"]
|
||||
include:
|
||||
- "!**/*.cc"
|
||||
- "**/*.c"
|
||||
- "**/*.h"
|
||||
- autopep8
|
||||
- black
|
||||
- clang-format:
|
||||
image: restyled/restyler-clang-format:13.0.1
|
||||
image: restyled/restyler-clang-format:v16.0.6
|
||||
include:
|
||||
- "**/*.cc"
|
||||
- "**/*.hh"
|
||||
- prettier-markdown
|
||||
- prettier-yaml
|
||||
- reorder-python-imports
|
||||
- shellharden
|
||||
|
20
external/toxcore/c-toxcore/CMakeLists.txt
vendored
20
external/toxcore/c-toxcore/CMakeLists.txt
vendored
@ -136,18 +136,20 @@ if(MIN_LOGGER_LEVEL)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
option(EXPERIMENTAL_API "Install experimental header file with unstable API" OFF)
|
||||
|
||||
option(USE_IPV6 "Use IPv6 in tests" ON)
|
||||
if(NOT USE_IPV6)
|
||||
add_definitions(-DUSE_IPV6=0)
|
||||
endif()
|
||||
|
||||
option(BUILD_MISC_TESTS "Build additional tests and utilities" OFF)
|
||||
option(BUILD_MISC_TESTS "Build additional tests" OFF)
|
||||
option(BUILD_FUN_UTILS "Build additional just for fun utilities" OFF)
|
||||
|
||||
option(AUTOTEST "Enable autotests (mainly for CI)" OFF)
|
||||
if(AUTOTEST)
|
||||
option(NON_HERMETIC_TESTS "Whether to build and run tests that depend on an internet connection" OFF)
|
||||
option(PROXY_TEST "Enable proxy test (needs HTTP/SOCKS5 proxy on port 8080/8081)" OFF)
|
||||
option(PROXY_TEST "Enable proxy test (requires other/proxy/proxy_server.go to be running)" OFF)
|
||||
endif()
|
||||
|
||||
option(BUILD_TOXAV "Whether to build the tox AV library" ON)
|
||||
@ -223,6 +225,8 @@ set(toxcore_SOURCES
|
||||
toxcore/ccompat.h
|
||||
toxcore/crypto_core.c
|
||||
toxcore/crypto_core.h
|
||||
toxcore/crypto_core_pack.c
|
||||
toxcore/crypto_core_pack.h
|
||||
toxcore/DHT.c
|
||||
toxcore/DHT.h
|
||||
toxcore/events/conference_connected.c
|
||||
@ -231,6 +235,7 @@ set(toxcore_SOURCES
|
||||
toxcore/events/conference_peer_list_changed.c
|
||||
toxcore/events/conference_peer_name.c
|
||||
toxcore/events/conference_title.c
|
||||
toxcore/events/dht_get_nodes_response.c
|
||||
toxcore/events/events_alloc.c
|
||||
toxcore/events/events_alloc.h
|
||||
toxcore/events/file_chunk_request.c
|
||||
@ -356,8 +361,11 @@ set(toxcore_PKGCONFIG_REQUIRES ${toxcore_PKGCONFIG_REQUIRES} libsodium)
|
||||
set(toxcore_API_HEADERS
|
||||
${toxcore_SOURCE_DIR}/toxcore/tox.h^tox
|
||||
${toxcore_SOURCE_DIR}/toxcore/tox_events.h^tox
|
||||
${toxcore_SOURCE_DIR}/toxcore/tox_dispatch.h^tox
|
||||
${toxcore_SOURCE_DIR}/toxcore/tox_private.h^tox)
|
||||
${toxcore_SOURCE_DIR}/toxcore/tox_dispatch.h^tox)
|
||||
if(EXPERIMENTAL_API)
|
||||
set(toxcore_API_HEADERS ${toxcore_API_HEADERS}
|
||||
${toxcore_SOURCE_DIR}/toxcore/tox_private.h^tox)
|
||||
endif()
|
||||
|
||||
################################################################################
|
||||
#
|
||||
@ -446,7 +454,7 @@ elseif(TARGET Threads::Threads)
|
||||
set(toxcore_LINK_LIBRARIES ${toxcore_LINK_LIBRARIES} Threads::Threads)
|
||||
endif()
|
||||
if(WIN32)
|
||||
set(toxcore_LINK_LIBRARIES ${toxcore_LINK_LIBRARIES} iphlpapi wsock32 ws2_32)
|
||||
set(toxcore_LINK_LIBRARIES ${toxcore_LINK_LIBRARIES} iphlpapi ws2_32)
|
||||
endif()
|
||||
|
||||
################################################################################
|
||||
@ -526,7 +534,7 @@ endfunction()
|
||||
|
||||
# The actual unit tests follow.
|
||||
#
|
||||
if(GTEST_FOUND)
|
||||
if(TARGET GTest::gtest AND TARGET GTest::gmock)
|
||||
unit_test(toxav ring_buffer)
|
||||
unit_test(toxav rtp)
|
||||
unit_test(toxcore DHT)
|
||||
|
351
external/toxcore/c-toxcore/INSTALL.md
vendored
351
external/toxcore/c-toxcore/INSTALL.md
vendored
@ -1,6 +1,8 @@
|
||||
# Installation instructions
|
||||
|
||||
These instructions will guide you through the process of building and installing the toxcore library and its components, as well as getting already pre-built binaries.
|
||||
These instructions will guide you through the process of building and installing
|
||||
the toxcore library and its components, as well as getting already pre-built
|
||||
binaries.
|
||||
|
||||
## Table of contents
|
||||
|
||||
@ -30,37 +32,44 @@ These instructions will guide you through the process of building and installing
|
||||
|
||||
#### Main
|
||||
|
||||
This repository, although called `toxcore`, in fact contains several libraries besides `toxcore` which complement it, as well as several executables. However, note that although these are separate libraries, at the moment, when building the libraries, they are all merged into a single `toxcore` library. Here is the full list of the main components that can be built using the CMake, their dependencies and descriptions.
|
||||
This repository, although called `toxcore`, in fact contains several libraries
|
||||
besides `toxcore` which complement it, as well as several executables. However,
|
||||
note that although these are separate libraries, at the moment, when building
|
||||
the libraries, they are all merged into a single `toxcore` library. Here is the
|
||||
full list of the main components that can be built using the CMake, their
|
||||
dependencies and descriptions.
|
||||
|
||||
| Name | Type | Dependencies | Platform | Description |
|
||||
|------------------|------------|------------------------------------|----------------|----------------------------------------------------------------------------|
|
||||
| `toxcore` | Library | libsodium, libm, libpthread, librt | Cross-platform | The main Tox library that provides the messenger functionality. |
|
||||
| `toxav` | Library | libtoxcore, libopus, libvpx | Cross-platform | Provides audio/video functionality. |
|
||||
| `toxencryptsave` | Library | libtoxcore, libsodium | Cross-platform | Provides encryption of Tox profiles (savedata), as well as arbitrary data. |
|
||||
| `DHT_bootstrap` | Executable | libtoxcore | Cross-platform | A simple DHT bootstrap node. |
|
||||
| `tox-bootstrapd` | Executable | libtoxcore, libconfig | Unix-like | Highly configurable DHT bootstrap node daemon (systemd, SysVinit, Docker). |
|
||||
| Name | Type | Dependencies | Platform | Description |
|
||||
| ---------------- | ---------- | ---------------------------------- | -------------- | -------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `toxcore` | Library | libsodium, libm, libpthread, librt | Cross-platform | The main Tox library that provides the messenger functionality. |
|
||||
| `toxav` | Library | libtoxcore, libopus, libvpx | Cross-platform | Provides audio/video functionality. |
|
||||
| `toxencryptsave` | Library | libtoxcore, libsodium | Cross-platform | Provides encryption of Tox profiles (savedata), as well as arbitrary data. |
|
||||
| `DHT_bootstrap` | Executable | libtoxcore | Cross-platform | A simple DHT bootstrap node. |
|
||||
| `tox-bootstrapd` | Executable | libtoxcore, libconfig | Unix-like | Highly configurable DHT bootstrap node daemon (systemd, SysVinit, Docker). |
|
||||
| `cmp` | Library | | Cross-platform | C implementation of the MessagePack serialization format. [https://github.com/camgunz/cmp](https://github.com/camgunz/cmp) |
|
||||
|
||||
#### Secondary
|
||||
|
||||
There are some programs that are not built by default which you might find interesting. You need to pass `-DBUILD_FUN_UTILS=ON` to cmake to build them.
|
||||
There are some programs that are not built by default which you might find
|
||||
interesting. You need to pass `-DBUILD_FUN_UTILS=ON` to cmake to build them.
|
||||
|
||||
##### Vanity key generators
|
||||
|
||||
Can be used to generate vanity Tox Ids or DHT bootstrap node public keys.
|
||||
|
||||
| Name | Type | Dependencies | Platform | Description |
|
||||
|---------------------------|------------|-----------------------|----------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `cracker` | Executable | libsodium, OpenMP | Cross-platform | Tries to find a curve25519 key pair, hex representation of the public key of which starts with a specified byte sequence. Multi-threaded. |
|
||||
| `cracker_simple` | Executable | libsodium | Cross-platform | Tries to find a curve25519 key pair, hex representation of the public key of which starts with a specified byte sequence. Single-threaded. |
|
||||
| `strkey` | Executable | libsodium | Cross-platform | Tries to find a curve25519 key pair, hex representation of the public key of which contains a specified byte sequence at a specified or any position at all. Single-threaded. |
|
||||
| Name | Type | Dependencies | Platform | Description |
|
||||
| ---------------- | ---------- | ----------------- | -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `cracker` | Executable | libsodium, OpenMP | Cross-platform | Tries to find a curve25519 key pair, hex representation of the public key of which starts with a specified byte sequence. Multi-threaded. |
|
||||
| `cracker_simple` | Executable | libsodium | Cross-platform | Tries to find a curve25519 key pair, hex representation of the public key of which starts with a specified byte sequence. Single-threaded. |
|
||||
| `strkey` | Executable | libsodium | Cross-platform | Tries to find a curve25519 key pair, hex representation of the public key of which contains a specified byte sequence at a specified or any position at all. Single-threaded. |
|
||||
|
||||
##### Key file generators
|
||||
|
||||
Useful for generating Tox profiles from the output of the vanity key generators, as well as generating random Tox profiles.
|
||||
Useful for generating Tox profiles from the output of the vanity key generators,
|
||||
as well as generating random Tox profiles.
|
||||
|
||||
| Name | Type | Dependencies | Platform | Description |
|
||||
|---------------------------|------------|-----------------------|----------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| ------------------------- | ---------- | --------------------- | -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `make-funny-savefile` | Script | python | Cross-platform | Generates a Tox profile file (savedata file) with the provided key pair. |
|
||||
| `create_bootstrap_keys` | Executable | libsodium | Cross-platform | Generates a keys file for tox-bootstrapd with either the provided or a random key pair. |
|
||||
| `create_minimal_savedata` | Executable | libsodium | Cross-platform | Generates a minimal Tox profile file (savedata file) with either the provided or a random key pair, printing the generated Tox Id and secret & public key information. |
|
||||
@ -69,10 +78,10 @@ Useful for generating Tox profiles from the output of the vanity key generators,
|
||||
|
||||
##### Other
|
||||
|
||||
| Name | Type | Dependencies | Platform | Description |
|
||||
|---------------------------|------------|-----------------------|----------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `bootstrap_node_info` | Script | python3 | Cross-platform | Prints version and Message Of The Day (MOTD) information of the specified DHT bootstrap node, given the node doesn't have those disabled. |
|
||||
| `sign` | Executable | libsodium | Cross-platform | Signs a file with a ed25519 key. |
|
||||
| Name | Type | Dependencies | Platform | Description |
|
||||
| --------------------- | ---------- | ------------ | -------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `bootstrap_node_info` | Script | python3 | Cross-platform | Prints version and Message Of The Day (MOTD) information of the specified DHT bootstrap node, given the node doesn't have those disabled. |
|
||||
| `sign` | Executable | libsodium | Cross-platform | Signs a file with a ed25519 key. |
|
||||
|
||||
## Building
|
||||
|
||||
@ -80,56 +89,78 @@ Useful for generating Tox profiles from the output of the vanity key generators,
|
||||
|
||||
#### Library dependencies
|
||||
|
||||
Library dependencies are listed in the [components](#components) table. The dependencies need to be satisfied for the components to be built. Note that if you don't have a dependency for some component, e.g. you don't have `libopus` installed required for building `toxav` component, building of that component is silently disabled.
|
||||
Library dependencies are listed in the [components](#components) table. The
|
||||
dependencies need to be satisfied for the components to be built. Note that if
|
||||
you don't have a dependency for some component, e.g. you don't have `libopus`
|
||||
installed required for building `toxav` component, building of that component is
|
||||
silently disabled.
|
||||
|
||||
|
||||
Be advised that due to the addition of `cmp` as a submodule, you now also need to initialize the git submodules required by toxcore. This can be done by cloning the repo with the addition of `--recurse-submodules` or by running `git submodule update --init` in the root directory of the repo.
|
||||
Be advised that due to the addition of `cmp` as a submodule, you now also need
|
||||
to initialize the git submodules required by toxcore. This can be done by
|
||||
cloning the repo with the addition of `--recurse-submodules` or by running
|
||||
`git submodule update --init` in the root directory of the repo.
|
||||
|
||||
#### Compiler requirements
|
||||
|
||||
The supported compilers are GCC, Clang and MinGW.
|
||||
|
||||
In theory, any compiler that fully supports C99 and accepts GCC flags should work.
|
||||
In theory, any compiler that fully supports C99 and accepts GCC flags should
|
||||
work.
|
||||
|
||||
There is a partial and experimental support of Microsoft Visual C++ compiler. We welcome any patches that help improve it.
|
||||
There is a partial and experimental support of Microsoft Visual C++ compiler. We
|
||||
welcome any patches that help improve it.
|
||||
|
||||
You should have a C99 compatible compiler in order to build the main components. The secondary components might require the compiler to support GNU extensions.
|
||||
You should have a C99 compatible compiler in order to build the main components.
|
||||
The secondary components might require the compiler to support GNU extensions.
|
||||
|
||||
#### Build system requirements
|
||||
|
||||
To build the main components you need to have CMake of at least 2.8.6 version installed. You also need to have pkg-config installed, the build system uses it to find dependency libraries.
|
||||
To build the main components you need to have CMake of at least 2.8.6 version
|
||||
installed. You also need to have pkg-config installed, the build system uses it
|
||||
to find dependency libraries.
|
||||
|
||||
There is some experimental accommodation for building natively on Windows, i.e. without having to use MSYS/Cygwin and pkg-config, but it uses exact hardcoded paths for finding libraries and supports building only of some of toxcore components, so your mileage might vary.
|
||||
There is some experimental accommodation for building natively on Windows, i.e.
|
||||
without having to use MSYS/Cygwin and pkg-config, but it uses exact hardcoded
|
||||
paths for finding libraries and supports building only of some of toxcore
|
||||
components, so your mileage might vary.
|
||||
|
||||
### CMake options
|
||||
|
||||
There are some options that are available to configure the build.
|
||||
|
||||
| Name | Description | Expected Value | Default Value |
|
||||
|------------------------|-----------------------------------------------------------------------------------------------|---------------------------------------------------------------------------|---------------------------------------------------|
|
||||
| `AUTOTEST` | Enable autotests (mainly for CI). | ON or OFF | OFF |
|
||||
| `BOOTSTRAP_DAEMON` | Enable building of tox-bootstrapd, the DHT bootstrap node daemon. For Unix-like systems only. | ON or OFF | ON |
|
||||
| `BUILD_FUZZ_TESTS` | Build fuzzing harnesses. | ON or OFF | OFF |
|
||||
| `BUILD_MISC_TESTS` | Build additional tests. | ON or OFF | OFF |
|
||||
| `BUILD_FUN_UTILS` | Build additional funny utilities. | ON or OFF | OFF |
|
||||
| `BUILD_TOXAV` | Whether to build the toxav library. | ON or OFF | ON |
|
||||
| `CMAKE_INSTALL_PREFIX` | Path to where everything should be installed. | Directory path. | Platform-dependent. Refer to CMake documentation. |
|
||||
| `CMAKE_BUILD_TYPE` | Specifies the build type on single-configuration generators (e.g. make or ninja). | Debug, Release, RelWithDebInfo, MinSizeRel | Empty string. |
|
||||
| `DHT_BOOTSTRAP` | Enable building of `DHT_bootstrap` | ON or OFF | ON |
|
||||
| `ENABLE_SHARED` | Build shared (dynamic) libraries for all modules. | ON or OFF | ON |
|
||||
| `ENABLE_STATIC` | Build static libraries for all modules. | ON or OFF | ON |
|
||||
| `EXECUTION_TRACE` | Print a function trace during execution (for debugging). | ON or OFF | OFF |
|
||||
| `FULLY_STATIC` | Build fully static executables. | ON or OFF | OFF |
|
||||
| `MIN_LOGGER_LEVEL` | Logging level to use. | TRACE, DEBUG, INFO, WARNING, ERROR or nothing (empty string) for default. | Empty string. |
|
||||
| `MSVC_STATIC_SODIUM` | Whether to link libsodium statically for MSVC. | ON or OFF | OFF |
|
||||
| `MUST_BUILD_TOXAV` | Fail the build if toxav cannot be built. | ON or OFF | OFF |
|
||||
| `NON_HERMETIC_TESTS` | Whether to build and run tests that depend on an internet connection. | ON or OFF | OFF |
|
||||
| `STRICT_ABI` | Enforce strict ABI export in dynamic libraries. | ON or OFF | OFF |
|
||||
| `TEST_TIMEOUT_SECONDS` | Limit runtime of each test to the number of seconds specified. | Positive number or nothing (empty string). | Empty string. |
|
||||
| `USE_IPV6` | Use IPv6 in tests. | ON or OFF | ON |
|
||||
| Name | Description | Expected Value | Default Value |
|
||||
| ----------------------- | --------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------- | ------------------------------------------------- |
|
||||
| `AUTOTEST` | Enable autotests (mainly for CI). | ON or OFF | OFF |
|
||||
| `BOOTSTRAP_DAEMON` | Enable building of tox-bootstrapd, the DHT bootstrap node daemon. For Unix-like systems only. | ON or OFF | ON |
|
||||
| `BUILD_FUN_UTILS` | Build additional just for fun utilities. | ON or OFF | OFF |
|
||||
| `BUILD_FUZZ_TESTS` | Build fuzzing harnesses. | ON or OFF | OFF |
|
||||
| `BUILD_MISC_TESTS` | Build additional tests. | ON or OFF | OFF |
|
||||
| `BUILD_TOXAV` | Whether to build the toxav library. | ON or OFF | ON |
|
||||
| `CMAKE_BUILD_TYPE` | Specifies the build type on single-configuration generators (e.g. make or ninja). | Debug, Release, RelWithDebInfo, MinSizeRel | Empty string. |
|
||||
| `CMAKE_INSTALL_PREFIX` | Path to where everything should be installed. | Directory path. | Platform-dependent. Refer to CMake documentation. |
|
||||
| `DHT_BOOTSTRAP` | Enable building of `DHT_bootstrap`. | ON or OFF | ON |
|
||||
| `ENABLE_SHARED` | Build shared (dynamic) libraries for all modules. | ON or OFF | ON |
|
||||
| `ENABLE_STATIC` | Build static libraries for all modules. | ON or OFF | ON |
|
||||
| `EXPERIMENTAL_API` | Install experimental header file with unstable API. | ON or OFF | OFF |
|
||||
| `FLAT_OUTPUT_STRUCTURE` | Whether to produce output artifacts in {bin,lib}. | ON or OFF | OFF |
|
||||
| `FULLY_STATIC` | Build fully static executables. | ON or OFF | OFF |
|
||||
| `MIN_LOGGER_LEVEL` | Logging level to use. | TRACE, DEBUG, INFO, WARNING, ERROR or nothing (empty string) for default. | Empty string. |
|
||||
| `MSVC_STATIC_SODIUM` | Whether to link libsodium statically for MSVC. | ON or OFF | OFF |
|
||||
| `MUST_BUILD_TOXAV` | Fail the build if toxav cannot be built. | ON or OFF | OFF |
|
||||
| `NON_HERMETIC_TESTS` | Whether to build and run tests that depend on an internet connection. | ON or OFF | OFF |
|
||||
| `PROXY_TEST` | Enable proxy test (requires `other/proxy/proxy_server.go` to be running). | ON or OFF | OFF |
|
||||
| `STRICT_ABI` | Enforce strict ABI export in dynamic libraries. | ON or OFF | OFF |
|
||||
| `TEST_TIMEOUT_SECONDS` | Limit runtime of each test to the number of seconds specified. | Positive number or nothing (empty string). | Empty string. |
|
||||
| `USE_IPV6` | Use IPv6 in tests. | ON or OFF | ON |
|
||||
|
||||
You can get this list of option using the following commands
|
||||
|
||||
```sh
|
||||
cmake -B _build -LAH
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```sh
|
||||
grep "option(" CMakeLists.txt cmake/*
|
||||
grep "set(.* CACHE" CMakeLists.txt cmake/*
|
||||
@ -150,11 +181,12 @@ cmake \
|
||||
```
|
||||
|
||||
### Building tests
|
||||
|
||||
In addition to the integration tests ("autotests") and miscellaneous tests
|
||||
enabled by cmake variables described above, there are unit tests which will be
|
||||
built if the source distribution of gtest (the Google Unit Test framework) is
|
||||
found by cmake in `c-toxcore/third_party`. This can be achieved by running
|
||||
'git clone https://github.com/google/googletest` from that directory.
|
||||
found by cmake in `c-toxcore/third_party`. This can be achieved by running 'git
|
||||
clone https://github.com/google/googletest` from that directory.
|
||||
|
||||
### Build process
|
||||
|
||||
@ -170,19 +202,33 @@ make
|
||||
make install
|
||||
```
|
||||
|
||||
or shorter
|
||||
|
||||
```sh
|
||||
cmake -B _build
|
||||
cmake -B _build --target install
|
||||
```
|
||||
|
||||
#### Windows
|
||||
|
||||
##### Building on Windows host
|
||||
|
||||
###### Microsoft Visual Studio's Developer Command Prompt
|
||||
|
||||
In addition to meeting the [requirements](#requirements), you need a version of Visual Studio (the [community edition](https://www.visualstudio.com/vs/visual-studio-express/) is enough) and a CMake version that's compatible with the Visual Studio version you're using.
|
||||
In addition to meeting the [requirements](#requirements), you need a version of
|
||||
Visual Studio (the
|
||||
[community edition](https://www.visualstudio.com/vs/visual-studio-express/) is
|
||||
enough) and a CMake version that's compatible with the Visual Studio version
|
||||
you're using.
|
||||
|
||||
You must also ensure that the msvc versions of dependencies you're using are placed in the correct folders.
|
||||
You must also ensure that the msvc versions of dependencies you're using are
|
||||
placed in the correct folders.
|
||||
|
||||
For libsodium that is `c-toxcore/third_party/libsodium`, and for pthreads-w32, it's `c-toxcore/third_party/pthreads-win32`
|
||||
For libsodium that is `c-toxcore/third_party/libsodium`, and for pthreads-w32,
|
||||
it's `c-toxcore/third_party/pthreads-win32`
|
||||
|
||||
Once all of this is done, from the **Developer Command Prompt for VS**, simply run
|
||||
Once all of this is done, from the **Developer Command Prompt for VS**, simply
|
||||
run
|
||||
|
||||
```
|
||||
mkdir _build
|
||||
@ -193,22 +239,23 @@ msbuild ALL_BUILD.vcxproj
|
||||
|
||||
###### MSYS/Cygwin
|
||||
|
||||
Download Cygwin ([32-bit](https://cygwin.com/setup-x86.exe)/[64-bit](https://cygwin.com/setup-x86_64.exe))
|
||||
Download Cygwin
|
||||
([32-bit](https://cygwin.com/setup-x86.exe)/[64-bit](https://cygwin.com/setup-x86_64.exe))
|
||||
|
||||
Search and select exactly these packages in Devel category:
|
||||
|
||||
- mingw64-i686-gcc-core (32-bit) / mingw64-x86_64-gcc-core (64-bit)
|
||||
- mingw64-i686-gcc-g++ (32-bit) / mingw64-x86_64-gcc-g++ (64-bit)
|
||||
- make
|
||||
- cmake
|
||||
- libtool
|
||||
- autoconf
|
||||
- automake
|
||||
- tree
|
||||
- curl
|
||||
- perl
|
||||
- yasm
|
||||
- pkg-config
|
||||
- mingw64-i686-gcc-core (32-bit) / mingw64-x86_64-gcc-core (64-bit)
|
||||
- mingw64-i686-gcc-g++ (32-bit) / mingw64-x86_64-gcc-g++ (64-bit)
|
||||
- make
|
||||
- cmake
|
||||
- libtool
|
||||
- autoconf
|
||||
- automake
|
||||
- tree
|
||||
- curl
|
||||
- perl
|
||||
- yasm
|
||||
- pkg-config
|
||||
|
||||
To handle Windows EOL correctly run the following in the Cygwin Terminal:
|
||||
|
||||
@ -221,18 +268,24 @@ set -o igncr
|
||||
|
||||
Download toxcore source code and extract it to a folder.
|
||||
|
||||
Open Cygwin Terminal in the toxcore folder and run `./other/windows_build_script_toxcore.sh` to start the build process.
|
||||
Open Cygwin Terminal in the toxcore folder and run
|
||||
`./other/windows_build_script_toxcore.sh` to start the build process.
|
||||
|
||||
Toxcore build result files will appear in `/root/prefix/` relatively to Cygwin folder (default `C:\cygwin64`).
|
||||
|
||||
Dependency versions can be customized in `./other/windows_build_script_toxcore.sh` and described in the section below.
|
||||
Toxcore build result files will appear in `/root/prefix/` relatively to Cygwin
|
||||
folder (default `C:\cygwin64`).
|
||||
|
||||
Dependency versions can be customized in
|
||||
`./other/windows_build_script_toxcore.sh` and described in the section below.
|
||||
|
||||
##### Cross-compiling from Linux
|
||||
|
||||
These cross-compilation instructions were tested on and written for 64-bit Ubuntu 16.04. You could generalize them for any Linux system, the only requirements are that you have Docker version of >= 1.9.0 and you are running 64-bit system.
|
||||
These cross-compilation instructions were tested on and written for 64-bit
|
||||
Ubuntu 16.04. You could generalize them for any Linux system, the only
|
||||
requirements are that you have Docker version of >= 1.9.0 and you are running
|
||||
64-bit system.
|
||||
|
||||
The cross-compilation is fully automated by a parameterized [Dockerfile](/other/docker/windows/Dockerfile).
|
||||
The cross-compilation is fully automated by a parameterized
|
||||
[Dockerfile](/other/docker/windows/Dockerfile).
|
||||
|
||||
Install Docker
|
||||
|
||||
@ -243,17 +296,18 @@ apt-get install docker.io
|
||||
|
||||
Get the toxcore source code and navigate to `other/docker/windows`.
|
||||
|
||||
Build the container image based on the Dockerfile. The following options are available to customize the building of the container image.
|
||||
Build the container image based on the Dockerfile. The following options are
|
||||
available to customize the building of the container image.
|
||||
|
||||
| Name | Description | Expected Value | Default Value |
|
||||
|-----------------------|----------------------------------------------------------------|-------------------------------------|---------------|
|
||||
| `SUPPORT_ARCH_i686` | Support building 32-bit toxcore. | "true" or "false" (case sensitive). | true |
|
||||
| `SUPPORT_ARCH_x86_64` | Support building 64-bit toxcore. | "true" or "false" (case sensitive). | true |
|
||||
| `SUPPORT_TEST` | Support running toxcore automated tests. | "true" or "false" (case sensitive). | false |
|
||||
| `CROSS_COMPILE` | Cross-compiling. True for Docker, false for Cygwin. | "true" or "false" (case sensitive). | true |
|
||||
| `VERSION_OPUS` | Version of libopus to build toxcore with. | Numeric version number. | 1.3.1 |
|
||||
| `VERSION_SODIUM` | Version of libsodium to build toxcore with. | Numeric version number. | 1.0.18 |
|
||||
| `VERSION_VPX` | Version of libvpx to build toxcore with. | Numeric version number. | 1.11.0 |
|
||||
| Name | Description | Expected Value | Default Value |
|
||||
| -------------------------- | ----------------------------------------------------- | ----------------------------------- | ------------- |
|
||||
| `SUPPORT_ARCH_i686` | Support building 32-bit toxcore. | "true" or "false" (case sensitive). | true |
|
||||
| `SUPPORT_ARCH_x86_64` | Support building 64-bit toxcore. | "true" or "false" (case sensitive). | true |
|
||||
| `SUPPORT_TEST` | Support running toxcore automated tests. | "true" or "false" (case sensitive). | false |
|
||||
| `VERSION_OPUS` | Version of libopus to build toxcore with. | Numeric version number. | 1.4 |
|
||||
| `VERSION_SODIUM` | Version of libsodium to build toxcore with. | Numeric version number. | 1.0.19 |
|
||||
| `VERSION_VPX` | Version of libvpx to build toxcore with. | Numeric version number. | 1.14.0 |
|
||||
| `ENABLE_HASH_VERIFICATION` | Verify the hashes of the default dependency versions. | "true" or "false" (case sensitive). | true |
|
||||
|
||||
Example of building a container image with options
|
||||
|
||||
@ -265,16 +319,16 @@ docker build \
|
||||
.
|
||||
```
|
||||
|
||||
Run the container to build toxcore. The following options are available to customize the running of the container image.
|
||||
Run the container to build toxcore. The following options are available to
|
||||
customize the running of the container image.
|
||||
|
||||
| Name | Description | Expected Value | Default Value |
|
||||
|----------------------|--------------------------------------------------------------------------------------------|-------------------------------------|--------------------------------------------------------------------|
|
||||
| `ALLOW_TEST_FAILURE` | Don't stop if a test suite fails. | "true" or "false" (case sensitive). | `false` |
|
||||
| `ENABLE_ARCH_i686` | Build 32-bit toxcore. The image should have been built with `SUPPORT_ARCH_i686` enabled. | "true" or "false" (case sensitive). | `true` |
|
||||
| `ENABLE_ARCH_x86_64` | Build 64-bit toxcore. The image should have been built with `SUPPORT_ARCH_x86_64` enabled. | "true" or "false" (case sensitive). | `true` |
|
||||
| `ENABLE_TEST` | Run the test suite. The image should have been built with `SUPPORT_TEST` enabled. | "true" or "false" (case sensitive). | `false` |
|
||||
| `EXTRA_CMAKE_FLAGS` | Extra arguments to pass to the CMake command when building toxcore. | CMake options. | `-DTEST_TIMEOUT_SECONDS=90` |
|
||||
| `CROSS_COMPILE` | Cross-compiling. True for Docker, false for Cygwin. | "true" or "false" (case sensitive). | `true` |
|
||||
| Name | Description | Expected Value | Default Value |
|
||||
| -------------------- | ------------------------------------------------------------------------------------------ | ----------------------------------- | ------------------------------------------ |
|
||||
| `ALLOW_TEST_FAILURE` | Don't stop if a test suite fails. | "true" or "false" (case sensitive). | `false` |
|
||||
| `ENABLE_ARCH_i686` | Build 32-bit toxcore. The image should have been built with `SUPPORT_ARCH_i686` enabled. | "true" or "false" (case sensitive). | `true` |
|
||||
| `ENABLE_ARCH_x86_64` | Build 64-bit toxcore. The image should have been built with `SUPPORT_ARCH_x86_64` enabled. | "true" or "false" (case sensitive). | `true` |
|
||||
| `ENABLE_TEST` | Run the test suite. The image should have been built with `SUPPORT_TEST` enabled. | "true" or "false" (case sensitive). | `false` |
|
||||
| `EXTRA_CMAKE_FLAGS` | Extra arguments to pass to the CMake command when building toxcore. | CMake options. | `-DTEST_TIMEOUT_SECONDS=90 -DUSE_IPV6=OFF` |
|
||||
|
||||
Example of running the container with options
|
||||
|
||||
@ -284,14 +338,117 @@ docker run \
|
||||
-e ALLOW_TEST_FAILURE=true \
|
||||
-v /path/to/toxcore/sourcecode:/toxcore \
|
||||
-v /path/to/where/output/build/result:/prefix \
|
||||
-t \
|
||||
--rm \
|
||||
toxcore
|
||||
```
|
||||
|
||||
After the build succeeds, you should see the built toxcore libraries in `/path/to/where/output/build/result`.
|
||||
After the build succeeds, you should see the built toxcore libraries in
|
||||
`/path/to/where/output/build/result`.
|
||||
|
||||
The file structure should look similar to the following
|
||||
|
||||
```
|
||||
result
|
||||
├── [4.0K] i686
|
||||
│ ├── [ 36K] bin
|
||||
│ │ ├── [636K] DHT_bootstrap.exe
|
||||
│ │ ├── [572K] cracker.exe
|
||||
│ │ ├── [359K] cracker_simple.exe
|
||||
│ │ ├── [378K] create_bootstrap_keys.exe
|
||||
│ │ ├── [378K] create_minimal_savedata.exe
|
||||
│ │ ├── [958K] create_savedata.exe
|
||||
│ │ ├── [ 18K] libtoxcore.def
|
||||
│ │ ├── [2.6M] libtoxcore.dll
|
||||
│ │ ├── [ 65K] libtoxcore.exp
|
||||
│ │ ├── [428K] libtoxcore.lib
|
||||
│ │ ├── [989K] save-generator.exe
|
||||
│ │ ├── [381K] sign.exe
|
||||
│ │ └── [408K] strkey.exe
|
||||
│ ├── [4.0K] include
|
||||
│ │ └── [4.0K] tox
|
||||
│ │ ├── [177K] tox.h
|
||||
│ │ ├── [ 10K] tox_dispatch.h
|
||||
│ │ ├── [ 26K] tox_events.h
|
||||
│ │ ├── [6.4K] tox_private.h
|
||||
│ │ ├── [ 26K] toxav.h
|
||||
│ │ └── [ 12K] toxencryptsave.h
|
||||
│ └── [4.0K] lib
|
||||
│ ├── [577K] libopus.a
|
||||
│ ├── [660K] libsodium.a
|
||||
│ ├── [ 10K] libssp.a
|
||||
│ ├── [1016K] libtoxcore.a
|
||||
│ ├── [456K] libtoxcore.dll.a
|
||||
│ ├── [2.7M] libvpx.a
|
||||
│ ├── [ 72K] libwinpthread.a
|
||||
│ └── [4.0K] pkgconfig
|
||||
│ ├── [ 250] libsodium.pc
|
||||
│ ├── [ 357] opus.pc
|
||||
│ ├── [ 247] toxcore.pc
|
||||
│ └── [ 309] vpx.pc
|
||||
└── [4.0K] x86_64
|
||||
├── [ 36K] bin
|
||||
│ ├── [504K] DHT_bootstrap.exe
|
||||
│ ├── [474K] cracker.exe
|
||||
│ ├── [277K] cracker_simple.exe
|
||||
│ ├── [287K] create_bootstrap_keys.exe
|
||||
│ ├── [288K] create_minimal_savedata.exe
|
||||
│ ├── [769K] create_savedata.exe
|
||||
│ ├── [ 18K] libtoxcore.def
|
||||
│ ├── [2.4M] libtoxcore.dll
|
||||
│ ├── [ 64K] libtoxcore.exp
|
||||
│ ├── [420K] libtoxcore.lib
|
||||
│ ├── [800K] save-generator.exe
|
||||
│ ├── [289K] sign.exe
|
||||
│ └── [317K] strkey.exe
|
||||
├── [4.0K] include
|
||||
│ └── [4.0K] tox
|
||||
│ ├── [177K] tox.h
|
||||
│ ├── [ 10K] tox_dispatch.h
|
||||
│ ├── [ 26K] tox_events.h
|
||||
│ ├── [6.4K] tox_private.h
|
||||
│ ├── [ 26K] toxav.h
|
||||
│ └── [ 12K] toxencryptsave.h
|
||||
└── [4.0K] lib
|
||||
├── [697K] libopus.a
|
||||
├── [575K] libsodium.a
|
||||
├── [ 11K] libssp.a
|
||||
├── [905K] libtoxcore.a
|
||||
├── [449K] libtoxcore.dll.a
|
||||
├── [2.9M] libvpx.a
|
||||
├── [ 68K] libwinpthread.a
|
||||
└── [4.0K] pkgconfig
|
||||
├── [ 252] libsodium.pc
|
||||
├── [ 359] opus.pc
|
||||
├── [ 249] toxcore.pc
|
||||
└── [ 311] vpx.pc
|
||||
|
||||
12 directories, 60 files
|
||||
```
|
||||
|
||||
- `libtoxcore.dll` is the shared library. It is fully self-contained, with no
|
||||
additional dependencies aside from the Windows OS dlls, and can be used in
|
||||
MSVC, MinGW, Clang, etc. projects. Despite its name, it provides toxcore,
|
||||
toxav, toxencryptsave -- all of Tox.
|
||||
- `libtoxcore.a` is the static library. In order to use it, it needs to be
|
||||
linked against the other provided .a libraries (but not the .dll.a!) and
|
||||
additionally -liphlpapi and -lws2_32 Windows dlls. It similarly provides all
|
||||
of Tox APIs.
|
||||
- `libtoxcore.dll.a` is the MinGW import library for `libtoxcore.dll`.
|
||||
- `libtoxcore.lib` is the MSVC import library for `libtoxcore.dll`.
|
||||
- `libtoxcore.exp` and `libtoxcore.def` are the exported by `libtoxcore`
|
||||
symbols.
|
||||
- `*.exe` are statically compiled executables -- `DHT_bootstrap` and
|
||||
[the fun utils](#secondary).
|
||||
|
||||
## Pre-built binaries
|
||||
|
||||
### Linux
|
||||
|
||||
Toxcore is packaged by at least by the following distributions: ALT Linux, [Arch Linux](https://www.archlinux.org/packages/?q=toxcore), [Fedora](https://apps.fedoraproject.org/packages/toxcore), Mageia, openSUSE, PCLinuxOS, ROSA and Slackware, [according to the information from pkgs.org](https://pkgs.org/download/toxcore). Note that this list might be incomplete and some other distributions might package it too.
|
||||
Toxcore is packaged by at least by the following distributions: ALT Linux,
|
||||
[Arch Linux](https://www.archlinux.org/packages/?q=toxcore),
|
||||
[Fedora](https://apps.fedoraproject.org/packages/toxcore), Mageia, openSUSE,
|
||||
PCLinuxOS, ROSA and Slackware,
|
||||
[according to the information from pkgs.org](https://pkgs.org/download/toxcore).
|
||||
Note that this list might be incomplete and some other distributions might
|
||||
package it too.
|
||||
|
71
external/toxcore/c-toxcore/README.md
vendored
71
external/toxcore/c-toxcore/README.md
vendored
@ -1,8 +1,14 @@
|
||||
# 
|
||||
|
||||
**Current Coverage:** [](https://codecov.io/gh/TokTok/c-toxcore)
|
||||
**Current Coverage:**
|
||||
[](https://codecov.io/gh/TokTok/c-toxcore)
|
||||
|
||||
[**Website**](https://tox.chat) **|** [**Wiki**](https://wiki.tox.chat/) **|** [**Blog**](https://blog.tox.chat/) **|** [**FAQ**](https://wiki.tox.chat/doku.php?id=users:faq) **|** [**Binaries/Downloads**](https://tox.chat/download.html) **|** [**Clients**](https://wiki.tox.chat/doku.php?id=clients) **|** [**Compiling**](/INSTALL.md)
|
||||
[**Website**](https://tox.chat) **|** [**Wiki**](https://wiki.tox.chat/) **|**
|
||||
[**Blog**](https://blog.tox.chat/) **|**
|
||||
[**FAQ**](https://wiki.tox.chat/doku.php?id=users:faq) **|**
|
||||
[**Binaries/Downloads**](https://tox.chat/download.html) **|**
|
||||
[**Clients**](https://wiki.tox.chat/doku.php?id=clients) **|**
|
||||
[**Compiling**](/INSTALL.md)
|
||||
|
||||
## What is Tox
|
||||
|
||||
@ -16,29 +22,33 @@ and privacy easy to obtain for regular users. It uses
|
||||
### 
|
||||
|
||||
This is an **experimental** cryptographic network library. It has not been
|
||||
formally audited by an independent third party that specializes in
|
||||
cryptography or cryptanalysis. **Use this library at your own risk.**
|
||||
formally audited by an independent third party that specializes in cryptography
|
||||
or cryptanalysis. **Use this library at your own risk.**
|
||||
|
||||
The underlying crypto library [libsodium](https://doc.libsodium.org/) provides
|
||||
reliable encryption, but the security model has not yet been fully specified.
|
||||
See [issue 210](https://github.com/TokTok/c-toxcore/issues/210) for a
|
||||
discussion on developing a threat model. See other issues for known weaknesses
|
||||
(e.g. [issue 426](https://github.com/TokTok/c-toxcore/issues/426) describes
|
||||
what can happen if your secret key is stolen).
|
||||
See [issue 210](https://github.com/TokTok/c-toxcore/issues/210) for a discussion
|
||||
on developing a threat model. See other issues for known weaknesses (e.g.
|
||||
[issue 426](https://github.com/TokTok/c-toxcore/issues/426) describes what can
|
||||
happen if your secret key is stolen).
|
||||
|
||||
## Toxcore Development Roadmap
|
||||
|
||||
The roadmap and changelog are generated from GitHub issues. You may view them
|
||||
on the website, where they are updated at least once every 24 hours:
|
||||
The roadmap and changelog are generated from GitHub issues. You may view them on
|
||||
the website, where they are updated at least once every 24 hours:
|
||||
|
||||
- Changelog: https://toktok.ltd/changelog/c-toxcore
|
||||
- Roadmap: https://toktok.ltd/roadmap/c-toxcore
|
||||
- Changelog: https://toktok.ltd/changelog/c-toxcore
|
||||
- Roadmap: https://toktok.ltd/roadmap/c-toxcore
|
||||
|
||||
## Installing toxcore
|
||||
|
||||
Detailed installation instructions can be found in [INSTALL.md](INSTALL.md).
|
||||
|
||||
Be advised that due to the addition of `cmp` as a submodule, you now also need to initialize the git submodules required by toxcore. This can be done by cloning the repo with the following command: `git clone --recurse-submodules https://github.com/Toktok/c-toxcore` or by running `git submodule update --init` in the root directory of the repo.
|
||||
Be advised that due to the addition of `cmp` as a submodule, you now also need
|
||||
to initialize the git submodules required by toxcore. This can be done by
|
||||
cloning the repo with the following command:
|
||||
`git clone --recurse-submodules https://github.com/Toktok/c-toxcore` or by
|
||||
running `git submodule update --init` in the root directory of the repo.
|
||||
|
||||
In a nutshell, if you have [libsodium](https://github.com/jedisct1/libsodium)
|
||||
installed, run:
|
||||
@ -74,17 +84,17 @@ if (err_new != TOX_ERR_NEW_OK) {
|
||||
}
|
||||
```
|
||||
|
||||
Here, we simply exit the program, but in a real client you will probably want
|
||||
to do some error handling and proper error reporting to the user. The `NULL`
|
||||
Here, we simply exit the program, but in a real client you will probably want to
|
||||
do some error handling and proper error reporting to the user. The `NULL`
|
||||
argument given to the first parameter of `tox_new` is the `Tox_Options`. It
|
||||
contains various write-once network settings and allows you to load a
|
||||
previously serialised instance. See [toxcore/tox.h](tox.h) for details.
|
||||
contains various write-once network settings and allows you to load a previously
|
||||
serialised instance. See [toxcore/tox.h](tox.h) for details.
|
||||
|
||||
### Setting up callbacks
|
||||
|
||||
Toxcore works with callbacks that you can register to listen for certain
|
||||
events. Examples of such events are "friend request received" or "friend sent
|
||||
a message". Search the API for `tox_callback_*` to find all of them.
|
||||
Toxcore works with callbacks that you can register to listen for certain events.
|
||||
Examples of such events are "friend request received" or "friend sent a
|
||||
message". Search the API for `tox_callback_*` to find all of them.
|
||||
|
||||
Here, we will set up callbacks for receiving friend requests and receiving
|
||||
messages. We will always accept any friend request (because we're a bot), and
|
||||
@ -172,3 +182,24 @@ the API documentation in [toxcore/tox.h](toxcore/tox.h) for more information.
|
||||
|
||||
- [Another echo bot](https://wiki.tox.chat/developers/client_examples/echo_bot)
|
||||
- [minitox](https://github.com/hqwrong/minitox) (A minimal tox client)
|
||||
|
||||
## SAST Tools
|
||||
|
||||
This project uses various tools supporting Static Application Security Testing:
|
||||
|
||||
- [clang-tidy](https://clang.llvm.org/extra/clang-tidy/): A clang-based C++
|
||||
"linter" tool.
|
||||
- [Coverity](https://scan.coverity.com/): A cloud-based static analyzer service
|
||||
for Java, C/C++, C#, JavaScript, Ruby, or Python that is free for open source
|
||||
projects.
|
||||
- [cppcheck](https://cppcheck.sourceforge.io/): A static analyzer for C/C++
|
||||
code.
|
||||
- [cpplint](https://github.com/cpplint/cpplint): Static code checker for C++
|
||||
- [goblint](https://goblint.in.tum.de/): A static analyzer for multi-threaded C
|
||||
programs, specializing in finding concurrency bugs.
|
||||
- [infer](https://github.com/facebook/infer): A static analyzer for Java, C,
|
||||
C++, and Objective-C.
|
||||
- [PVS-Studio](https://pvs-studio.com/en/pvs-studio/?utm_source=website&utm_medium=github&utm_campaign=open_source):
|
||||
A static analyzer for C, C++, C#, and Java code.
|
||||
- [tokstyle](https://github.com/TokTok/hs-tokstyle): A style checker for TokTok
|
||||
C projects.
|
||||
|
@ -17,6 +17,8 @@ cc_library(
|
||||
"//c-toxcore/toxcore:Messenger",
|
||||
"//c-toxcore/toxcore:mono_time",
|
||||
"//c-toxcore/toxcore:tox",
|
||||
"//c-toxcore/toxcore:tox_dispatch",
|
||||
"//c-toxcore/toxcore:tox_events",
|
||||
],
|
||||
)
|
||||
|
||||
|
@ -240,6 +240,7 @@ endif
|
||||
|
||||
|
||||
EXTRA_DIST += \
|
||||
$(top_srcdir)/auto_tests/data/save.tox \
|
||||
$(top_srcdir)/auto_tests/data/save.tox.big \
|
||||
$(top_srcdir)/auto_tests/data/save.tox.little \
|
||||
$(top_srcdir)/auto_tests/check_compat.h \
|
||||
$(top_srcdir)/auto_tests/auto_test_support.h
|
||||
|
52
external/toxcore/c-toxcore/auto_tests/TCP_test.c
vendored
52
external/toxcore/c-toxcore/auto_tests/TCP_test.c
vendored
@ -45,11 +45,11 @@ static uint16_t ports[NUM_PORTS] = {13215, 33445, 25643};
|
||||
|
||||
static void test_basic(void)
|
||||
{
|
||||
const Random *rng = system_random();
|
||||
const Random *rng = os_random();
|
||||
ck_assert(rng != nullptr);
|
||||
const Network *ns = system_network();
|
||||
const Network *ns = os_network();
|
||||
ck_assert(ns != nullptr);
|
||||
const Memory *mem = system_memory();
|
||||
const Memory *mem = os_memory();
|
||||
ck_assert(mem != nullptr);
|
||||
|
||||
Mono_Time *mono_time = mono_time_new(mem, nullptr, nullptr);
|
||||
@ -266,13 +266,14 @@ static void kill_tcp_con(struct sec_TCP_con *con)
|
||||
static int write_packet_tcp_test_connection(const Logger *logger, struct sec_TCP_con *con, const uint8_t *data,
|
||||
uint16_t length)
|
||||
{
|
||||
VLA(uint8_t, packet, sizeof(uint16_t) + length + CRYPTO_MAC_SIZE);
|
||||
const uint16_t packet_size = sizeof(uint16_t) + length + CRYPTO_MAC_SIZE;
|
||||
VLA(uint8_t, packet, packet_size);
|
||||
|
||||
uint16_t c_length = net_htons(length + CRYPTO_MAC_SIZE);
|
||||
memcpy(packet, &c_length, sizeof(uint16_t));
|
||||
int len = encrypt_data_symmetric(con->shared_key, con->sent_nonce, data, length, packet + sizeof(uint16_t));
|
||||
|
||||
if ((unsigned int)len != (SIZEOF_VLA(packet) - sizeof(uint16_t))) {
|
||||
if ((unsigned int)len != (packet_size - sizeof(uint16_t))) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -282,7 +283,7 @@ static int write_packet_tcp_test_connection(const Logger *logger, struct sec_TCP
|
||||
localhost.ip = get_loopback();
|
||||
localhost.port = 0;
|
||||
|
||||
ck_assert_msg(net_send(con->ns, logger, con->sock, packet, SIZEOF_VLA(packet), &localhost) == SIZEOF_VLA(packet),
|
||||
ck_assert_msg(net_send(con->ns, logger, con->sock, packet, packet_size, &localhost) == packet_size,
|
||||
"Failed to send a packet.");
|
||||
return 0;
|
||||
}
|
||||
@ -303,11 +304,11 @@ static int read_packet_sec_tcp(const Logger *logger, struct sec_TCP_con *con, ui
|
||||
|
||||
static void test_some(void)
|
||||
{
|
||||
const Random *rng = system_random();
|
||||
const Random *rng = os_random();
|
||||
ck_assert(rng != nullptr);
|
||||
const Network *ns = system_network();
|
||||
const Network *ns = os_network();
|
||||
ck_assert(ns != nullptr);
|
||||
const Memory *mem = system_memory();
|
||||
const Memory *mem = os_memory();
|
||||
ck_assert(mem != nullptr);
|
||||
|
||||
Mono_Time *mono_time = mono_time_new(mem, nullptr, nullptr);
|
||||
@ -498,11 +499,11 @@ static int oob_data_callback(void *object, const uint8_t *public_key, const uint
|
||||
|
||||
static void test_client(void)
|
||||
{
|
||||
const Random *rng = system_random();
|
||||
const Random *rng = os_random();
|
||||
ck_assert(rng != nullptr);
|
||||
const Network *ns = system_network();
|
||||
const Network *ns = os_network();
|
||||
ck_assert(ns != nullptr);
|
||||
const Memory *mem = system_memory();
|
||||
const Memory *mem = os_memory();
|
||||
ck_assert(mem != nullptr);
|
||||
|
||||
Logger *logger = logger_new();
|
||||
@ -524,8 +525,9 @@ static void test_client(void)
|
||||
ip_port_tcp_s.ip = get_loopback();
|
||||
|
||||
TCP_Client_Connection *conn = new_tcp_connection(logger, mem, mono_time, rng, ns, &ip_port_tcp_s, self_public_key, f_public_key, f_secret_key, nullptr);
|
||||
do_tcp_connection(logger, mono_time, conn, nullptr);
|
||||
// TCP sockets might need a moment before they can be written to.
|
||||
c_sleep(50);
|
||||
do_tcp_connection(logger, mono_time, conn, nullptr);
|
||||
|
||||
// The connection status should be unconfirmed here because we have finished
|
||||
// sending our data and are awaiting a response.
|
||||
@ -559,6 +561,7 @@ static void test_client(void)
|
||||
ip_port_tcp_s.port = net_htons(ports[random_u32(rng) % NUM_PORTS]);
|
||||
TCP_Client_Connection *conn2 = new_tcp_connection(logger, mem, mono_time, rng, ns, &ip_port_tcp_s, self_public_key, f2_public_key,
|
||||
f2_secret_key, nullptr);
|
||||
c_sleep(50);
|
||||
|
||||
// The client should call this function (defined earlier) during the routing process.
|
||||
routing_response_handler(conn, response_callback, (char *)conn + 2);
|
||||
@ -581,7 +584,7 @@ static void test_client(void)
|
||||
do_tcp_connection(logger, mono_time, conn2, nullptr);
|
||||
c_sleep(50);
|
||||
|
||||
uint8_t data[5] = {1, 2, 3, 4, 5};
|
||||
const uint8_t data[5] = {1, 2, 3, 4, 5};
|
||||
memcpy(oob_pubkey, f2_public_key, CRYPTO_PUBLIC_KEY_SIZE);
|
||||
send_oob_packet(logger, conn2, f_public_key, data, 5);
|
||||
send_routing_request(logger, conn, f2_public_key);
|
||||
@ -632,11 +635,11 @@ static void test_client(void)
|
||||
// Test how the client handles servers that don't respond.
|
||||
static void test_client_invalid(void)
|
||||
{
|
||||
const Random *rng = system_random();
|
||||
const Random *rng = os_random();
|
||||
ck_assert(rng != nullptr);
|
||||
const Network *ns = system_network();
|
||||
const Network *ns = os_network();
|
||||
ck_assert(ns != nullptr);
|
||||
const Memory *mem = system_memory();
|
||||
const Memory *mem = os_memory();
|
||||
ck_assert(mem != nullptr);
|
||||
|
||||
Mono_Time *mono_time = mono_time_new(mem, nullptr, nullptr);
|
||||
@ -654,7 +657,7 @@ static void test_client_invalid(void)
|
||||
ip_port_tcp_s.port = net_htons(ports[random_u32(rng) % NUM_PORTS]);
|
||||
ip_port_tcp_s.ip = get_loopback();
|
||||
TCP_Client_Connection *conn = new_tcp_connection(logger, mem, mono_time, rng, ns, &ip_port_tcp_s,
|
||||
self_public_key, f_public_key, f_secret_key, nullptr);
|
||||
self_public_key, f_public_key, f_secret_key, nullptr);
|
||||
|
||||
// Run the client's main loop but not the server.
|
||||
mono_time_update(mono_time);
|
||||
@ -708,14 +711,13 @@ static int tcp_data_callback(void *object, int id, const uint8_t *data, uint16_t
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void test_tcp_connection(void)
|
||||
{
|
||||
const Random *rng = system_random();
|
||||
const Random *rng = os_random();
|
||||
ck_assert(rng != nullptr);
|
||||
const Network *ns = system_network();
|
||||
const Network *ns = os_network();
|
||||
ck_assert(ns != nullptr);
|
||||
const Memory *mem = system_memory();
|
||||
const Memory *mem = os_memory();
|
||||
ck_assert(mem != nullptr);
|
||||
|
||||
Mono_Time *mono_time = mono_time_new(mem, nullptr, nullptr);
|
||||
@ -824,11 +826,11 @@ static int tcp_oobdata_callback(void *object, const uint8_t *public_key, unsigne
|
||||
|
||||
static void test_tcp_connection2(void)
|
||||
{
|
||||
const Random *rng = system_random();
|
||||
const Random *rng = os_random();
|
||||
ck_assert(rng != nullptr);
|
||||
const Network *ns = system_network();
|
||||
const Network *ns = os_network();
|
||||
ck_assert(ns != nullptr);
|
||||
const Memory *mem = system_memory();
|
||||
const Memory *mem = os_memory();
|
||||
ck_assert(mem != nullptr);
|
||||
|
||||
Mono_Time *mono_time = mono_time_new(mem, nullptr, nullptr);
|
||||
|
@ -13,7 +13,7 @@
|
||||
|
||||
static void test_bucketnum(void)
|
||||
{
|
||||
const Random *rng = system_random();
|
||||
const Random *rng = os_random();
|
||||
ck_assert(rng != nullptr);
|
||||
uint8_t key1[CRYPTO_PUBLIC_KEY_SIZE], key2[CRYPTO_PUBLIC_KEY_SIZE];
|
||||
random_bytes(rng, key1, sizeof(key1));
|
||||
@ -50,11 +50,11 @@ static void test_announce_data(void *object, const uint8_t *data, uint16_t lengt
|
||||
|
||||
static void test_store_data(void)
|
||||
{
|
||||
const Random *rng = system_random();
|
||||
const Random *rng = os_random();
|
||||
ck_assert(rng != nullptr);
|
||||
const Network *ns = system_network();
|
||||
const Network *ns = os_network();
|
||||
ck_assert(ns != nullptr);
|
||||
const Memory *mem = system_memory();
|
||||
const Memory *mem = os_memory();
|
||||
ck_assert(mem != nullptr);
|
||||
|
||||
Logger *log = logger_new();
|
||||
@ -120,7 +120,6 @@ static void basic_announce_tests(void)
|
||||
test_store_data();
|
||||
}
|
||||
|
||||
|
||||
int main(void)
|
||||
{
|
||||
setvbuf(stdout, nullptr, _IONBF, 0);
|
||||
|
@ -5,6 +5,8 @@
|
||||
#include "../testing/misc_tools.h"
|
||||
#include "../toxcore/Messenger.h"
|
||||
#include "../toxcore/mono_time.h"
|
||||
#include "../toxcore/tox_dispatch.h"
|
||||
#include "../toxcore/tox_events.h"
|
||||
#include "../toxcore/tox_struct.h"
|
||||
|
||||
#include "auto_test_support.h"
|
||||
@ -23,6 +25,7 @@ Run_Auto_Options default_run_auto_options(void)
|
||||
.graph = GRAPH_COMPLETE,
|
||||
.init_autotox = nullptr,
|
||||
.tcp_port = 33188,
|
||||
.events = true,
|
||||
};
|
||||
}
|
||||
|
||||
@ -131,7 +134,15 @@ void iterate_all_wait(AutoTox *autotoxes, uint32_t tox_count, uint32_t wait)
|
||||
|
||||
for (uint32_t i = 0; i < tox_count; ++i) {
|
||||
if (autotoxes[i].alive) {
|
||||
tox_iterate(autotoxes[i].tox, &autotoxes[i]);
|
||||
if (autotoxes[i].events) {
|
||||
Tox_Err_Events_Iterate err;
|
||||
Tox_Events *events = tox_events_iterate(autotoxes[i].tox, true, &err);
|
||||
ck_assert(err == TOX_ERR_EVENTS_ITERATE_OK);
|
||||
tox_dispatch_invoke(autotoxes[i].dispatch, events, &autotoxes[i]);
|
||||
tox_events_free(events);
|
||||
} else {
|
||||
tox_iterate(autotoxes[i].tox, &autotoxes[i]);
|
||||
}
|
||||
autotoxes[i].clock += wait;
|
||||
}
|
||||
}
|
||||
@ -181,6 +192,7 @@ void kill_autotox(AutoTox *autotox)
|
||||
ck_assert(autotox->alive);
|
||||
fprintf(stderr, "Killing #%u\n", autotox->index);
|
||||
autotox->alive = false;
|
||||
tox_dispatch_free(autotox->dispatch);
|
||||
tox_kill(autotox->tox);
|
||||
}
|
||||
|
||||
@ -202,6 +214,11 @@ void reload(AutoTox *autotox)
|
||||
tox_options_set_savedata_data(options, autotox->save_state, autotox->save_size);
|
||||
autotox->tox = tox_new_log(options, nullptr, &autotox->index);
|
||||
ck_assert(autotox->tox != nullptr);
|
||||
autotox->dispatch = tox_dispatch_new(nullptr);
|
||||
ck_assert(autotox->dispatch != nullptr);
|
||||
if (autotox->events) {
|
||||
tox_events_init(autotox->tox);
|
||||
}
|
||||
tox_options_free(options);
|
||||
|
||||
set_mono_time_callback(autotox);
|
||||
@ -212,6 +229,7 @@ static void initialise_autotox(struct Tox_Options *options, AutoTox *autotox, ui
|
||||
Run_Auto_Options *autotest_opts)
|
||||
{
|
||||
autotox->index = index;
|
||||
autotox->events = autotest_opts->events;
|
||||
|
||||
Tox_Err_New err = TOX_ERR_NEW_OK;
|
||||
|
||||
@ -259,6 +277,12 @@ static void initialise_autotox(struct Tox_Options *options, AutoTox *autotox, ui
|
||||
|
||||
set_mono_time_callback(autotox);
|
||||
|
||||
autotox->dispatch = tox_dispatch_new(nullptr);
|
||||
ck_assert(autotox->dispatch != nullptr);
|
||||
if (autotox->events) {
|
||||
tox_events_init(autotox->tox);
|
||||
}
|
||||
|
||||
autotox->alive = true;
|
||||
autotox->save_state = nullptr;
|
||||
|
||||
@ -311,7 +335,7 @@ static void initialise_friend_graph(Graph_Type graph, uint32_t num_toxes, AutoTo
|
||||
}
|
||||
}
|
||||
|
||||
static void bootstrap_autotoxes(struct Tox_Options *options, uint32_t tox_count, const Run_Auto_Options *autotest_opts,
|
||||
static void bootstrap_autotoxes(const Tox_Options *options, uint32_t tox_count, const Run_Auto_Options *autotest_opts,
|
||||
AutoTox *autotoxes)
|
||||
{
|
||||
const bool udp_enabled = options != nullptr ? tox_options_get_udp_enabled(options) : true;
|
||||
@ -339,7 +363,9 @@ static void bootstrap_autotoxes(struct Tox_Options *options, uint32_t tox_count,
|
||||
}
|
||||
}
|
||||
|
||||
void run_auto_test(struct Tox_Options *options, uint32_t tox_count, void test(AutoTox *autotoxes),
|
||||
typedef void autotox_test_cb(AutoTox *autotoxes);
|
||||
|
||||
void run_auto_test(struct Tox_Options *options, uint32_t tox_count, autotox_test_cb *test,
|
||||
uint32_t state_size, Run_Auto_Options *autotest_opts)
|
||||
{
|
||||
printf("initialising %u toxes\n", tox_count);
|
||||
@ -371,6 +397,7 @@ void run_auto_test(struct Tox_Options *options, uint32_t tox_count, void test(Au
|
||||
test(autotoxes);
|
||||
|
||||
for (uint32_t i = 0; i < tox_count; ++i) {
|
||||
tox_dispatch_free(autotoxes[i].dispatch);
|
||||
tox_kill(autotoxes[i].tox);
|
||||
free(autotoxes[i].state);
|
||||
free(autotoxes[i].save_state);
|
||||
@ -417,7 +444,6 @@ void print_debug_log(Tox *m, Tox_Log_Level level, const char *file, uint32_t lin
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void print_debug_logger(void *context, Logger_Level level, const char *file, int line, const char *func, const char *message, void *userdata)
|
||||
{
|
||||
print_debug_log(nullptr, (Tox_Log_Level) level, file, (uint32_t) line, func, message, userdata);
|
||||
@ -455,4 +481,3 @@ Tox *tox_new_log(struct Tox_Options *options, Tox_Err_New *err, void *log_user_d
|
||||
{
|
||||
return tox_new_log_lan(options, err, log_user_data, false);
|
||||
}
|
||||
|
||||
|
@ -7,9 +7,11 @@
|
||||
#include "../testing/misc_tools.h"
|
||||
#include "../toxcore/Messenger.h"
|
||||
#include "../toxcore/mono_time.h"
|
||||
#include "../toxcore/tox_dispatch.h"
|
||||
|
||||
typedef struct AutoTox {
|
||||
Tox *tox;
|
||||
Tox_Dispatch *dispatch;
|
||||
|
||||
uint32_t index;
|
||||
uint64_t clock;
|
||||
@ -17,6 +19,7 @@ typedef struct AutoTox {
|
||||
size_t save_size;
|
||||
uint8_t *save_state;
|
||||
bool alive;
|
||||
bool events;
|
||||
|
||||
void *state;
|
||||
} AutoTox;
|
||||
@ -42,6 +45,7 @@ typedef struct Run_Auto_Options {
|
||||
Graph_Type graph;
|
||||
void (*init_autotox)(AutoTox *autotox, uint32_t n);
|
||||
uint16_t tcp_port;
|
||||
bool events;
|
||||
} Run_Auto_Options;
|
||||
|
||||
Run_Auto_Options default_run_auto_options(void);
|
||||
@ -57,7 +61,7 @@ void print_debug_log(Tox *m, Tox_Log_Level level, const char *file, uint32_t lin
|
||||
|
||||
// Use this function when setting the log callback on a Logger object
|
||||
void print_debug_logger(void *context, Logger_Level level, const char *file, int line,
|
||||
const char *func, const char *message, void *userdata);
|
||||
const char *func, const char *message, void *userdata);
|
||||
|
||||
Tox *tox_new_log(struct Tox_Options *options, Tox_Err_New *err, void *log_user_data);
|
||||
Tox *tox_new_log_lan(struct Tox_Options *options, Tox_Err_New *err, void *log_user_data, bool lan_discovery);
|
||||
|
@ -23,10 +23,11 @@ typedef struct State {
|
||||
} State;
|
||||
|
||||
static void handle_self_connection_status(
|
||||
Tox *tox, Tox_Connection connection_status, void *user_data)
|
||||
const Tox_Event_Self_Connection_Status *event, void *user_data)
|
||||
{
|
||||
const AutoTox *autotox = (AutoTox *)user_data;
|
||||
|
||||
const Tox_Connection connection_status = tox_event_self_connection_status_get_connection_status(event);
|
||||
if (connection_status != TOX_CONNECTION_NONE) {
|
||||
printf("tox #%u: is now connected\n", autotox->index);
|
||||
} else {
|
||||
@ -35,10 +36,13 @@ static void handle_self_connection_status(
|
||||
}
|
||||
|
||||
static void handle_friend_connection_status(
|
||||
Tox *tox, uint32_t friendnumber, Tox_Connection connection_status, void *user_data)
|
||||
const Tox_Event_Friend_Connection_Status *event, void *user_data)
|
||||
{
|
||||
const AutoTox *autotox = (AutoTox *)user_data;
|
||||
|
||||
const uint32_t friendnumber = tox_event_friend_connection_status_get_friend_number(event);
|
||||
const Tox_Connection connection_status = tox_event_friend_connection_status_get_connection_status(event);
|
||||
|
||||
if (connection_status != TOX_CONNECTION_NONE) {
|
||||
printf("tox #%u: is now connected to friend %u\n", autotox->index, friendnumber);
|
||||
} else {
|
||||
@ -70,28 +74,33 @@ static void audio_callback(void *tox, uint32_t groupnumber, uint32_t peernumber,
|
||||
}
|
||||
|
||||
static void handle_conference_invite(
|
||||
Tox *tox, uint32_t friendnumber, Tox_Conference_Type type,
|
||||
const uint8_t *data, size_t length, void *user_data)
|
||||
const Tox_Event_Conference_Invite *event, void *user_data)
|
||||
{
|
||||
const AutoTox *autotox = (AutoTox *)user_data;
|
||||
|
||||
const uint32_t friend_number = tox_event_conference_invite_get_friend_number(event);
|
||||
const Tox_Conference_Type type = tox_event_conference_invite_get_type(event);
|
||||
const uint8_t *cookie = tox_event_conference_invite_get_cookie(event);
|
||||
const size_t length = tox_event_conference_invite_get_cookie_length(event);
|
||||
|
||||
ck_assert_msg(type == TOX_CONFERENCE_TYPE_AV, "tox #%u: wrong conference type: %d", autotox->index, type);
|
||||
|
||||
ck_assert_msg(toxav_join_av_groupchat(tox, friendnumber, data, length, audio_callback, user_data) == 0,
|
||||
ck_assert_msg(toxav_join_av_groupchat(autotox->tox, friend_number, cookie, length, audio_callback, user_data) == 0,
|
||||
"tox #%u: failed to join group", autotox->index);
|
||||
}
|
||||
|
||||
static void handle_conference_connected(
|
||||
Tox *tox, uint32_t conference_number, void *user_data)
|
||||
const Tox_Event_Conference_Connected *event, void *user_data)
|
||||
{
|
||||
const AutoTox *autotox = (AutoTox *)user_data;
|
||||
State *state = (State *)autotox->state;
|
||||
|
||||
if (state->invited_next || tox_self_get_friend_list_size(tox) <= 1) {
|
||||
if (state->invited_next || tox_self_get_friend_list_size(autotox->tox) <= 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
Tox_Err_Conference_Invite err;
|
||||
tox_conference_invite(tox, 1, 0, &err);
|
||||
tox_conference_invite(autotox->tox, 1, 0, &err);
|
||||
ck_assert_msg(err == TOX_ERR_CONFERENCE_INVITE_OK, "tox #%u failed to invite next friend: err = %d", autotox->index,
|
||||
err);
|
||||
printf("tox #%u: invited next friend\n", autotox->index);
|
||||
@ -99,7 +108,7 @@ static void handle_conference_connected(
|
||||
}
|
||||
|
||||
static bool toxes_are_disconnected_from_group(uint32_t tox_count, AutoTox *autotoxes,
|
||||
bool *disconnected)
|
||||
const bool *disconnected)
|
||||
{
|
||||
uint32_t num_disconnected = 0;
|
||||
|
||||
@ -138,7 +147,10 @@ static void disconnect_toxes(uint32_t tox_count, AutoTox *autotoxes,
|
||||
do {
|
||||
for (uint32_t i = 0; i < tox_count; ++i) {
|
||||
if (!disconnect_now[i]) {
|
||||
tox_iterate(autotoxes[i].tox, &autotoxes[i]);
|
||||
Tox_Err_Events_Iterate err;
|
||||
Tox_Events *events = tox_events_iterate(autotoxes[i].tox, true, &err);
|
||||
tox_dispatch_invoke(autotoxes[i].dispatch, events, &autotoxes[i]);
|
||||
tox_events_free(events);
|
||||
autotoxes[i].clock += 1000;
|
||||
}
|
||||
}
|
||||
@ -165,7 +177,7 @@ static bool all_connected_to_group(uint32_t tox_count, AutoTox *autotoxes)
|
||||
* returns a random index at which a list of booleans is false
|
||||
* (some such index is required to exist)
|
||||
*/
|
||||
static uint32_t random_false_index(const Random *rng, bool *list, const uint32_t length)
|
||||
static uint32_t random_false_index(const Random *rng, const bool *list, const uint32_t length)
|
||||
{
|
||||
uint32_t index;
|
||||
|
||||
@ -185,7 +197,7 @@ static bool all_got_audio(AutoTox *autotoxes, const bool *disabled)
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < NUM_AV_GROUP_TOX; ++i) {
|
||||
State *state = (State *)autotoxes[i].state;
|
||||
const State *state = (const State *)autotoxes[i].state;
|
||||
|
||||
if (disabled[i] ^ (state->received_audio_num
|
||||
!= NUM_AV_GROUP_TOX - num_disabled - 1)) {
|
||||
@ -291,7 +303,7 @@ static void do_audio(AutoTox *autotoxes, uint32_t iterations)
|
||||
|
||||
static void run_conference_tests(AutoTox *autotoxes)
|
||||
{
|
||||
const Random *rng = system_random();
|
||||
const Random *rng = os_random();
|
||||
ck_assert(rng != nullptr);
|
||||
bool disabled[NUM_AV_GROUP_TOX] = {0};
|
||||
|
||||
@ -402,10 +414,10 @@ static void test_groupav(AutoTox *autotoxes)
|
||||
const time_t test_start_time = time(nullptr);
|
||||
|
||||
for (uint32_t i = 0; i < NUM_AV_GROUP_TOX; ++i) {
|
||||
tox_callback_self_connection_status(autotoxes[i].tox, &handle_self_connection_status);
|
||||
tox_callback_friend_connection_status(autotoxes[i].tox, &handle_friend_connection_status);
|
||||
tox_callback_conference_invite(autotoxes[i].tox, &handle_conference_invite);
|
||||
tox_callback_conference_connected(autotoxes[i].tox, &handle_conference_connected);
|
||||
tox_events_callback_self_connection_status(autotoxes[i].dispatch, handle_self_connection_status);
|
||||
tox_events_callback_friend_connection_status(autotoxes[i].dispatch, handle_friend_connection_status);
|
||||
tox_events_callback_conference_invite(autotoxes[i].dispatch, handle_conference_invite);
|
||||
tox_events_callback_conference_connected(autotoxes[i].dispatch, handle_conference_connected);
|
||||
}
|
||||
|
||||
ck_assert_msg(toxav_add_av_groupchat(autotoxes[0].tox, audio_callback, &autotoxes[0]) != UINT32_MAX,
|
||||
@ -414,7 +426,6 @@ static void test_groupav(AutoTox *autotoxes)
|
||||
ck_assert_msg(tox_conference_invite(autotoxes[0].tox, 0, 0, nullptr) != 0, "failed to invite friend");
|
||||
((State *)autotoxes[0].state)->invited_next = true;
|
||||
|
||||
|
||||
printf("waiting for invitations to be made\n");
|
||||
uint32_t invited_count = 0;
|
||||
|
||||
|
@ -12,12 +12,16 @@ typedef struct State {
|
||||
#include "auto_test_support.h"
|
||||
|
||||
static void handle_conference_invite(
|
||||
Tox *tox, uint32_t friend_number, Tox_Conference_Type type,
|
||||
const uint8_t *cookie, size_t length, void *user_data)
|
||||
const Tox_Event_Conference_Invite *event, void *user_data)
|
||||
{
|
||||
const AutoTox *autotox = (AutoTox *)user_data;
|
||||
State *state = (State *)autotox->state;
|
||||
|
||||
const uint32_t friend_number = tox_event_conference_invite_get_friend_number(event);
|
||||
const Tox_Conference_Type type = tox_event_conference_invite_get_type(event);
|
||||
const uint8_t *cookie = tox_event_conference_invite_get_cookie(event);
|
||||
const size_t length = tox_event_conference_invite_get_cookie_length(event);
|
||||
|
||||
fprintf(stderr, "handle_conference_invite(#%u, %u, %d, uint8_t[%u], _)\n",
|
||||
autotox->index, friend_number, type, (unsigned)length);
|
||||
fprintf(stderr, "tox%u joining conference\n", autotox->index);
|
||||
@ -26,7 +30,7 @@ static void handle_conference_invite(
|
||||
|
||||
if (friend_number != -1) {
|
||||
Tox_Err_Conference_Join err;
|
||||
state->conference = tox_conference_join(tox, friend_number, cookie, length, &err);
|
||||
state->conference = tox_conference_join(autotox->tox, friend_number, cookie, length, &err);
|
||||
ck_assert_msg(err == TOX_ERR_CONFERENCE_JOIN_OK,
|
||||
"attempting to join the conference returned with an error: %d", err);
|
||||
fprintf(stderr, "tox%u joined conference %u\n", autotox->index, state->conference);
|
||||
@ -37,8 +41,8 @@ static void handle_conference_invite(
|
||||
static void conference_double_invite_test(AutoTox *autotoxes)
|
||||
{
|
||||
// Conference callbacks.
|
||||
tox_callback_conference_invite(autotoxes[0].tox, handle_conference_invite);
|
||||
tox_callback_conference_invite(autotoxes[1].tox, handle_conference_invite);
|
||||
tox_events_callback_conference_invite(autotoxes[0].dispatch, handle_conference_invite);
|
||||
tox_events_callback_conference_invite(autotoxes[1].dispatch, handle_conference_invite);
|
||||
|
||||
State *state[2];
|
||||
state[0] = (State *)autotoxes[0].state;
|
||||
|
@ -12,15 +12,18 @@ typedef struct State {
|
||||
#include "auto_test_support.h"
|
||||
|
||||
static void handle_conference_invite(
|
||||
Tox *tox, uint32_t friend_number, Tox_Conference_Type type,
|
||||
const uint8_t *cookie, size_t length, void *user_data)
|
||||
const Tox_Event_Conference_Invite *event, void *user_data)
|
||||
{
|
||||
const AutoTox *autotox = (AutoTox *)user_data;
|
||||
State *state = (State *)autotox->state;
|
||||
|
||||
const uint32_t friend_number = tox_event_conference_invite_get_friend_number(event);
|
||||
const uint8_t *cookie = tox_event_conference_invite_get_cookie(event);
|
||||
const size_t length = tox_event_conference_invite_get_cookie_length(event);
|
||||
|
||||
if (friend_number != -1) {
|
||||
Tox_Err_Conference_Join err;
|
||||
state->conference = tox_conference_join(tox, friend_number, cookie, length, &err);
|
||||
state->conference = tox_conference_join(autotox->tox, friend_number, cookie, length, &err);
|
||||
ck_assert_msg(err == TOX_ERR_CONFERENCE_JOIN_OK,
|
||||
"attempting to join the conference returned with an error: %d", err);
|
||||
fprintf(stderr, "#%u accepted invite to conference %u\n", autotox->index, state->conference);
|
||||
@ -28,7 +31,7 @@ static void handle_conference_invite(
|
||||
}
|
||||
|
||||
static void handle_conference_connected(
|
||||
Tox *tox, uint32_t conference_number, void *user_data)
|
||||
const Tox_Event_Conference_Connected *event, void *user_data)
|
||||
{
|
||||
const AutoTox *autotox = (AutoTox *)user_data;
|
||||
State *state = (State *)autotox->state;
|
||||
@ -37,7 +40,7 @@ static void handle_conference_connected(
|
||||
state->connected = true;
|
||||
}
|
||||
|
||||
static void wait_connected(AutoTox *autotoxes, AutoTox *autotox, uint32_t friendnumber)
|
||||
static void wait_connected(AutoTox *autotoxes, const AutoTox *autotox, uint32_t friendnumber)
|
||||
{
|
||||
do {
|
||||
iterate_all_wait(autotoxes, NUM_INVITE_MERGE_TOX, ITERATION_INTERVAL);
|
||||
@ -95,8 +98,8 @@ static void conference_invite_merge_test(AutoTox *autotoxes)
|
||||
// components will cause a split group to merge
|
||||
|
||||
for (int i = 0; i < NUM_INVITE_MERGE_TOX; i++) {
|
||||
tox_callback_conference_invite(autotoxes[i].tox, &handle_conference_invite);
|
||||
tox_callback_conference_connected(autotoxes[i].tox, &handle_conference_connected);
|
||||
tox_events_callback_conference_invite(autotoxes[i].dispatch, handle_conference_invite);
|
||||
tox_events_callback_conference_connected(autotoxes[i].dispatch, handle_conference_connected);
|
||||
}
|
||||
|
||||
State *state2 = (State *)autotoxes[2].state;
|
||||
|
@ -13,34 +13,39 @@ typedef struct State {
|
||||
#include "auto_test_support.h"
|
||||
|
||||
static void handle_conference_invite(
|
||||
Tox *tox, uint32_t friend_number, Tox_Conference_Type type,
|
||||
const uint8_t *cookie, size_t length, void *user_data)
|
||||
const Tox_Event_Conference_Invite *event, void *user_data)
|
||||
{
|
||||
const AutoTox *autotox = (AutoTox *)user_data;
|
||||
State *state = (State *)autotox->state;
|
||||
|
||||
const uint32_t friend_number = tox_event_conference_invite_get_friend_number(event);
|
||||
const Tox_Conference_Type type = tox_event_conference_invite_get_type(event);
|
||||
const uint8_t *cookie = tox_event_conference_invite_get_cookie(event);
|
||||
const size_t length = tox_event_conference_invite_get_cookie_length(event);
|
||||
|
||||
fprintf(stderr, "handle_conference_invite(#%u, %u, %d, uint8_t[%u], _)\n",
|
||||
autotox->index, friend_number, type, (unsigned)length);
|
||||
fprintf(stderr, "tox%u joining conference\n", autotox->index);
|
||||
|
||||
Tox_Err_Conference_Join err;
|
||||
state->conference = tox_conference_join(tox, friend_number, cookie, length, &err);
|
||||
state->conference = tox_conference_join(autotox->tox, friend_number, cookie, length, &err);
|
||||
ck_assert_msg(err == TOX_ERR_CONFERENCE_JOIN_OK,
|
||||
"attempting to join the conference returned with an error: %d", err);
|
||||
fprintf(stderr, "tox%u joined conference %u\n", autotox->index, state->conference);
|
||||
state->joined = true;
|
||||
}
|
||||
|
||||
static void handle_peer_list_changed(Tox *tox, uint32_t conference_number, void *user_data)
|
||||
static void handle_peer_list_changed(const Tox_Event_Conference_Peer_List_Changed *event, void *user_data)
|
||||
{
|
||||
const AutoTox *autotox = (AutoTox *)user_data;
|
||||
State *state = (State *)autotox->state;
|
||||
|
||||
const uint32_t conference_number = tox_event_conference_peer_list_changed_get_conference_number(event);
|
||||
fprintf(stderr, "handle_peer_list_changed(#%u, %u, _)\n",
|
||||
autotox->index, conference_number);
|
||||
|
||||
Tox_Err_Conference_Peer_Query err;
|
||||
uint32_t const count = tox_conference_peer_count(tox, conference_number, &err);
|
||||
uint32_t const count = tox_conference_peer_count(autotox->tox, conference_number, &err);
|
||||
ck_assert_msg(err == TOX_ERR_CONFERENCE_PEER_QUERY_OK,
|
||||
"failed to get conference peer count: err = %d", err);
|
||||
printf("tox%u has %u peers\n", autotox->index, count);
|
||||
@ -75,10 +80,10 @@ static void rebuild_peer_list(Tox *tox)
|
||||
static void conference_peer_nick_test(AutoTox *autotoxes)
|
||||
{
|
||||
// Conference callbacks.
|
||||
tox_callback_conference_invite(autotoxes[0].tox, handle_conference_invite);
|
||||
tox_callback_conference_invite(autotoxes[1].tox, handle_conference_invite);
|
||||
tox_callback_conference_peer_list_changed(autotoxes[0].tox, handle_peer_list_changed);
|
||||
tox_callback_conference_peer_list_changed(autotoxes[1].tox, handle_peer_list_changed);
|
||||
tox_events_callback_conference_invite(autotoxes[0].dispatch, handle_conference_invite);
|
||||
tox_events_callback_conference_invite(autotoxes[1].dispatch, handle_conference_invite);
|
||||
tox_events_callback_conference_peer_list_changed(autotoxes[0].dispatch, handle_peer_list_changed);
|
||||
tox_events_callback_conference_peer_list_changed(autotoxes[1].dispatch, handle_peer_list_changed);
|
||||
|
||||
// Set the names of the toxes.
|
||||
tox_self_set_name(autotoxes[0].tox, (const uint8_t *)"test-tox-0", 10, nullptr);
|
||||
|
@ -3,11 +3,14 @@
|
||||
|
||||
#include "../testing/misc_tools.h"
|
||||
#include "../toxcore/tox.h"
|
||||
#include "../toxcore/tox_dispatch.h"
|
||||
#include "../toxcore/tox_events.h"
|
||||
#include "auto_test_support.h"
|
||||
#include "check_compat.h"
|
||||
|
||||
typedef struct State {
|
||||
uint32_t id;
|
||||
Tox *tox;
|
||||
bool self_online;
|
||||
bool friend_online;
|
||||
bool invited_next;
|
||||
@ -20,46 +23,57 @@ typedef struct State {
|
||||
uint32_t peers;
|
||||
} State;
|
||||
|
||||
static void handle_self_connection_status(Tox *tox, Tox_Connection connection_status, void *user_data)
|
||||
static void handle_self_connection_status(const Tox_Event_Self_Connection_Status *event, void *user_data)
|
||||
{
|
||||
State *state = (State *)user_data;
|
||||
|
||||
const Tox_Connection connection_status = tox_event_self_connection_status_get_connection_status(event);
|
||||
fprintf(stderr, "self_connection_status(#%u, %d, _)\n", state->id, connection_status);
|
||||
state->self_online = connection_status != TOX_CONNECTION_NONE;
|
||||
}
|
||||
|
||||
static void handle_friend_connection_status(Tox *tox, uint32_t friend_number, Tox_Connection connection_status,
|
||||
static void handle_friend_connection_status(const Tox_Event_Friend_Connection_Status *event,
|
||||
void *user_data)
|
||||
{
|
||||
State *state = (State *)user_data;
|
||||
|
||||
const uint32_t friend_number = tox_event_friend_connection_status_get_friend_number(event);
|
||||
const Tox_Connection connection_status = tox_event_friend_connection_status_get_connection_status(event);
|
||||
fprintf(stderr, "handle_friend_connection_status(#%u, %u, %d, _)\n", state->id, friend_number, connection_status);
|
||||
state->friend_online = connection_status != TOX_CONNECTION_NONE;
|
||||
}
|
||||
|
||||
static void handle_conference_invite(Tox *tox, uint32_t friend_number, Tox_Conference_Type type, const uint8_t *cookie,
|
||||
size_t length, void *user_data)
|
||||
static void handle_conference_invite(const Tox_Event_Conference_Invite *event, void *user_data)
|
||||
{
|
||||
State *state = (State *)user_data;
|
||||
|
||||
const uint32_t friend_number = tox_event_conference_invite_get_friend_number(event);
|
||||
const Tox_Conference_Type type = tox_event_conference_invite_get_type(event);
|
||||
const uint8_t *cookie = tox_event_conference_invite_get_cookie(event);
|
||||
const size_t length = tox_event_conference_invite_get_cookie_length(event);
|
||||
fprintf(stderr, "handle_conference_invite(#%u, %u, %d, uint8_t[%u], _)\n",
|
||||
state->id, friend_number, type, (unsigned)length);
|
||||
fprintf(stderr, "tox%u joining conference\n", state->id);
|
||||
|
||||
{
|
||||
Tox_Err_Conference_Join err;
|
||||
state->conference = tox_conference_join(tox, friend_number, cookie, length, &err);
|
||||
state->conference = tox_conference_join(state->tox, friend_number, cookie, length, &err);
|
||||
ck_assert_msg(err == TOX_ERR_CONFERENCE_JOIN_OK, "failed to join a conference: err = %d", err);
|
||||
fprintf(stderr, "tox%u Joined conference %u\n", state->id, state->conference);
|
||||
state->joined = true;
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_conference_message(Tox *tox, uint32_t conference_number, uint32_t peer_number,
|
||||
Tox_Message_Type type, const uint8_t *message, size_t length, void *user_data)
|
||||
static void handle_conference_message(const Tox_Event_Conference_Message *event, void *user_data)
|
||||
{
|
||||
State *state = (State *)user_data;
|
||||
|
||||
const uint32_t conference_number = tox_event_conference_message_get_conference_number(event);
|
||||
const uint32_t peer_number = tox_event_conference_message_get_peer_number(event);
|
||||
const Tox_Message_Type type = tox_event_conference_message_get_type(event);
|
||||
const uint8_t *message = tox_event_conference_message_get_message(event);
|
||||
const size_t length = tox_event_conference_message_get_message_length(event);
|
||||
|
||||
fprintf(stderr, "handle_conference_message(#%u, %u, %u, %d, uint8_t[%u], _)\n",
|
||||
state->id, conference_number, peer_number, type, (unsigned)length);
|
||||
|
||||
@ -67,15 +81,16 @@ static void handle_conference_message(Tox *tox, uint32_t conference_number, uint
|
||||
state->received = true;
|
||||
}
|
||||
|
||||
static void handle_conference_peer_list_changed(Tox *tox, uint32_t conference_number, void *user_data)
|
||||
static void handle_conference_peer_list_changed(const Tox_Event_Conference_Peer_List_Changed *event, void *user_data)
|
||||
{
|
||||
State *state = (State *)user_data;
|
||||
|
||||
const uint32_t conference_number = tox_event_conference_peer_list_changed_get_conference_number(event);
|
||||
fprintf(stderr, "handle_conference_peer_list_changed(#%u, %u, _)\n",
|
||||
state->id, conference_number);
|
||||
|
||||
Tox_Err_Conference_Peer_Query err;
|
||||
uint32_t count = tox_conference_peer_count(tox, conference_number, &err);
|
||||
uint32_t count = tox_conference_peer_count(state->tox, conference_number, &err);
|
||||
|
||||
if (err != TOX_ERR_CONFERENCE_PEER_QUERY_OK) {
|
||||
fprintf(stderr, "ERROR: %d\n", err);
|
||||
@ -86,14 +101,14 @@ static void handle_conference_peer_list_changed(Tox *tox, uint32_t conference_nu
|
||||
state->peers = count;
|
||||
}
|
||||
|
||||
static void handle_conference_connected(Tox *tox, uint32_t conference_number, void *user_data)
|
||||
static void handle_conference_connected(const Tox_Event_Conference_Connected *event, void *user_data)
|
||||
{
|
||||
State *state = (State *)user_data;
|
||||
|
||||
// We're tox2, so now we invite tox3.
|
||||
if (state->id == 2 && !state->invited_next) {
|
||||
Tox_Err_Conference_Invite err;
|
||||
tox_conference_invite(tox, 1, state->conference, &err);
|
||||
tox_conference_invite(state->tox, 1, state->conference, &err);
|
||||
ck_assert_msg(err == TOX_ERR_CONFERENCE_INVITE_OK, "tox2 failed to invite tox3: err = %d", err);
|
||||
|
||||
state->invited_next = true;
|
||||
@ -101,6 +116,27 @@ static void handle_conference_connected(Tox *tox, uint32_t conference_number, vo
|
||||
}
|
||||
}
|
||||
|
||||
static void iterate_one(
|
||||
Tox *tox, State *state, const Tox_Dispatch *dispatch)
|
||||
{
|
||||
Tox_Err_Events_Iterate err;
|
||||
Tox_Events *events = tox_events_iterate(tox, true, &err);
|
||||
ck_assert(err == TOX_ERR_EVENTS_ITERATE_OK);
|
||||
tox_dispatch_invoke(dispatch, events, state);
|
||||
tox_events_free(events);
|
||||
}
|
||||
|
||||
static void iterate3_wait(
|
||||
State *state1, State *state2, State *state3,
|
||||
const Tox_Dispatch *dispatch, int interval)
|
||||
{
|
||||
iterate_one(state1->tox, state1, dispatch);
|
||||
iterate_one(state2->tox, state2, dispatch);
|
||||
iterate_one(state3->tox, state3, dispatch);
|
||||
|
||||
c_sleep(interval);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
setvbuf(stdout, nullptr, _IONBF, 0);
|
||||
@ -110,64 +146,51 @@ int main(void)
|
||||
State state3 = {3};
|
||||
|
||||
// Create toxes.
|
||||
Tox *tox1 = tox_new_log(nullptr, nullptr, &state1.id);
|
||||
Tox *tox2 = tox_new_log(nullptr, nullptr, &state2.id);
|
||||
Tox *tox3 = tox_new_log(nullptr, nullptr, &state3.id);
|
||||
state1.tox = tox_new_log(nullptr, nullptr, &state1.id);
|
||||
state2.tox = tox_new_log(nullptr, nullptr, &state2.id);
|
||||
state3.tox = tox_new_log(nullptr, nullptr, &state3.id);
|
||||
|
||||
tox_events_init(state1.tox);
|
||||
tox_events_init(state2.tox);
|
||||
tox_events_init(state3.tox);
|
||||
|
||||
// tox1 <-> tox2, tox2 <-> tox3
|
||||
uint8_t key[TOX_PUBLIC_KEY_SIZE];
|
||||
tox_self_get_public_key(tox2, key);
|
||||
tox_friend_add_norequest(tox1, key, nullptr); // tox1 -> tox2
|
||||
tox_self_get_public_key(tox1, key);
|
||||
tox_friend_add_norequest(tox2, key, nullptr); // tox2 -> tox1
|
||||
tox_self_get_public_key(tox3, key);
|
||||
tox_friend_add_norequest(tox2, key, nullptr); // tox2 -> tox3
|
||||
tox_self_get_public_key(tox2, key);
|
||||
tox_friend_add_norequest(tox3, key, nullptr); // tox3 -> tox2
|
||||
tox_self_get_public_key(state2.tox, key);
|
||||
tox_friend_add_norequest(state1.tox, key, nullptr); // tox1 -> tox2
|
||||
tox_self_get_public_key(state1.tox, key);
|
||||
tox_friend_add_norequest(state2.tox, key, nullptr); // tox2 -> tox1
|
||||
tox_self_get_public_key(state3.tox, key);
|
||||
tox_friend_add_norequest(state2.tox, key, nullptr); // tox2 -> tox3
|
||||
tox_self_get_public_key(state2.tox, key);
|
||||
tox_friend_add_norequest(state3.tox, key, nullptr); // tox3 -> tox2
|
||||
|
||||
printf("bootstrapping tox2 and tox3 off tox1\n");
|
||||
uint8_t dht_key[TOX_PUBLIC_KEY_SIZE];
|
||||
tox_self_get_dht_id(tox1, dht_key);
|
||||
const uint16_t dht_port = tox_self_get_udp_port(tox1, nullptr);
|
||||
tox_self_get_dht_id(state1.tox, dht_key);
|
||||
const uint16_t dht_port = tox_self_get_udp_port(state1.tox, nullptr);
|
||||
|
||||
tox_bootstrap(tox2, "localhost", dht_port, dht_key, nullptr);
|
||||
tox_bootstrap(tox3, "localhost", dht_port, dht_key, nullptr);
|
||||
tox_bootstrap(state2.tox, "localhost", dht_port, dht_key, nullptr);
|
||||
tox_bootstrap(state3.tox, "localhost", dht_port, dht_key, nullptr);
|
||||
|
||||
Tox_Dispatch *dispatch = tox_dispatch_new(nullptr);
|
||||
ck_assert(dispatch != nullptr);
|
||||
|
||||
// Connection callbacks.
|
||||
tox_callback_self_connection_status(tox1, handle_self_connection_status);
|
||||
tox_callback_self_connection_status(tox2, handle_self_connection_status);
|
||||
tox_callback_self_connection_status(tox3, handle_self_connection_status);
|
||||
|
||||
tox_callback_friend_connection_status(tox1, handle_friend_connection_status);
|
||||
tox_callback_friend_connection_status(tox2, handle_friend_connection_status);
|
||||
tox_callback_friend_connection_status(tox3, handle_friend_connection_status);
|
||||
tox_events_callback_self_connection_status(dispatch, handle_self_connection_status);
|
||||
tox_events_callback_friend_connection_status(dispatch, handle_friend_connection_status);
|
||||
|
||||
// Conference callbacks.
|
||||
tox_callback_conference_invite(tox1, handle_conference_invite);
|
||||
tox_callback_conference_invite(tox2, handle_conference_invite);
|
||||
tox_callback_conference_invite(tox3, handle_conference_invite);
|
||||
|
||||
tox_callback_conference_connected(tox1, handle_conference_connected);
|
||||
tox_callback_conference_connected(tox2, handle_conference_connected);
|
||||
tox_callback_conference_connected(tox3, handle_conference_connected);
|
||||
|
||||
tox_callback_conference_message(tox1, handle_conference_message);
|
||||
tox_callback_conference_message(tox2, handle_conference_message);
|
||||
tox_callback_conference_message(tox3, handle_conference_message);
|
||||
|
||||
tox_callback_conference_peer_list_changed(tox1, handle_conference_peer_list_changed);
|
||||
tox_callback_conference_peer_list_changed(tox2, handle_conference_peer_list_changed);
|
||||
tox_callback_conference_peer_list_changed(tox3, handle_conference_peer_list_changed);
|
||||
tox_events_callback_conference_invite(dispatch, handle_conference_invite);
|
||||
tox_events_callback_conference_connected(dispatch, handle_conference_connected);
|
||||
tox_events_callback_conference_message(dispatch, handle_conference_message);
|
||||
tox_events_callback_conference_peer_list_changed(dispatch, handle_conference_peer_list_changed);
|
||||
|
||||
// Wait for self connection.
|
||||
fprintf(stderr, "Waiting for toxes to come online\n");
|
||||
|
||||
do {
|
||||
tox_iterate(tox1, &state1);
|
||||
tox_iterate(tox2, &state2);
|
||||
tox_iterate(tox3, &state3);
|
||||
|
||||
c_sleep(100);
|
||||
iterate3_wait(&state1, &state2, &state3, dispatch, 100);
|
||||
} while (!state1.self_online || !state2.self_online || !state3.self_online);
|
||||
|
||||
fprintf(stderr, "Toxes are online\n");
|
||||
@ -176,11 +199,7 @@ int main(void)
|
||||
fprintf(stderr, "Waiting for friends to connect\n");
|
||||
|
||||
do {
|
||||
tox_iterate(tox1, &state1);
|
||||
tox_iterate(tox2, &state2);
|
||||
tox_iterate(tox3, &state3);
|
||||
|
||||
c_sleep(100);
|
||||
iterate3_wait(&state1, &state2, &state3, dispatch, 100);
|
||||
} while (!state1.friend_online || !state2.friend_online || !state3.friend_online);
|
||||
|
||||
fprintf(stderr, "Friends are connected\n");
|
||||
@ -188,7 +207,7 @@ int main(void)
|
||||
{
|
||||
// Create new conference, tox1 is the founder.
|
||||
Tox_Err_Conference_New err;
|
||||
state1.conference = tox_conference_new(tox1, &err);
|
||||
state1.conference = tox_conference_new(state1.tox, &err);
|
||||
state1.joined = true;
|
||||
ck_assert_msg(err == TOX_ERR_CONFERENCE_NEW_OK, "failed to create a conference: err = %d", err);
|
||||
fprintf(stderr, "Created conference: id = %u\n", state1.conference);
|
||||
@ -197,7 +216,7 @@ int main(void)
|
||||
{
|
||||
// Invite friend.
|
||||
Tox_Err_Conference_Invite err;
|
||||
tox_conference_invite(tox1, 0, state1.conference, &err);
|
||||
tox_conference_invite(state1.tox, 0, state1.conference, &err);
|
||||
ck_assert_msg(err == TOX_ERR_CONFERENCE_INVITE_OK, "failed to invite a friend: err = %d", err);
|
||||
state1.invited_next = true;
|
||||
fprintf(stderr, "tox1 invited tox2\n");
|
||||
@ -206,11 +225,7 @@ int main(void)
|
||||
fprintf(stderr, "Waiting for invitation to arrive\n");
|
||||
|
||||
do {
|
||||
tox_iterate(tox1, &state1);
|
||||
tox_iterate(tox2, &state2);
|
||||
tox_iterate(tox3, &state3);
|
||||
|
||||
c_sleep(100);
|
||||
iterate3_wait(&state1, &state2, &state3, dispatch, 100);
|
||||
} while (!state1.joined || !state2.joined || !state3.joined);
|
||||
|
||||
fprintf(stderr, "Invitations accepted\n");
|
||||
@ -218,11 +233,7 @@ int main(void)
|
||||
fprintf(stderr, "Waiting for peers to come online\n");
|
||||
|
||||
do {
|
||||
tox_iterate(tox1, &state1);
|
||||
tox_iterate(tox2, &state2);
|
||||
tox_iterate(tox3, &state3);
|
||||
|
||||
c_sleep(100);
|
||||
iterate3_wait(&state1, &state2, &state3, dispatch, 100);
|
||||
} while (state1.peers == 0 || state2.peers == 0 || state3.peers == 0);
|
||||
|
||||
fprintf(stderr, "All peers are online\n");
|
||||
@ -230,7 +241,7 @@ int main(void)
|
||||
{
|
||||
fprintf(stderr, "tox1 sends a message to the group: \"hello!\"\n");
|
||||
Tox_Err_Conference_Send_Message err;
|
||||
tox_conference_send_message(tox1, state1.conference, TOX_MESSAGE_TYPE_NORMAL,
|
||||
tox_conference_send_message(state1.tox, state1.conference, TOX_MESSAGE_TYPE_NORMAL,
|
||||
(const uint8_t *)"hello!", 7, &err);
|
||||
|
||||
if (err != TOX_ERR_CONFERENCE_SEND_MESSAGE_OK) {
|
||||
@ -242,18 +253,16 @@ int main(void)
|
||||
fprintf(stderr, "Waiting for messages to arrive\n");
|
||||
|
||||
do {
|
||||
tox_iterate(tox1, &state1);
|
||||
tox_iterate(tox2, &state2);
|
||||
tox_iterate(tox3, &state3);
|
||||
|
||||
iterate3_wait(&state1, &state2, &state3, dispatch, 100);
|
||||
c_sleep(100);
|
||||
} while (!state2.received || !state3.received);
|
||||
|
||||
fprintf(stderr, "Messages received. Test complete.\n");
|
||||
|
||||
tox_kill(tox3);
|
||||
tox_kill(tox2);
|
||||
tox_kill(tox1);
|
||||
tox_dispatch_free(dispatch);
|
||||
tox_kill(state3.tox);
|
||||
tox_kill(state2.tox);
|
||||
tox_kill(state1.tox);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -56,13 +56,13 @@ static void handle_conference_invite(
|
||||
ck_assert_msg(type == TOX_CONFERENCE_TYPE_TEXT, "tox #%u: wrong conference type: %d", autotox->index, type);
|
||||
|
||||
Tox_Err_Conference_Join err;
|
||||
uint32_t g_num = tox_conference_join(tox, friendnumber, data, length, &err);
|
||||
uint32_t g_num = tox_conference_join(autotox->tox, friendnumber, data, length, &err);
|
||||
|
||||
ck_assert_msg(err == TOX_ERR_CONFERENCE_JOIN_OK, "tox #%u: error joining group: %d", autotox->index, err);
|
||||
ck_assert_msg(g_num == 0, "tox #%u: group number was not 0", autotox->index);
|
||||
|
||||
// Try joining again. We should only be allowed to join once.
|
||||
tox_conference_join(tox, friendnumber, data, length, &err);
|
||||
tox_conference_join(autotox->tox, friendnumber, data, length, &err);
|
||||
ck_assert_msg(err != TOX_ERR_CONFERENCE_JOIN_OK,
|
||||
"tox #%u: joining groupchat twice should be impossible.", autotox->index);
|
||||
}
|
||||
@ -73,12 +73,12 @@ static void handle_conference_connected(
|
||||
const AutoTox *autotox = (AutoTox *)user_data;
|
||||
State *state = (State *)autotox->state;
|
||||
|
||||
if (state->invited_next || tox_self_get_friend_list_size(tox) <= 1) {
|
||||
if (state->invited_next || tox_self_get_friend_list_size(autotox->tox) <= 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
Tox_Err_Conference_Invite err;
|
||||
tox_conference_invite(tox, 1, 0, &err);
|
||||
tox_conference_invite(autotox->tox, 1, 0, &err);
|
||||
ck_assert_msg(err == TOX_ERR_CONFERENCE_INVITE_OK, "tox #%u failed to invite next friend: err = %d", autotox->index,
|
||||
err);
|
||||
printf("tox #%u: invited next friend\n", autotox->index);
|
||||
@ -97,7 +97,7 @@ static void handle_conference_message(
|
||||
}
|
||||
|
||||
static bool toxes_are_disconnected_from_group(uint32_t tox_count, AutoTox *autotoxes,
|
||||
bool *disconnected)
|
||||
const bool *disconnected)
|
||||
{
|
||||
uint32_t num_disconnected = 0;
|
||||
|
||||
@ -174,12 +174,11 @@ static bool names_propagated(uint32_t tox_count, AutoTox *autotoxes)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* returns a random index at which a list of booleans is false
|
||||
* (some such index is required to exist)
|
||||
*/
|
||||
static uint32_t random_false_index(const Random *rng, bool *list, const uint32_t length)
|
||||
static uint32_t random_false_index(const Random *rng, const bool *list, const uint32_t length)
|
||||
{
|
||||
uint32_t index;
|
||||
|
||||
@ -192,7 +191,7 @@ static uint32_t random_false_index(const Random *rng, bool *list, const uint32_t
|
||||
|
||||
static void run_conference_tests(AutoTox *autotoxes)
|
||||
{
|
||||
const Random *rng = system_random();
|
||||
const Random *rng = os_random();
|
||||
ck_assert(rng != nullptr);
|
||||
/* disabling name change propagation check for now, as it occasionally
|
||||
* fails due to disconnections too short to trigger freezing */
|
||||
@ -357,7 +356,6 @@ static void test_many_group(AutoTox *autotoxes)
|
||||
nullptr) != 0,
|
||||
"failed to set group title");
|
||||
|
||||
|
||||
printf("waiting for invitations to be made\n");
|
||||
uint32_t invited_count = 0;
|
||||
|
||||
@ -435,6 +433,7 @@ int main(void)
|
||||
|
||||
Run_Auto_Options options = default_run_auto_options();
|
||||
options.graph = GRAPH_LINEAR;
|
||||
options.events = false;
|
||||
|
||||
run_auto_test(nullptr, NUM_GROUP_TOX, test_many_group, sizeof(State), &options);
|
||||
return 0;
|
||||
|
@ -125,7 +125,7 @@ static void test_fast_known(void)
|
||||
|
||||
static void test_endtoend(void)
|
||||
{
|
||||
const Random *rng = system_random();
|
||||
const Random *rng = os_random();
|
||||
ck_assert(rng != nullptr);
|
||||
|
||||
// Test 100 random messages and keypairs
|
||||
@ -192,7 +192,7 @@ static void test_endtoend(void)
|
||||
|
||||
static void test_large_data(void)
|
||||
{
|
||||
const Random *rng = system_random();
|
||||
const Random *rng = os_random();
|
||||
ck_assert(rng != nullptr);
|
||||
uint8_t k[CRYPTO_SHARED_KEY_SIZE];
|
||||
uint8_t n[CRYPTO_NONCE_SIZE];
|
||||
@ -236,7 +236,7 @@ static void test_large_data(void)
|
||||
|
||||
static void test_large_data_symmetric(void)
|
||||
{
|
||||
const Random *rng = system_random();
|
||||
const Random *rng = os_random();
|
||||
ck_assert(rng != nullptr);
|
||||
uint8_t k[CRYPTO_SYMMETRIC_KEY_SIZE];
|
||||
|
||||
@ -271,10 +271,10 @@ static void test_large_data_symmetric(void)
|
||||
|
||||
static void test_very_large_data(void)
|
||||
{
|
||||
const Random *rng = system_random();
|
||||
const Random *rng = os_random();
|
||||
ck_assert(rng != nullptr);
|
||||
|
||||
uint8_t nonce[CRYPTO_NONCE_SIZE] = {0};
|
||||
const uint8_t nonce[CRYPTO_NONCE_SIZE] = {0};
|
||||
uint8_t pk[CRYPTO_PUBLIC_KEY_SIZE];
|
||||
uint8_t sk[CRYPTO_SECRET_KEY_SIZE];
|
||||
crypto_new_keypair(rng, pk, sk);
|
||||
@ -316,7 +316,7 @@ static void increment_nonce_number_cmp(uint8_t *nonce, uint32_t num)
|
||||
|
||||
static void test_increment_nonce(void)
|
||||
{
|
||||
const Random *rng = system_random();
|
||||
const Random *rng = os_random();
|
||||
ck_assert(rng != nullptr);
|
||||
|
||||
uint8_t n[CRYPTO_NONCE_SIZE];
|
||||
|
Binary file not shown.
BIN
external/toxcore/c-toxcore/auto_tests/data/save.tox.little
vendored
Normal file
BIN
external/toxcore/c-toxcore/auto_tests/data/save.tox.little
vendored
Normal file
Binary file not shown.
@ -72,12 +72,16 @@ static bool all_nodes_crawled(const AutoTox *autotoxes, uint32_t num_toxes, uint
|
||||
return true;
|
||||
}
|
||||
|
||||
static void getnodes_response_cb(Tox *tox, const uint8_t *public_key, const char *ip, uint16_t port, void *user_data)
|
||||
static void getnodes_response_cb(const Tox_Event_Dht_Get_Nodes_Response *event, void *user_data)
|
||||
{
|
||||
ck_assert(user_data != nullptr);
|
||||
|
||||
AutoTox *autotoxes = (AutoTox *)user_data;
|
||||
State *state = (State *)autotoxes->state;
|
||||
AutoTox *autotox = (AutoTox *)user_data;
|
||||
State *state = (State *)autotox->state;
|
||||
|
||||
const uint8_t *public_key = tox_event_dht_get_nodes_response_get_public_key(event);
|
||||
const char *ip = (const char *)tox_event_dht_get_nodes_response_get_ip(event);
|
||||
const uint16_t port = tox_event_dht_get_nodes_response_get_port(event);
|
||||
|
||||
if (node_crawled(state->nodes, state->num_nodes, public_key)) {
|
||||
return;
|
||||
@ -97,7 +101,7 @@ static void getnodes_response_cb(Tox *tox, const uint8_t *public_key, const char
|
||||
|
||||
// ask new node to give us their close nodes to every public key
|
||||
for (size_t i = 0; i < NUM_TOXES; ++i) {
|
||||
tox_dht_get_nodes(tox, public_key, ip, port, state->public_key_list[i], nullptr);
|
||||
tox_dht_get_nodes(autotox->tox, public_key, ip, port, state->public_key_list[i], nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
@ -121,13 +125,12 @@ static void test_dht_getnodes(AutoTox *autotoxes)
|
||||
ck_assert(public_key_list[i] != nullptr);
|
||||
|
||||
tox_self_get_dht_id(autotoxes[i].tox, public_key_list[i]);
|
||||
tox_callback_dht_get_nodes_response(autotoxes[i].tox, getnodes_response_cb);
|
||||
tox_events_callback_dht_get_nodes_response(autotoxes[i].dispatch, getnodes_response_cb);
|
||||
|
||||
printf("Peer %zu dht closenode count total/announce-capable: %d/%d\n",
|
||||
i,
|
||||
tox_dht_get_num_closelist(autotoxes[i].tox),
|
||||
tox_dht_get_num_closelist_announce_capable(autotoxes[i].tox)
|
||||
);
|
||||
i,
|
||||
tox_dht_get_num_closelist(autotoxes[i].tox),
|
||||
tox_dht_get_num_closelist_announce_capable(autotoxes[i].tox));
|
||||
}
|
||||
|
||||
while (!all_nodes_crawled(autotoxes, NUM_TOXES, public_key_list)) {
|
||||
|
@ -168,7 +168,7 @@ static void test_keys(void)
|
||||
ck_assert(encrypted2a != nullptr);
|
||||
uint8_t *in_plaintext2a = (uint8_t *)malloc(plaintext_length2a);
|
||||
ck_assert(in_plaintext2a != nullptr);
|
||||
const Random *rng = system_random();
|
||||
const Random *rng = os_random();
|
||||
ck_assert(rng != nullptr);
|
||||
random_bytes(rng, in_plaintext2a, plaintext_length2a);
|
||||
ret = tox_pass_encrypt(in_plaintext2a, plaintext_length2a, key_char, 12, encrypted2a, &encerr);
|
||||
@ -184,7 +184,6 @@ static void test_keys(void)
|
||||
free(in_plaintext2a);
|
||||
free(out_plaintext2a);
|
||||
|
||||
|
||||
uint8_t encrypted2[44 + TOX_PASS_ENCRYPTION_EXTRA_LENGTH];
|
||||
ret = tox_pass_encrypt(string, 44, key_char, 12, encrypted2, &encerr);
|
||||
ck_assert_msg(ret, "generic failure 3: %d", encerr);
|
||||
|
@ -53,7 +53,7 @@ static void tox_file_receive(Tox *tox, uint32_t friend_number, uint32_t file_num
|
||||
|
||||
ck_assert_msg(memcmp(file_id, file_cmp_id, TOX_FILE_ID_LENGTH) == 0, "bad file_id");
|
||||
|
||||
uint8_t empty[TOX_FILE_ID_LENGTH] = {0};
|
||||
const uint8_t empty[TOX_FILE_ID_LENGTH] = {0};
|
||||
|
||||
ck_assert_msg(memcmp(empty, file_cmp_id, TOX_FILE_ID_LENGTH) != 0, "empty file_id");
|
||||
|
||||
@ -126,7 +126,6 @@ static void tox_file_chunk_request(Tox *tox, uint32_t friend_number, uint32_t fi
|
||||
Tox_Err_File_Send_Chunk error;
|
||||
tox_file_send_chunk(tox, friend_number, file_number, position, f_data, length, &error);
|
||||
|
||||
|
||||
ck_assert_msg(error == TOX_ERR_FILE_SEND_CHUNK_OK,
|
||||
"could not send chunk, error num=%d pos=%d len=%d", (int)error, (int)position, (int)length);
|
||||
|
||||
@ -134,7 +133,6 @@ static void tox_file_chunk_request(Tox *tox, uint32_t friend_number, uint32_t fi
|
||||
sending_pos += length;
|
||||
}
|
||||
|
||||
|
||||
static uint8_t num;
|
||||
static bool file_recv;
|
||||
static void write_file(Tox *tox, uint32_t friendnumber, uint32_t filenumber, uint64_t position, const uint8_t *data,
|
||||
@ -209,7 +207,6 @@ static void file_transfer_test(void)
|
||||
file_accepted = file_size = sendf_ok = size_recv = 0;
|
||||
file_recv = 0;
|
||||
max_sending = UINT64_MAX;
|
||||
uint64_t totalf_size = 100 * 1024 * 1024;
|
||||
|
||||
printf("Starting file streaming transfer test.\n");
|
||||
|
||||
@ -224,10 +221,10 @@ static void file_transfer_test(void)
|
||||
tox_callback_file_chunk_request(tox2, tox_file_chunk_request);
|
||||
tox_callback_file_recv_control(tox3, file_print_control);
|
||||
tox_callback_file_recv(tox3, tox_file_receive);
|
||||
totalf_size = UINT64_MAX;
|
||||
const uint64_t totalf_size = UINT64_MAX;
|
||||
Tox_File_Number fnum = tox_file_send(
|
||||
tox2, 0, TOX_FILE_KIND_DATA, totalf_size, nullptr,
|
||||
(const uint8_t *)"Gentoo.exe", sizeof("Gentoo.exe"), nullptr);
|
||||
tox2, 0, TOX_FILE_KIND_DATA, totalf_size, nullptr,
|
||||
(const uint8_t *)"Gentoo.exe", sizeof("Gentoo.exe"), nullptr);
|
||||
ck_assert_msg(fnum != UINT32_MAX, "tox_new_file_sender fail");
|
||||
|
||||
Tox_Err_File_Get gfierr;
|
||||
|
@ -26,10 +26,16 @@
|
||||
#define TOX_LOCALHOST "127.0.0.1"
|
||||
#endif
|
||||
|
||||
static void accept_friend_request(Tox *m, const uint8_t *public_key, const uint8_t *data, size_t length, void *userdata)
|
||||
static void accept_friend_request(const Tox_Event_Friend_Request *event, void *userdata)
|
||||
{
|
||||
Tox *tox = (Tox *)userdata;
|
||||
|
||||
const uint8_t *public_key = tox_event_friend_request_get_public_key(event);
|
||||
const uint8_t *data = tox_event_friend_request_get_message(event);
|
||||
const size_t length = tox_event_friend_request_get_message_length(event);
|
||||
|
||||
if (length == 7 && memcmp("Gentoo", data, 7) == 0) {
|
||||
tox_friend_add_norequest(m, public_key, nullptr);
|
||||
tox_friend_add_norequest(tox, public_key, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
@ -39,9 +45,17 @@ static uint64_t sending_pos;
|
||||
static uint8_t file_cmp_id[TOX_FILE_ID_LENGTH];
|
||||
static uint32_t file_accepted;
|
||||
static uint64_t file_size;
|
||||
static void tox_file_receive(Tox *tox, uint32_t friend_number, uint32_t file_number, uint32_t kind, uint64_t filesize,
|
||||
const uint8_t *filename, size_t filename_length, void *userdata)
|
||||
static void tox_file_receive(const Tox_Event_File_Recv *event, void *userdata)
|
||||
{
|
||||
Tox *state_tox = (Tox *)userdata;
|
||||
|
||||
const uint32_t friend_number = tox_event_file_recv_get_friend_number(event);
|
||||
const uint32_t file_number = tox_event_file_recv_get_file_number(event);
|
||||
const uint32_t kind = tox_event_file_recv_get_kind(event);
|
||||
const uint64_t filesize = tox_event_file_recv_get_file_size(event);
|
||||
const uint8_t *filename = tox_event_file_recv_get_filename(event);
|
||||
const size_t filename_length = tox_event_file_recv_get_filename_length(event);
|
||||
|
||||
ck_assert_msg(kind == TOX_FILE_KIND_DATA, "bad kind");
|
||||
|
||||
ck_assert_msg(filename_length == sizeof("Gentoo.exe")
|
||||
@ -49,11 +63,11 @@ static void tox_file_receive(Tox *tox, uint32_t friend_number, uint32_t file_num
|
||||
|
||||
uint8_t file_id[TOX_FILE_ID_LENGTH];
|
||||
|
||||
ck_assert_msg(tox_file_get_file_id(tox, friend_number, file_number, file_id, nullptr), "tox_file_get_file_id error");
|
||||
ck_assert_msg(tox_file_get_file_id(state_tox, friend_number, file_number, file_id, nullptr), "tox_file_get_file_id error");
|
||||
|
||||
ck_assert_msg(memcmp(file_id, file_cmp_id, TOX_FILE_ID_LENGTH) == 0, "bad file_id");
|
||||
|
||||
uint8_t empty[TOX_FILE_ID_LENGTH] = {0};
|
||||
const uint8_t empty[TOX_FILE_ID_LENGTH] = {0};
|
||||
|
||||
ck_assert_msg(memcmp(empty, file_cmp_id, TOX_FILE_ID_LENGTH) != 0, "empty file_id");
|
||||
|
||||
@ -64,7 +78,7 @@ static void tox_file_receive(Tox *tox, uint32_t friend_number, uint32_t file_num
|
||||
|
||||
Tox_Err_File_Seek err_s;
|
||||
|
||||
ck_assert_msg(tox_file_seek(tox, friend_number, file_number, 1337, &err_s), "tox_file_seek error");
|
||||
ck_assert_msg(tox_file_seek(state_tox, friend_number, file_number, 1337, &err_s), "tox_file_seek error");
|
||||
|
||||
ck_assert_msg(err_s == TOX_ERR_FILE_SEEK_OK, "tox_file_seek wrong error");
|
||||
|
||||
@ -74,21 +88,24 @@ static void tox_file_receive(Tox *tox, uint32_t friend_number, uint32_t file_num
|
||||
|
||||
Tox_Err_File_Control error;
|
||||
|
||||
ck_assert_msg(tox_file_control(tox, friend_number, file_number, TOX_FILE_CONTROL_RESUME, &error),
|
||||
ck_assert_msg(tox_file_control(state_tox, friend_number, file_number, TOX_FILE_CONTROL_RESUME, &error),
|
||||
"tox_file_control failed. %i", error);
|
||||
++file_accepted;
|
||||
|
||||
Tox_Err_File_Seek err_s;
|
||||
|
||||
ck_assert_msg(!tox_file_seek(tox, friend_number, file_number, 1234, &err_s), "tox_file_seek no error");
|
||||
ck_assert_msg(!tox_file_seek(state_tox, friend_number, file_number, 1234, &err_s), "tox_file_seek no error");
|
||||
|
||||
ck_assert_msg(err_s == TOX_ERR_FILE_SEEK_DENIED, "tox_file_seek wrong error");
|
||||
}
|
||||
|
||||
static uint32_t sendf_ok;
|
||||
static void file_print_control(Tox *tox, uint32_t friend_number, uint32_t file_number, Tox_File_Control control,
|
||||
static void file_print_control(const Tox_Event_File_Recv_Control *event,
|
||||
void *userdata)
|
||||
{
|
||||
const uint32_t file_number = tox_event_file_recv_control_get_file_number(event);
|
||||
const Tox_File_Control control = tox_event_file_recv_control_get_control(event);
|
||||
|
||||
/* First send file num is 0.*/
|
||||
if (file_number == 0 && control == TOX_FILE_CONTROL_RESUME) {
|
||||
sendf_ok = 1;
|
||||
@ -99,12 +116,18 @@ static uint64_t max_sending;
|
||||
static bool m_send_reached;
|
||||
static uint8_t sending_num;
|
||||
static bool file_sending_done;
|
||||
static void tox_file_chunk_request(Tox *tox, uint32_t friend_number, uint32_t file_number, uint64_t position,
|
||||
size_t length, void *user_data)
|
||||
static void tox_file_chunk_request(const Tox_Event_File_Chunk_Request *event, void *user_data)
|
||||
{
|
||||
Tox *state_tox = (Tox *)user_data;
|
||||
|
||||
const uint32_t friend_number = tox_event_file_chunk_request_get_friend_number(event);
|
||||
const uint32_t file_number = tox_event_file_chunk_request_get_file_number(event);
|
||||
const uint64_t position = tox_event_file_chunk_request_get_position(event);
|
||||
size_t length = tox_event_file_chunk_request_get_length(event);
|
||||
|
||||
ck_assert_msg(sendf_ok, "didn't get resume control");
|
||||
|
||||
ck_assert_msg(sending_pos == position, "bad position %lu", (unsigned long)position);
|
||||
ck_assert_msg(sending_pos == position, "bad position %lu (should be %lu)", (unsigned long)position, (unsigned long)sending_pos);
|
||||
|
||||
if (length == 0) {
|
||||
ck_assert_msg(!file_sending_done, "file sending already done");
|
||||
@ -124,8 +147,7 @@ static void tox_file_chunk_request(Tox *tox, uint32_t friend_number, uint32_t fi
|
||||
memset(f_data, sending_num, length);
|
||||
|
||||
Tox_Err_File_Send_Chunk error;
|
||||
tox_file_send_chunk(tox, friend_number, file_number, position, f_data, length, &error);
|
||||
|
||||
tox_file_send_chunk(state_tox, friend_number, file_number, position, f_data, length, &error);
|
||||
|
||||
ck_assert_msg(error == TOX_ERR_FILE_SEND_CHUNK_OK,
|
||||
"could not send chunk, error num=%d pos=%d len=%d", (int)error, (int)position, (int)length);
|
||||
@ -134,12 +156,14 @@ static void tox_file_chunk_request(Tox *tox, uint32_t friend_number, uint32_t fi
|
||||
sending_pos += length;
|
||||
}
|
||||
|
||||
|
||||
static uint8_t num;
|
||||
static bool file_recv;
|
||||
static void write_file(Tox *tox, uint32_t friendnumber, uint32_t filenumber, uint64_t position, const uint8_t *data,
|
||||
size_t length, void *user_data)
|
||||
static void write_file(const Tox_Event_File_Recv_Chunk *event, void *user_data)
|
||||
{
|
||||
const uint64_t position = tox_event_file_recv_chunk_get_position(event);
|
||||
const uint8_t *data = tox_event_file_recv_chunk_get_data(event);
|
||||
const size_t length = tox_event_file_recv_chunk_get_data_length(event);
|
||||
|
||||
ck_assert_msg(size_recv == position, "bad position");
|
||||
|
||||
if (length == 0) {
|
||||
@ -156,6 +180,17 @@ static void write_file(Tox *tox, uint32_t friendnumber, uint32_t filenumber, uin
|
||||
size_recv += length;
|
||||
}
|
||||
|
||||
static void iterate_and_dispatch(const Tox_Dispatch *dispatch, Tox *tox)
|
||||
{
|
||||
Tox_Err_Events_Iterate err;
|
||||
Tox_Events *events;
|
||||
|
||||
events = tox_events_iterate(tox, true, &err);
|
||||
ck_assert(err == TOX_ERR_EVENTS_ITERATE_OK);
|
||||
tox_dispatch_invoke(dispatch, events, tox);
|
||||
tox_events_free(events);
|
||||
}
|
||||
|
||||
static void file_transfer_test(void)
|
||||
{
|
||||
printf("Starting test: few_clients\n");
|
||||
@ -171,7 +206,19 @@ static void file_transfer_test(void)
|
||||
|
||||
ck_assert_msg(tox1 && tox2 && tox3, "Failed to create 3 tox instances");
|
||||
|
||||
tox_callback_friend_request(tox2, accept_friend_request);
|
||||
tox_events_init(tox1);
|
||||
tox_events_init(tox2);
|
||||
tox_events_init(tox3);
|
||||
|
||||
Tox_Dispatch *dispatch1 = tox_dispatch_new(nullptr);
|
||||
ck_assert(dispatch1 != nullptr);
|
||||
Tox_Dispatch *dispatch2 = tox_dispatch_new(nullptr);
|
||||
ck_assert(dispatch2 != nullptr);
|
||||
Tox_Dispatch *dispatch3 = tox_dispatch_new(nullptr);
|
||||
ck_assert(dispatch3 != nullptr);
|
||||
|
||||
tox_events_callback_friend_request(dispatch2, accept_friend_request);
|
||||
|
||||
uint8_t address[TOX_ADDRESS_SIZE];
|
||||
tox_self_get_address(tox2, address);
|
||||
uint32_t test = tox_friend_add(tox3, address, (const uint8_t *)"Gentoo", 7, nullptr);
|
||||
@ -187,9 +234,9 @@ static void file_transfer_test(void)
|
||||
printf("Waiting for toxes to come online\n");
|
||||
|
||||
do {
|
||||
tox_iterate(tox1, nullptr);
|
||||
tox_iterate(tox2, nullptr);
|
||||
tox_iterate(tox3, nullptr);
|
||||
iterate_and_dispatch(dispatch1, tox1);
|
||||
iterate_and_dispatch(dispatch2, tox2);
|
||||
iterate_and_dispatch(dispatch3, tox3);
|
||||
|
||||
printf("Connections: self (%d, %d, %d), friends (%d, %d)\n",
|
||||
tox_self_get_connection_status(tox1),
|
||||
@ -210,11 +257,11 @@ static void file_transfer_test(void)
|
||||
file_recv = 0;
|
||||
max_sending = UINT64_MAX;
|
||||
uint64_t f_time = time(nullptr);
|
||||
tox_callback_file_recv_chunk(tox3, write_file);
|
||||
tox_callback_file_recv_control(tox2, file_print_control);
|
||||
tox_callback_file_chunk_request(tox2, tox_file_chunk_request);
|
||||
tox_callback_file_recv_control(tox3, file_print_control);
|
||||
tox_callback_file_recv(tox3, tox_file_receive);
|
||||
tox_events_callback_file_recv_chunk(dispatch3, write_file);
|
||||
tox_events_callback_file_recv_control(dispatch2, file_print_control);
|
||||
tox_events_callback_file_chunk_request(dispatch2, tox_file_chunk_request);
|
||||
tox_events_callback_file_recv_control(dispatch3, file_print_control);
|
||||
tox_events_callback_file_recv(dispatch3, tox_file_receive);
|
||||
uint64_t totalf_size = 100 * 1024 * 1024;
|
||||
uint32_t fnum = tox_file_send(tox2, 0, TOX_FILE_KIND_DATA, totalf_size, nullptr, (const uint8_t *)"Gentoo.exe",
|
||||
sizeof("Gentoo.exe"), nullptr);
|
||||
@ -231,9 +278,9 @@ static void file_transfer_test(void)
|
||||
const size_t max_iterations = INT16_MAX;
|
||||
|
||||
for (size_t i = 0; i < max_iterations; i++) {
|
||||
tox_iterate(tox1, nullptr);
|
||||
tox_iterate(tox2, nullptr);
|
||||
tox_iterate(tox3, nullptr);
|
||||
iterate_and_dispatch(dispatch1, tox1);
|
||||
iterate_and_dispatch(dispatch2, tox2);
|
||||
iterate_and_dispatch(dispatch3, tox3);
|
||||
|
||||
if (file_sending_done) {
|
||||
ck_assert_msg(sendf_ok && file_recv && totalf_size == file_size && size_recv == file_size && sending_pos == size_recv
|
||||
@ -274,11 +321,11 @@ static void file_transfer_test(void)
|
||||
sendf_ok = 0;
|
||||
size_recv = 0;
|
||||
file_recv = 0;
|
||||
tox_callback_file_recv_chunk(tox3, write_file);
|
||||
tox_callback_file_recv_control(tox2, file_print_control);
|
||||
tox_callback_file_chunk_request(tox2, tox_file_chunk_request);
|
||||
tox_callback_file_recv_control(tox3, file_print_control);
|
||||
tox_callback_file_recv(tox3, tox_file_receive);
|
||||
tox_events_callback_file_recv_chunk(dispatch3, write_file);
|
||||
tox_events_callback_file_recv_control(dispatch2, file_print_control);
|
||||
tox_events_callback_file_chunk_request(dispatch2, tox_file_chunk_request);
|
||||
tox_events_callback_file_recv_control(dispatch3, file_print_control);
|
||||
tox_events_callback_file_recv(dispatch3, tox_file_receive);
|
||||
totalf_size = 0;
|
||||
fnum = tox_file_send(tox2, 0, TOX_FILE_KIND_DATA, totalf_size, nullptr,
|
||||
(const uint8_t *)"Gentoo.exe", sizeof("Gentoo.exe"), nullptr);
|
||||
@ -298,9 +345,9 @@ static void file_transfer_test(void)
|
||||
|
||||
c_sleep(min_u32(tox1_interval, min_u32(tox2_interval, tox3_interval)));
|
||||
|
||||
tox_iterate(tox1, nullptr);
|
||||
tox_iterate(tox2, nullptr);
|
||||
tox_iterate(tox3, nullptr);
|
||||
iterate_and_dispatch(dispatch1, tox1);
|
||||
iterate_and_dispatch(dispatch2, tox2);
|
||||
iterate_and_dispatch(dispatch3, tox3);
|
||||
} while (!file_sending_done);
|
||||
|
||||
ck_assert_msg(sendf_ok && file_recv && totalf_size == file_size && size_recv == file_size
|
||||
@ -312,9 +359,12 @@ static void file_transfer_test(void)
|
||||
|
||||
printf("file_transfer_test succeeded, took %llu seconds\n", time(nullptr) - cur_time);
|
||||
|
||||
tox_kill(tox1);
|
||||
tox_kill(tox2);
|
||||
tox_dispatch_free(dispatch3);
|
||||
tox_dispatch_free(dispatch2);
|
||||
tox_dispatch_free(dispatch1);
|
||||
tox_kill(tox3);
|
||||
tox_kill(tox2);
|
||||
tox_kill(tox1);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
|
@ -47,8 +47,8 @@ static void test_forwarded_request_cb(void *object, const IP_Port *forwarder,
|
||||
const uint8_t *sendback, uint16_t sendback_length,
|
||||
const uint8_t *data, uint16_t length, void *userdata)
|
||||
{
|
||||
Test_Data *test_data = (Test_Data *)object;
|
||||
uint8_t *index = (uint8_t *)userdata;
|
||||
const Test_Data *test_data = (const Test_Data *)object;
|
||||
const uint8_t *index = (const uint8_t *)userdata;
|
||||
|
||||
if (length != 12 || memcmp("hello: ", data, 8) != 0) {
|
||||
printf("[%u] got unexpected data of length %d\n", *index, length);
|
||||
@ -66,7 +66,7 @@ static void test_forwarded_response_cb(void *object,
|
||||
const uint8_t *data, uint16_t length, void *userdata)
|
||||
{
|
||||
Test_Data *test_data = (Test_Data *)object;
|
||||
uint8_t *index = (uint8_t *)userdata;
|
||||
const uint8_t *index = (const uint8_t *)userdata;
|
||||
|
||||
if (length != 12 || memcmp("reply: ", data, 8) != 0) {
|
||||
printf("[%u] got unexpected data of length %d\n", *index, length);
|
||||
@ -104,9 +104,9 @@ typedef struct Forwarding_Subtox {
|
||||
|
||||
static Forwarding_Subtox *new_forwarding_subtox(const Memory *mem, bool no_udp, uint32_t *index, uint16_t port)
|
||||
{
|
||||
const Random *rng = system_random();
|
||||
const Random *rng = os_random();
|
||||
ck_assert(rng != nullptr);
|
||||
const Network *ns = system_network();
|
||||
const Network *ns = os_network();
|
||||
ck_assert(ns != nullptr);
|
||||
|
||||
Forwarding_Subtox *subtox = (Forwarding_Subtox *)calloc(1, sizeof(Forwarding_Subtox));
|
||||
@ -152,11 +152,11 @@ static void kill_forwarding_subtox(const Memory *mem, Forwarding_Subtox *subtox)
|
||||
|
||||
static void test_forwarding(void)
|
||||
{
|
||||
const Memory *mem = system_memory();
|
||||
const Memory *mem = os_memory();
|
||||
ck_assert(mem != nullptr);
|
||||
const Random *rng = system_random();
|
||||
const Random *rng = os_random();
|
||||
ck_assert(rng != nullptr);
|
||||
const Network *ns = system_network();
|
||||
const Network *ns = os_network();
|
||||
ck_assert(ns != nullptr);
|
||||
|
||||
uint32_t index[NUM_FORWARDER];
|
||||
@ -317,7 +317,6 @@ static void test_forwarding(void)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (uint32_t i = 0; i < NUM_FORWARDER; ++i) {
|
||||
kill_forwarding_subtox(mem, subtoxes[i]);
|
||||
}
|
||||
@ -325,7 +324,6 @@ static void test_forwarding(void)
|
||||
tox_kill(relay);
|
||||
}
|
||||
|
||||
|
||||
int main(void)
|
||||
{
|
||||
setvbuf(stdout, nullptr, _IONBF, 0);
|
||||
|
@ -22,12 +22,18 @@ typedef struct State {
|
||||
bool unused;
|
||||
} State;
|
||||
|
||||
static void accept_friend_request(Tox *tox, const uint8_t *public_key, const uint8_t *data, size_t length,
|
||||
static void accept_friend_request(const Tox_Event_Friend_Request *event,
|
||||
void *userdata)
|
||||
{
|
||||
AutoTox *autotox = (AutoTox *)userdata;
|
||||
|
||||
const uint8_t *public_key = tox_event_friend_request_get_public_key(event);
|
||||
const uint8_t *data = tox_event_friend_request_get_message(event);
|
||||
const size_t length = tox_event_friend_request_get_message_length(event);
|
||||
|
||||
ck_assert_msg(length == sizeof(FR_MESSAGE) && memcmp(FR_MESSAGE, data, sizeof(FR_MESSAGE)) == 0,
|
||||
"unexpected friend request message");
|
||||
tox_friend_add_norequest(tox, public_key, nullptr);
|
||||
tox_friend_add_norequest(autotox->tox, public_key, nullptr);
|
||||
}
|
||||
|
||||
static void test_friend_request(AutoTox *autotoxes)
|
||||
@ -35,7 +41,7 @@ static void test_friend_request(AutoTox *autotoxes)
|
||||
const time_t con_time = time(nullptr);
|
||||
|
||||
printf("All toxes add tox1 as friend.\n");
|
||||
tox_callback_friend_request(autotoxes[0].tox, accept_friend_request);
|
||||
tox_events_callback_friend_request(autotoxes[0].dispatch, accept_friend_request);
|
||||
|
||||
uint8_t address[TOX_ADDRESS_SIZE];
|
||||
tox_self_get_address(autotoxes[0].tox, address);
|
||||
|
@ -15,12 +15,36 @@
|
||||
|
||||
#define FR_MESSAGE "Gentoo"
|
||||
|
||||
static void accept_friend_request(Tox *tox, const uint8_t *public_key, const uint8_t *data, size_t length,
|
||||
static void accept_friend_request(const Tox_Event_Friend_Request *event,
|
||||
void *userdata)
|
||||
{
|
||||
Tox *state_tox = (Tox *)userdata;
|
||||
|
||||
const uint8_t *public_key = tox_event_friend_request_get_public_key(event);
|
||||
const uint8_t *data = tox_event_friend_request_get_message(event);
|
||||
const size_t length = tox_event_friend_request_get_message_length(event);
|
||||
|
||||
ck_assert_msg(length == sizeof(FR_MESSAGE) && memcmp(FR_MESSAGE, data, sizeof(FR_MESSAGE)) == 0,
|
||||
"unexpected friend request message");
|
||||
tox_friend_add_norequest(tox, public_key, nullptr);
|
||||
tox_friend_add_norequest(state_tox, public_key, nullptr);
|
||||
}
|
||||
|
||||
static void iterate2_wait(const Tox_Dispatch *dispatch, Tox *tox1, Tox *tox2)
|
||||
{
|
||||
Tox_Err_Events_Iterate err;
|
||||
Tox_Events *events;
|
||||
|
||||
events = tox_events_iterate(tox1, true, &err);
|
||||
ck_assert(err == TOX_ERR_EVENTS_ITERATE_OK);
|
||||
tox_dispatch_invoke(dispatch, events, tox1);
|
||||
tox_events_free(events);
|
||||
|
||||
events = tox_events_iterate(tox2, true, &err);
|
||||
ck_assert(err == TOX_ERR_EVENTS_ITERATE_OK);
|
||||
tox_dispatch_invoke(dispatch, events, tox2);
|
||||
tox_events_free(events);
|
||||
|
||||
c_sleep(ITERATION_INTERVAL);
|
||||
}
|
||||
|
||||
static void test_friend_request(void)
|
||||
@ -33,6 +57,9 @@ static void test_friend_request(void)
|
||||
|
||||
ck_assert_msg(tox1 && tox2, "failed to create 2 tox instances");
|
||||
|
||||
tox_events_init(tox1);
|
||||
tox_events_init(tox2);
|
||||
|
||||
printf("Bootstrapping tox2 off tox1.\n");
|
||||
uint8_t dht_key[TOX_PUBLIC_KEY_SIZE];
|
||||
tox_self_get_dht_id(tox1, dht_key);
|
||||
@ -40,11 +67,11 @@ static void test_friend_request(void)
|
||||
|
||||
tox_bootstrap(tox2, "localhost", dht_port, dht_key, nullptr);
|
||||
|
||||
do {
|
||||
tox_iterate(tox1, nullptr);
|
||||
tox_iterate(tox2, nullptr);
|
||||
Tox_Dispatch *dispatch = tox_dispatch_new(nullptr);
|
||||
ck_assert(dispatch != nullptr);
|
||||
|
||||
c_sleep(ITERATION_INTERVAL);
|
||||
do {
|
||||
iterate2_wait(dispatch, tox1, tox2);
|
||||
} while (tox_self_get_connection_status(tox1) == TOX_CONNECTION_NONE ||
|
||||
tox_self_get_connection_status(tox2) == TOX_CONNECTION_NONE);
|
||||
|
||||
@ -52,7 +79,7 @@ static void test_friend_request(void)
|
||||
const time_t con_time = time(nullptr);
|
||||
|
||||
printf("Tox1 adds tox2 as friend, tox2 accepts.\n");
|
||||
tox_callback_friend_request(tox2, accept_friend_request);
|
||||
tox_events_callback_friend_request(dispatch, accept_friend_request);
|
||||
|
||||
uint8_t address[TOX_ADDRESS_SIZE];
|
||||
tox_self_get_address(tox2, address);
|
||||
@ -61,16 +88,14 @@ static void test_friend_request(void)
|
||||
ck_assert_msg(test == 0, "failed to add friend error code: %u", test);
|
||||
|
||||
do {
|
||||
tox_iterate(tox1, nullptr);
|
||||
tox_iterate(tox2, nullptr);
|
||||
|
||||
c_sleep(ITERATION_INTERVAL);
|
||||
iterate2_wait(dispatch, tox1, tox2);
|
||||
} while (tox_friend_get_connection_status(tox1, 0, nullptr) != TOX_CONNECTION_UDP ||
|
||||
tox_friend_get_connection_status(tox2, 0, nullptr) != TOX_CONNECTION_UDP);
|
||||
|
||||
printf("Tox clients connected took %lu seconds.\n", (unsigned long)(time(nullptr) - con_time));
|
||||
printf("friend_request_test succeeded, took %lu seconds.\n", (unsigned long)(time(nullptr) - cur_time));
|
||||
|
||||
tox_dispatch_free(dispatch);
|
||||
tox_kill(tox1);
|
||||
tox_kill(tox2);
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ typedef struct State {
|
||||
|
||||
#define PEER_LIMIT 20
|
||||
|
||||
static void print_ip(Tox *tox, uint32_t groupnumber, uint32_t peer_id)
|
||||
static void print_ip(const Tox *tox, uint32_t groupnumber, uint32_t peer_id)
|
||||
{
|
||||
Tox_Err_Group_Peer_Query err;
|
||||
size_t length = tox_group_peer_get_ip_address_size(tox, groupnumber, peer_id, &err);
|
||||
@ -81,32 +81,35 @@ static bool all_group_peers_connected(AutoTox *autotoxes, uint32_t tox_count, ui
|
||||
return true;
|
||||
}
|
||||
|
||||
static void group_peer_join_handler(Tox *tox, uint32_t groupnumber, uint32_t peer_id, void *user_data)
|
||||
static void group_peer_join_handler(const Tox_Event_Group_Peer_Join *event, void *user_data)
|
||||
{
|
||||
AutoTox *autotox = (AutoTox *)user_data;
|
||||
ck_assert(autotox != nullptr);
|
||||
|
||||
State *state = (State *)autotox->state;
|
||||
|
||||
const uint32_t groupnumber = tox_event_group_peer_join_get_group_number(event);
|
||||
const uint32_t peer_id = tox_event_group_peer_join_get_peer_id(event);
|
||||
|
||||
// we do a connection test here for fun
|
||||
Tox_Err_Group_Peer_Query pq_err;
|
||||
TOX_CONNECTION connection_status = tox_group_peer_get_connection_status(tox, groupnumber, peer_id, &pq_err);
|
||||
Tox_Connection connection_status = tox_group_peer_get_connection_status(autotox->tox, groupnumber, peer_id, &pq_err);
|
||||
ck_assert(pq_err == TOX_ERR_GROUP_PEER_QUERY_OK);
|
||||
ck_assert(connection_status != TOX_CONNECTION_NONE);
|
||||
|
||||
Tox_Group_Role role = tox_group_peer_get_role(tox, groupnumber, peer_id, &pq_err);
|
||||
Tox_Group_Role role = tox_group_peer_get_role(autotox->tox, groupnumber, peer_id, &pq_err);
|
||||
ck_assert_msg(pq_err == TOX_ERR_GROUP_PEER_QUERY_OK, "%d", pq_err);
|
||||
|
||||
Tox_User_Status status = tox_group_peer_get_status(tox, groupnumber, peer_id, &pq_err);
|
||||
Tox_User_Status status = tox_group_peer_get_status(autotox->tox, groupnumber, peer_id, &pq_err);
|
||||
ck_assert_msg(pq_err == TOX_ERR_GROUP_PEER_QUERY_OK, "%d", pq_err);
|
||||
|
||||
size_t peer_name_len = tox_group_peer_get_name_size(tox, groupnumber, peer_id, &pq_err);
|
||||
size_t peer_name_len = tox_group_peer_get_name_size(autotox->tox, groupnumber, peer_id, &pq_err);
|
||||
char peer_name[TOX_MAX_NAME_LENGTH + 1];
|
||||
|
||||
ck_assert(pq_err == TOX_ERR_GROUP_PEER_QUERY_OK);
|
||||
ck_assert(peer_name_len <= TOX_MAX_NAME_LENGTH);
|
||||
|
||||
tox_group_peer_get_name(tox, groupnumber, peer_id, (uint8_t *) peer_name, &pq_err);
|
||||
tox_group_peer_get_name(autotox->tox, groupnumber, peer_id, (uint8_t *)peer_name, &pq_err);
|
||||
ck_assert(pq_err == TOX_ERR_GROUP_PEER_QUERY_OK);
|
||||
|
||||
peer_name[peer_name_len] = 0;
|
||||
@ -137,35 +140,37 @@ static void group_peer_join_handler(Tox *tox, uint32_t groupnumber, uint32_t pee
|
||||
}
|
||||
|
||||
fprintf(stderr, "%s joined with IP: ", peer_name);
|
||||
print_ip(tox, groupnumber, peer_id);
|
||||
print_ip(autotox->tox, groupnumber, peer_id);
|
||||
|
||||
state->peer_id = peer_id;
|
||||
++state->peer_joined_count;
|
||||
}
|
||||
|
||||
static void group_peer_self_join_handler(Tox *tox, uint32_t groupnumber, void *user_data)
|
||||
static void group_peer_self_join_handler(const Tox_Event_Group_Self_Join *event, void *user_data)
|
||||
{
|
||||
AutoTox *autotox = (AutoTox *)user_data;
|
||||
ck_assert(autotox != nullptr);
|
||||
|
||||
State *state = (State *)autotox->state;
|
||||
|
||||
const uint32_t groupnumber = tox_event_group_self_join_get_group_number(event);
|
||||
|
||||
// make sure we see our own correct peer state on join callback
|
||||
|
||||
Tox_Err_Group_Self_Query sq_err;
|
||||
size_t self_length = tox_group_self_get_name_size(tox, groupnumber, &sq_err);
|
||||
size_t self_length = tox_group_self_get_name_size(autotox->tox, groupnumber, &sq_err);
|
||||
|
||||
ck_assert(sq_err == TOX_ERR_GROUP_SELF_QUERY_OK);
|
||||
|
||||
uint8_t self_name[TOX_MAX_NAME_LENGTH];
|
||||
tox_group_self_get_name(tox, groupnumber, self_name, &sq_err);
|
||||
tox_group_self_get_name(autotox->tox, groupnumber, self_name, &sq_err);
|
||||
|
||||
ck_assert(sq_err == TOX_ERR_GROUP_SELF_QUERY_OK);
|
||||
|
||||
TOX_USER_STATUS self_status = tox_group_self_get_status(tox, groupnumber, &sq_err);
|
||||
Tox_User_Status self_status = tox_group_self_get_status(autotox->tox, groupnumber, &sq_err);
|
||||
ck_assert(sq_err == TOX_ERR_GROUP_SELF_QUERY_OK);
|
||||
|
||||
Tox_Group_Role self_role = tox_group_self_get_role(tox, groupnumber, &sq_err);
|
||||
Tox_Group_Role self_role = tox_group_self_get_role(autotox->tox, groupnumber, &sq_err);
|
||||
ck_assert(sq_err == TOX_ERR_GROUP_SELF_QUERY_OK);
|
||||
|
||||
if (state->is_founder) {
|
||||
@ -185,36 +190,37 @@ static void group_peer_self_join_handler(Tox *tox, uint32_t groupnumber, void *u
|
||||
uint8_t group_name[GROUP_NAME_LEN];
|
||||
uint8_t topic[TOX_GROUP_MAX_TOPIC_LENGTH];
|
||||
|
||||
ck_assert(tox_group_get_peer_limit(tox, groupnumber, nullptr) == PEER_LIMIT);
|
||||
ck_assert(tox_group_get_name_size(tox, groupnumber, nullptr) == GROUP_NAME_LEN);
|
||||
ck_assert(tox_group_get_topic_size(tox, groupnumber, nullptr) == TOPIC_LEN);
|
||||
ck_assert(tox_group_get_peer_limit(autotox->tox, groupnumber, nullptr) == PEER_LIMIT);
|
||||
ck_assert(tox_group_get_name_size(autotox->tox, groupnumber, nullptr) == GROUP_NAME_LEN);
|
||||
ck_assert(tox_group_get_topic_size(autotox->tox, groupnumber, nullptr) == TOPIC_LEN);
|
||||
|
||||
Tox_Err_Group_State_Queries query_err;
|
||||
tox_group_get_name(tox, groupnumber, group_name, &query_err);
|
||||
ck_assert_msg(query_err == TOX_ERR_GROUP_STATE_QUERIES_OK, "%d", query_err);
|
||||
Tox_Err_Group_State_Query query_err;
|
||||
tox_group_get_name(autotox->tox, groupnumber, group_name, &query_err);
|
||||
ck_assert_msg(query_err == TOX_ERR_GROUP_STATE_QUERY_OK, "%d", query_err);
|
||||
ck_assert(memcmp(group_name, GROUP_NAME, GROUP_NAME_LEN) == 0);
|
||||
|
||||
tox_group_get_topic(tox, groupnumber, topic, &query_err);
|
||||
ck_assert_msg(query_err == TOX_ERR_GROUP_STATE_QUERIES_OK, "%d", query_err);
|
||||
tox_group_get_topic(autotox->tox, groupnumber, topic, &query_err);
|
||||
ck_assert_msg(query_err == TOX_ERR_GROUP_STATE_QUERY_OK, "%d", query_err);
|
||||
ck_assert(memcmp(topic, TOPIC, TOPIC_LEN) == 0);
|
||||
|
||||
uint32_t peer_id = tox_group_self_get_peer_id(tox, groupnumber, nullptr);
|
||||
uint32_t peer_id = tox_group_self_get_peer_id(autotox->tox, groupnumber, nullptr);
|
||||
|
||||
fprintf(stderr, "self joined with IP: ");
|
||||
print_ip(tox, groupnumber, peer_id);
|
||||
print_ip(autotox->tox, groupnumber, peer_id);
|
||||
|
||||
++state->self_joined_count;
|
||||
}
|
||||
|
||||
static void group_peer_exit_handler(Tox *tox, uint32_t groupnumber, uint32_t peer_id, Tox_Group_Exit_Type exit_type,
|
||||
const uint8_t *name, size_t name_length, const uint8_t *part_message,
|
||||
size_t length, void *user_data)
|
||||
static void group_peer_exit_handler(const Tox_Event_Group_Peer_Exit *event, void *user_data)
|
||||
{
|
||||
AutoTox *autotox = (AutoTox *)user_data;
|
||||
ck_assert(autotox != nullptr);
|
||||
|
||||
State *state = (State *)autotox->state;
|
||||
|
||||
const uint8_t *part_message = tox_event_group_peer_exit_get_part_message(event);
|
||||
const size_t length = tox_event_group_peer_exit_get_part_message_length(event);
|
||||
|
||||
++state->peer_exit_count;
|
||||
|
||||
// first exit is a disconnect. second is a real exit with a part message
|
||||
@ -224,14 +230,16 @@ static void group_peer_exit_handler(Tox *tox, uint32_t groupnumber, uint32_t pee
|
||||
}
|
||||
}
|
||||
|
||||
static void group_peer_name_handler(Tox *tox, uint32_t groupnumber, uint32_t peer_id, const uint8_t *name,
|
||||
size_t length, void *user_data)
|
||||
static void group_peer_name_handler(const Tox_Event_Group_Peer_Name *event, void *user_data)
|
||||
{
|
||||
AutoTox *autotox = (AutoTox *)user_data;
|
||||
ck_assert(autotox != nullptr);
|
||||
|
||||
State *state = (State *)autotox->state;
|
||||
|
||||
const uint8_t *name = tox_event_group_peer_name_get_name(event);
|
||||
const size_t length = tox_event_group_peer_name_get_name_length(event);
|
||||
|
||||
// note: we already test the name_get api call elsewhere
|
||||
|
||||
ck_assert(length == PEER0_NICK2_LEN);
|
||||
@ -240,7 +248,7 @@ static void group_peer_name_handler(Tox *tox, uint32_t groupnumber, uint32_t pee
|
||||
state->peer_nick = true;
|
||||
}
|
||||
|
||||
static void group_peer_status_handler(Tox *tox, uint32_t groupnumber, uint32_t peer_id, TOX_USER_STATUS status,
|
||||
static void group_peer_status_handler(const Tox_Event_Group_Peer_Status *event,
|
||||
void *user_data)
|
||||
{
|
||||
AutoTox *autotox = (AutoTox *)user_data;
|
||||
@ -248,8 +256,12 @@ static void group_peer_status_handler(Tox *tox, uint32_t groupnumber, uint32_t p
|
||||
|
||||
State *state = (State *)autotox->state;
|
||||
|
||||
const uint32_t groupnumber = tox_event_group_peer_status_get_group_number(event);
|
||||
const uint32_t peer_id = tox_event_group_peer_status_get_peer_id(event);
|
||||
const Tox_User_Status status = tox_event_group_peer_status_get_status(event);
|
||||
|
||||
Tox_Err_Group_Peer_Query err;
|
||||
TOX_USER_STATUS cur_status = tox_group_peer_get_status(tox, groupnumber, peer_id, &err);
|
||||
Tox_User_Status cur_status = tox_group_peer_get_status(autotox->tox, groupnumber, peer_id, &err);
|
||||
|
||||
ck_assert_msg(cur_status == status, "%d, %d", cur_status, status);
|
||||
ck_assert(status == TOX_USER_STATUS_BUSY);
|
||||
@ -264,15 +276,15 @@ static void group_announce_test(AutoTox *autotoxes)
|
||||
Tox *tox0 = autotoxes[0].tox;
|
||||
Tox *tox1 = autotoxes[1].tox;
|
||||
State *state0 = (State *)autotoxes[0].state;
|
||||
State *state1 = (State *)autotoxes[1].state;
|
||||
const State *state1 = (const State *)autotoxes[1].state;
|
||||
|
||||
tox_callback_group_peer_join(tox0, group_peer_join_handler);
|
||||
tox_callback_group_peer_join(tox1, group_peer_join_handler);
|
||||
tox_callback_group_self_join(tox0, group_peer_self_join_handler);
|
||||
tox_callback_group_self_join(tox1, group_peer_self_join_handler);
|
||||
tox_callback_group_peer_name(tox1, group_peer_name_handler);
|
||||
tox_callback_group_peer_status(tox1, group_peer_status_handler);
|
||||
tox_callback_group_peer_exit(tox1, group_peer_exit_handler);
|
||||
tox_events_callback_group_peer_join(autotoxes[0].dispatch, group_peer_join_handler);
|
||||
tox_events_callback_group_peer_join(autotoxes[1].dispatch, group_peer_join_handler);
|
||||
tox_events_callback_group_self_join(autotoxes[0].dispatch, group_peer_self_join_handler);
|
||||
tox_events_callback_group_self_join(autotoxes[1].dispatch, group_peer_self_join_handler);
|
||||
tox_events_callback_group_peer_name(autotoxes[1].dispatch, group_peer_name_handler);
|
||||
tox_events_callback_group_peer_status(autotoxes[1].dispatch, group_peer_status_handler);
|
||||
tox_events_callback_group_peer_exit(autotoxes[1].dispatch, group_peer_exit_handler);
|
||||
|
||||
// tox0 makes new group.
|
||||
Tox_Err_Group_New err_new;
|
||||
@ -286,19 +298,19 @@ static void group_announce_test(AutoTox *autotoxes)
|
||||
iterate_all_wait(autotoxes, NUM_GROUP_TOXES, ITERATION_INTERVAL);
|
||||
|
||||
// changes the state (for sync check purposes)
|
||||
Tox_Err_Group_Founder_Set_Peer_Limit limit_set_err;
|
||||
tox_group_founder_set_peer_limit(tox0, groupnumber, PEER_LIMIT, &limit_set_err);
|
||||
ck_assert_msg(limit_set_err == TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_OK, "failed to set peer limit: %d", limit_set_err);
|
||||
Tox_Err_Group_Set_Peer_Limit limit_set_err;
|
||||
tox_group_set_peer_limit(tox0, groupnumber, PEER_LIMIT, &limit_set_err);
|
||||
ck_assert_msg(limit_set_err == TOX_ERR_GROUP_SET_PEER_LIMIT_OK, "failed to set peer limit: %d", limit_set_err);
|
||||
|
||||
Tox_Err_Group_Topic_Set tp_err;
|
||||
tox_group_set_topic(tox0, groupnumber, (const uint8_t *)TOPIC, TOPIC_LEN, &tp_err);
|
||||
ck_assert(tp_err == TOX_ERR_GROUP_TOPIC_SET_OK);
|
||||
|
||||
// get the chat id of the new group.
|
||||
Tox_Err_Group_State_Queries err_id;
|
||||
Tox_Err_Group_State_Query err_id;
|
||||
uint8_t chat_id[TOX_GROUP_CHAT_ID_SIZE];
|
||||
tox_group_get_chat_id(tox0, groupnumber, chat_id, &err_id);
|
||||
ck_assert(err_id == TOX_ERR_GROUP_STATE_QUERIES_OK);
|
||||
ck_assert(err_id == TOX_ERR_GROUP_STATE_QUERY_OK);
|
||||
|
||||
// tox1 joins it.
|
||||
Tox_Err_Group_Join err_join;
|
||||
@ -343,7 +355,7 @@ static void group_announce_test(AutoTox *autotoxes)
|
||||
|
||||
iterate_all_wait(autotoxes, NUM_GROUP_TOXES, ITERATION_INTERVAL);
|
||||
|
||||
TOX_USER_STATUS self_status = tox_group_self_get_status(tox0, groupnumber, &sq_err);
|
||||
Tox_User_Status self_status = tox_group_self_get_status(tox0, groupnumber, &sq_err);
|
||||
ck_assert(sq_err == TOX_ERR_GROUP_SELF_QUERY_OK);
|
||||
ck_assert(self_status == TOX_USER_STATUS_BUSY);
|
||||
|
||||
@ -429,10 +441,12 @@ static void group_announce_test(AutoTox *autotoxes)
|
||||
tox_group_leave(tox1, groupnumber, nullptr, 0, &err_exit);
|
||||
ck_assert(err_exit == TOX_ERR_GROUP_LEAVE_OK);
|
||||
|
||||
num_groups1 = tox_group_get_number_groups(tox0);
|
||||
num_groups2 = tox_group_get_number_groups(tox1);
|
||||
while (num_groups1 != 0 || num_groups2 != 0) {
|
||||
num_groups1 = tox_group_get_number_groups(tox0);
|
||||
num_groups2 = tox_group_get_number_groups(tox1);
|
||||
|
||||
ck_assert(num_groups1 == num_groups2 && num_groups2 == 0);
|
||||
iterate_all_wait(autotoxes, NUM_GROUP_TOXES, ITERATION_INTERVAL);
|
||||
}
|
||||
|
||||
printf("All tests passed!\n");
|
||||
}
|
||||
|
@ -51,13 +51,15 @@ static bool group_has_full_graph(const AutoTox *autotoxes, uint32_t group_number
|
||||
return true;
|
||||
}
|
||||
|
||||
static void group_join_fail_handler(Tox *tox, uint32_t group_number, Tox_Group_Join_Fail fail_type, void *user_data)
|
||||
static void group_join_fail_handler(const Tox_Event_Group_Join_Fail *event, void *user_data)
|
||||
{
|
||||
AutoTox *autotox = (AutoTox *)user_data;
|
||||
ck_assert(autotox != nullptr);
|
||||
|
||||
State *state = (State *)autotox->state;
|
||||
|
||||
const Tox_Group_Join_Fail fail_type = tox_event_group_join_fail_get_fail_type(event);
|
||||
|
||||
switch (fail_type) {
|
||||
case TOX_GROUP_JOIN_FAIL_PEER_LIMIT: {
|
||||
state->peer_limit_fail = true;
|
||||
@ -79,7 +81,7 @@ static void group_join_fail_handler(Tox *tox, uint32_t group_number, Tox_Group_J
|
||||
}
|
||||
}
|
||||
|
||||
static void group_self_join_handler(Tox *tox, uint32_t group_number, void *user_data)
|
||||
static void group_self_join_handler(const Tox_Event_Group_Self_Join *event, void *user_data)
|
||||
{
|
||||
AutoTox *autotox = (AutoTox *)user_data;
|
||||
ck_assert(autotox != nullptr);
|
||||
@ -89,7 +91,7 @@ static void group_self_join_handler(Tox *tox, uint32_t group_number, void *user_
|
||||
state->connected = true;
|
||||
}
|
||||
|
||||
static void group_peer_join_handler(Tox *tox, uint32_t group_number, uint32_t peer_id, void *user_data)
|
||||
static void group_peer_join_handler(const Tox_Event_Group_Peer_Join *event, void *user_data)
|
||||
{
|
||||
AutoTox *autotox = (AutoTox *)user_data;
|
||||
ck_assert(autotox != nullptr);
|
||||
@ -105,9 +107,9 @@ static void group_invite_test(AutoTox *autotoxes)
|
||||
ck_assert_msg(NUM_GROUP_TOXES > 7, "NUM_GROUP_TOXES is too small: %d", NUM_GROUP_TOXES);
|
||||
|
||||
for (size_t i = 0; i < NUM_GROUP_TOXES; ++i) {
|
||||
tox_callback_group_peer_join(autotoxes[i].tox, group_peer_join_handler);
|
||||
tox_callback_group_join_fail(autotoxes[i].tox, group_join_fail_handler);
|
||||
tox_callback_group_self_join(autotoxes[i].tox, group_self_join_handler);
|
||||
tox_events_callback_group_peer_join(autotoxes[i].dispatch, group_peer_join_handler);
|
||||
tox_events_callback_group_join_fail(autotoxes[i].dispatch, group_join_fail_handler);
|
||||
tox_events_callback_group_self_join(autotoxes[i].dispatch, group_self_join_handler);
|
||||
}
|
||||
|
||||
Tox *tox0 = autotoxes[0].tox;
|
||||
@ -118,12 +120,12 @@ static void group_invite_test(AutoTox *autotoxes)
|
||||
Tox *tox5 = autotoxes[5].tox;
|
||||
Tox *tox6 = autotoxes[6].tox;
|
||||
|
||||
State *state0 = (State *)autotoxes[0].state;
|
||||
State *state2 = (State *)autotoxes[2].state;
|
||||
State *state3 = (State *)autotoxes[3].state;
|
||||
State *state4 = (State *)autotoxes[4].state;
|
||||
State *state5 = (State *)autotoxes[5].state;
|
||||
State *state6 = (State *)autotoxes[6].state;
|
||||
const State *state0 = (const State *)autotoxes[0].state;
|
||||
const State *state2 = (const State *)autotoxes[2].state;
|
||||
const State *state3 = (const State *)autotoxes[3].state;
|
||||
const State *state4 = (const State *)autotoxes[4].state;
|
||||
const State *state5 = (const State *)autotoxes[5].state;
|
||||
const State *state6 = (const State *)autotoxes[6].state;
|
||||
|
||||
Tox_Err_Group_New new_err;
|
||||
uint32_t groupnumber = tox_group_new(tox0, TOX_GROUP_PRIVACY_STATE_PUBLIC, (const uint8_t *)"test", 4,
|
||||
@ -132,11 +134,11 @@ static void group_invite_test(AutoTox *autotoxes)
|
||||
|
||||
iterate_all_wait(autotoxes, NUM_GROUP_TOXES, ITERATION_INTERVAL);
|
||||
|
||||
Tox_Err_Group_State_Queries id_err;
|
||||
Tox_Err_Group_State_Query id_err;
|
||||
uint8_t chat_id[TOX_GROUP_CHAT_ID_SIZE];
|
||||
|
||||
tox_group_get_chat_id(tox0, groupnumber, chat_id, &id_err);
|
||||
ck_assert_msg(id_err == TOX_ERR_GROUP_STATE_QUERIES_OK, "%d", id_err);
|
||||
ck_assert_msg(id_err == TOX_ERR_GROUP_STATE_QUERY_OK, "%d", id_err);
|
||||
|
||||
// peer 1 joins public group with no password
|
||||
Tox_Err_Group_Join join_err;
|
||||
@ -150,9 +152,9 @@ static void group_invite_test(AutoTox *autotoxes)
|
||||
printf("Peer 1 joined group\n");
|
||||
|
||||
// founder sets a password
|
||||
Tox_Err_Group_Founder_Set_Password pass_set_err;
|
||||
tox_group_founder_set_password(tox0, groupnumber, (const uint8_t *)PASSWORD, PASS_LEN, &pass_set_err);
|
||||
ck_assert_msg(pass_set_err == TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_OK, "%d", pass_set_err);
|
||||
Tox_Err_Group_Set_Password pass_set_err;
|
||||
tox_group_set_password(tox0, groupnumber, (const uint8_t *)PASSWORD, PASS_LEN, &pass_set_err);
|
||||
ck_assert_msg(pass_set_err == TOX_ERR_GROUP_SET_PASSWORD_OK, "%d", pass_set_err);
|
||||
|
||||
iterate_all_wait(autotoxes, NUM_GROUP_TOXES, 5000);
|
||||
|
||||
@ -177,9 +179,9 @@ static void group_invite_test(AutoTox *autotoxes)
|
||||
printf("Peer 3 successfully blocked with invalid password\n");
|
||||
|
||||
// founder sets peer limit to 1
|
||||
Tox_Err_Group_Founder_Set_Peer_Limit limit_set_err;
|
||||
tox_group_founder_set_peer_limit(tox0, groupnumber, 1, &limit_set_err);
|
||||
ck_assert_msg(limit_set_err == TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_OK, "%d", limit_set_err);
|
||||
Tox_Err_Group_Set_Peer_Limit limit_set_err;
|
||||
tox_group_set_peer_limit(tox0, groupnumber, 1, &limit_set_err);
|
||||
ck_assert_msg(limit_set_err == TOX_ERR_GROUP_SET_PEER_LIMIT_OK, "%d", limit_set_err);
|
||||
|
||||
iterate_all_wait(autotoxes, NUM_GROUP_TOXES, 5000);
|
||||
|
||||
@ -194,11 +196,11 @@ static void group_invite_test(AutoTox *autotoxes)
|
||||
printf("Peer 4 successfully blocked from joining full group\n");
|
||||
|
||||
// founder removes password and increases peer limit to 100
|
||||
tox_group_founder_set_password(tox0, groupnumber, nullptr, 0, &pass_set_err);
|
||||
ck_assert_msg(pass_set_err == TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_OK, "%d", pass_set_err);
|
||||
tox_group_set_password(tox0, groupnumber, nullptr, 0, &pass_set_err);
|
||||
ck_assert_msg(pass_set_err == TOX_ERR_GROUP_SET_PASSWORD_OK, "%d", pass_set_err);
|
||||
|
||||
tox_group_founder_set_peer_limit(tox0, groupnumber, 100, &limit_set_err);
|
||||
ck_assert_msg(limit_set_err == TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_OK, "%d", limit_set_err);
|
||||
tox_group_set_peer_limit(tox0, groupnumber, 100, &limit_set_err);
|
||||
ck_assert_msg(limit_set_err == TOX_ERR_GROUP_SET_PEER_LIMIT_OK, "%d", limit_set_err);
|
||||
|
||||
iterate_all_wait(autotoxes, NUM_GROUP_TOXES, 5000);
|
||||
|
||||
@ -213,9 +215,9 @@ static void group_invite_test(AutoTox *autotoxes)
|
||||
printf("Peer 5 successfully joined the group\n");
|
||||
|
||||
// founder makes group private
|
||||
Tox_Err_Group_Founder_Set_Privacy_State priv_err;
|
||||
tox_group_founder_set_privacy_state(tox0, groupnumber, TOX_GROUP_PRIVACY_STATE_PRIVATE, &priv_err);
|
||||
ck_assert_msg(priv_err == TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_OK, "%d", priv_err);
|
||||
Tox_Err_Group_Set_Privacy_State priv_err;
|
||||
tox_group_set_privacy_state(tox0, groupnumber, TOX_GROUP_PRIVACY_STATE_PRIVATE, &priv_err);
|
||||
ck_assert_msg(priv_err == TOX_ERR_GROUP_SET_PRIVACY_STATE_OK, "%d", priv_err);
|
||||
|
||||
iterate_all_wait(autotoxes, NUM_GROUP_TOXES, 5000);
|
||||
|
||||
@ -231,8 +233,8 @@ static void group_invite_test(AutoTox *autotoxes)
|
||||
printf("Peer 6 failed to join private group via chat ID\n");
|
||||
|
||||
// founder makes group public again
|
||||
tox_group_founder_set_privacy_state(tox0, groupnumber, TOX_GROUP_PRIVACY_STATE_PUBLIC, &priv_err);
|
||||
ck_assert_msg(priv_err == TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_OK, "%d", priv_err);
|
||||
tox_group_set_privacy_state(tox0, groupnumber, TOX_GROUP_PRIVACY_STATE_PUBLIC, &priv_err);
|
||||
ck_assert_msg(priv_err == TOX_ERR_GROUP_SET_PRIVACY_STATE_OK, "%d", priv_err);
|
||||
|
||||
iterate_all_wait(autotoxes, NUM_GROUP_TOXES, ITERATION_INTERVAL);
|
||||
|
||||
|
@ -19,7 +19,7 @@ typedef struct State {
|
||||
bool peer_joined;
|
||||
bool message_sent;
|
||||
bool message_received;
|
||||
uint32_t pseudo_msg_id;
|
||||
Tox_Group_Message_Id pseudo_msg_id;
|
||||
bool private_message_received;
|
||||
size_t custom_packets_received;
|
||||
size_t custom_private_packets_received;
|
||||
@ -71,28 +71,37 @@ static uint16_t get_message_checksum(const uint8_t *message, uint16_t length)
|
||||
return sum;
|
||||
}
|
||||
|
||||
static void group_invite_handler(Tox *tox, uint32_t friend_number, const uint8_t *invite_data, size_t length,
|
||||
const uint8_t *group_name, size_t group_name_length, void *user_data)
|
||||
static void group_invite_handler(const Tox_Event_Group_Invite *event, void *user_data)
|
||||
{
|
||||
AutoTox *autotox = (AutoTox *)user_data;
|
||||
ck_assert(autotox != nullptr);
|
||||
|
||||
const uint32_t friend_number = tox_event_group_invite_get_friend_number(event);
|
||||
const uint8_t *invite_data = tox_event_group_invite_get_invite_data(event);
|
||||
const size_t length = tox_event_group_invite_get_invite_data_length(event);
|
||||
|
||||
printf("invite arrived; accepting\n");
|
||||
Tox_Err_Group_Invite_Accept err_accept;
|
||||
tox_group_invite_accept(tox, friend_number, invite_data, length, (const uint8_t *)PEER0_NICK, PEER0_NICK_LEN,
|
||||
tox_group_invite_accept(autotox->tox, friend_number, invite_data, length, (const uint8_t *)PEER0_NICK, PEER0_NICK_LEN,
|
||||
nullptr, 0, &err_accept);
|
||||
ck_assert(err_accept == TOX_ERR_GROUP_INVITE_ACCEPT_OK);
|
||||
}
|
||||
|
||||
static void group_join_fail_handler(Tox *tox, uint32_t groupnumber, Tox_Group_Join_Fail fail_type, void *user_data)
|
||||
static void group_join_fail_handler(const Tox_Event_Group_Join_Fail *event, void *user_data)
|
||||
{
|
||||
const Tox_Group_Join_Fail fail_type = tox_event_group_join_fail_get_fail_type(event);
|
||||
printf("join failed: %d\n", fail_type);
|
||||
}
|
||||
|
||||
static void group_peer_join_handler(Tox *tox, uint32_t groupnumber, uint32_t peer_id, void *user_data)
|
||||
static void group_peer_join_handler(const Tox_Event_Group_Peer_Join *event, void *user_data)
|
||||
{
|
||||
AutoTox *autotox = (AutoTox *)user_data;
|
||||
ck_assert(autotox != nullptr);
|
||||
|
||||
State *state = (State *)autotox->state;
|
||||
|
||||
const uint32_t peer_id = tox_event_group_peer_join_get_peer_id(event);
|
||||
|
||||
ck_assert_msg(state->peer_joined == false, "Peer timedout");
|
||||
|
||||
printf("peer %u joined, sending message\n", peer_id);
|
||||
@ -100,9 +109,16 @@ static void group_peer_join_handler(Tox *tox, uint32_t groupnumber, uint32_t pee
|
||||
state->peer_id = peer_id;
|
||||
}
|
||||
|
||||
static void group_custom_private_packet_handler(Tox *tox, uint32_t groupnumber, uint32_t peer_id, const uint8_t *data,
|
||||
size_t length, void *user_data)
|
||||
static void group_custom_private_packet_handler(const Tox_Event_Group_Custom_Private_Packet *event, void *user_data)
|
||||
{
|
||||
AutoTox *autotox = (AutoTox *)user_data;
|
||||
ck_assert(autotox != nullptr);
|
||||
|
||||
const uint32_t groupnumber = tox_event_group_custom_private_packet_get_group_number(event);
|
||||
const uint32_t peer_id = tox_event_group_custom_private_packet_get_peer_id(event);
|
||||
const uint8_t *data = tox_event_group_custom_private_packet_get_data(event);
|
||||
const size_t length = tox_event_group_custom_private_packet_get_data_length(event);
|
||||
|
||||
ck_assert_msg(length == TEST_CUSTOM_PRIVATE_PACKET_LEN,
|
||||
"Failed to receive custom private packet. Invalid length: %zu\n", length);
|
||||
|
||||
@ -111,25 +127,25 @@ static void group_custom_private_packet_handler(Tox *tox, uint32_t groupnumber,
|
||||
message_buf[length] = 0;
|
||||
|
||||
Tox_Err_Group_Peer_Query q_err;
|
||||
size_t peer_name_len = tox_group_peer_get_name_size(tox, groupnumber, peer_id, &q_err);
|
||||
size_t peer_name_len = tox_group_peer_get_name_size(autotox->tox, groupnumber, peer_id, &q_err);
|
||||
|
||||
ck_assert(q_err == TOX_ERR_GROUP_PEER_QUERY_OK);
|
||||
ck_assert(peer_name_len <= TOX_MAX_NAME_LENGTH);
|
||||
|
||||
char peer_name[TOX_MAX_NAME_LENGTH + 1];
|
||||
tox_group_peer_get_name(tox, groupnumber, peer_id, (uint8_t *) peer_name, &q_err);
|
||||
tox_group_peer_get_name(autotox->tox, groupnumber, peer_id, (uint8_t *) peer_name, &q_err);
|
||||
peer_name[peer_name_len] = 0;
|
||||
|
||||
ck_assert(q_err == TOX_ERR_GROUP_PEER_QUERY_OK);
|
||||
ck_assert(memcmp(peer_name, PEER0_NICK, peer_name_len) == 0);
|
||||
|
||||
Tox_Err_Group_Self_Query s_err;
|
||||
size_t self_name_len = tox_group_self_get_name_size(tox, groupnumber, &s_err);
|
||||
size_t self_name_len = tox_group_self_get_name_size(autotox->tox, groupnumber, &s_err);
|
||||
ck_assert(s_err == TOX_ERR_GROUP_SELF_QUERY_OK);
|
||||
ck_assert(self_name_len <= TOX_MAX_NAME_LENGTH);
|
||||
|
||||
char self_name[TOX_MAX_NAME_LENGTH + 1];
|
||||
tox_group_self_get_name(tox, groupnumber, (uint8_t *) self_name, &s_err);
|
||||
tox_group_self_get_name(autotox->tox, groupnumber, (uint8_t *)self_name, &s_err);
|
||||
self_name[self_name_len] = 0;
|
||||
|
||||
ck_assert(s_err == TOX_ERR_GROUP_SELF_QUERY_OK);
|
||||
@ -138,17 +154,21 @@ static void group_custom_private_packet_handler(Tox *tox, uint32_t groupnumber,
|
||||
printf("%s sent custom private packet to %s: %s\n", peer_name, self_name, message_buf);
|
||||
ck_assert(memcmp(message_buf, TEST_CUSTOM_PRIVATE_PACKET, length) == 0);
|
||||
|
||||
AutoTox *autotox = (AutoTox *)user_data;
|
||||
ck_assert(autotox != nullptr);
|
||||
|
||||
State *state = (State *)autotox->state;
|
||||
|
||||
++state->custom_private_packets_received;
|
||||
}
|
||||
|
||||
static void group_custom_packet_handler(Tox *tox, uint32_t groupnumber, uint32_t peer_id, const uint8_t *data,
|
||||
size_t length, void *user_data)
|
||||
static void group_custom_packet_handler(const Tox_Event_Group_Custom_Packet *event, void *user_data)
|
||||
{
|
||||
AutoTox *autotox = (AutoTox *)user_data;
|
||||
ck_assert(autotox != nullptr);
|
||||
|
||||
const uint32_t groupnumber = tox_event_group_custom_packet_get_group_number(event);
|
||||
const uint32_t peer_id = tox_event_group_custom_packet_get_peer_id(event);
|
||||
const uint8_t *data = tox_event_group_custom_packet_get_data(event);
|
||||
const size_t length = tox_event_group_custom_packet_get_data_length(event);
|
||||
|
||||
ck_assert_msg(length == TEST_CUSTOM_PACKET_LEN, "Failed to receive custom packet. Invalid length: %zu\n", length);
|
||||
|
||||
char message_buf[TOX_MAX_CUSTOM_PACKET_SIZE + 1];
|
||||
@ -156,25 +176,25 @@ static void group_custom_packet_handler(Tox *tox, uint32_t groupnumber, uint32_t
|
||||
message_buf[length] = 0;
|
||||
|
||||
Tox_Err_Group_Peer_Query q_err;
|
||||
size_t peer_name_len = tox_group_peer_get_name_size(tox, groupnumber, peer_id, &q_err);
|
||||
size_t peer_name_len = tox_group_peer_get_name_size(autotox->tox, groupnumber, peer_id, &q_err);
|
||||
|
||||
ck_assert(q_err == TOX_ERR_GROUP_PEER_QUERY_OK);
|
||||
ck_assert(peer_name_len <= TOX_MAX_NAME_LENGTH);
|
||||
|
||||
char peer_name[TOX_MAX_NAME_LENGTH + 1];
|
||||
tox_group_peer_get_name(tox, groupnumber, peer_id, (uint8_t *) peer_name, &q_err);
|
||||
tox_group_peer_get_name(autotox->tox, groupnumber, peer_id, (uint8_t *)peer_name, &q_err);
|
||||
peer_name[peer_name_len] = 0;
|
||||
|
||||
ck_assert(q_err == TOX_ERR_GROUP_PEER_QUERY_OK);
|
||||
ck_assert(memcmp(peer_name, PEER0_NICK, peer_name_len) == 0);
|
||||
|
||||
Tox_Err_Group_Self_Query s_err;
|
||||
size_t self_name_len = tox_group_self_get_name_size(tox, groupnumber, &s_err);
|
||||
size_t self_name_len = tox_group_self_get_name_size(autotox->tox, groupnumber, &s_err);
|
||||
ck_assert(s_err == TOX_ERR_GROUP_SELF_QUERY_OK);
|
||||
ck_assert(self_name_len <= TOX_MAX_NAME_LENGTH);
|
||||
|
||||
char self_name[TOX_MAX_NAME_LENGTH + 1];
|
||||
tox_group_self_get_name(tox, groupnumber, (uint8_t *) self_name, &s_err);
|
||||
tox_group_self_get_name(autotox->tox, groupnumber, (uint8_t *)self_name, &s_err);
|
||||
self_name[self_name_len] = 0;
|
||||
|
||||
ck_assert(s_err == TOX_ERR_GROUP_SELF_QUERY_OK);
|
||||
@ -183,32 +203,39 @@ static void group_custom_packet_handler(Tox *tox, uint32_t groupnumber, uint32_t
|
||||
printf("%s sent custom packet to %s: %s\n", peer_name, self_name, message_buf);
|
||||
ck_assert(memcmp(message_buf, TEST_CUSTOM_PACKET, length) == 0);
|
||||
|
||||
AutoTox *autotox = (AutoTox *)user_data;
|
||||
ck_assert(autotox != nullptr);
|
||||
|
||||
State *state = (State *)autotox->state;
|
||||
|
||||
++state->custom_packets_received;
|
||||
}
|
||||
|
||||
static void group_custom_packet_large_handler(Tox *tox, uint32_t groupnumber, uint32_t peer_id, const uint8_t *data,
|
||||
size_t length, void *user_data)
|
||||
static void group_custom_packet_large_handler(const Tox_Event_Group_Custom_Packet *event, void *user_data)
|
||||
{
|
||||
AutoTox *autotox = (AutoTox *)user_data;
|
||||
ck_assert(autotox != nullptr);
|
||||
|
||||
const uint8_t *data = tox_event_group_custom_packet_get_data(event);
|
||||
const size_t length = tox_event_group_custom_packet_get_data_length(event);
|
||||
|
||||
ck_assert_msg(length == TEST_CUSTOM_PACKET_LARGE_LEN, "Failed to receive large custom packet. Invalid length: %zu\n", length);
|
||||
|
||||
ck_assert(memcmp(data, TEST_CUSTOM_PACKET_LARGE, length) == 0);
|
||||
|
||||
AutoTox *autotox = (AutoTox *)user_data;
|
||||
ck_assert(autotox != nullptr);
|
||||
|
||||
State *state = (State *)autotox->state;
|
||||
|
||||
++state->custom_packets_received;
|
||||
}
|
||||
|
||||
static void group_message_handler(Tox *tox, uint32_t groupnumber, uint32_t peer_id, TOX_MESSAGE_TYPE type,
|
||||
const uint8_t *message, size_t length, uint32_t pseudo_msg_id, void *user_data)
|
||||
static void group_message_handler(const Tox_Event_Group_Message *event, void *user_data)
|
||||
{
|
||||
AutoTox *autotox = (AutoTox *)user_data;
|
||||
ck_assert(autotox != nullptr);
|
||||
|
||||
const uint32_t groupnumber = tox_event_group_message_get_group_number(event);
|
||||
const uint32_t peer_id = tox_event_group_message_get_peer_id(event);
|
||||
const uint8_t *message = tox_event_group_message_get_message(event);
|
||||
const size_t length = tox_event_group_message_get_message_length(event);
|
||||
const uint32_t pseudo_msg_id = tox_event_group_message_get_message_id(event);
|
||||
|
||||
ck_assert(!(length == IGNORE_MESSAGE_LEN && memcmp(message, IGNORE_MESSAGE, length) == 0));
|
||||
ck_assert_msg(length == TEST_MESSAGE_LEN, "Failed to receive message. Invalid length: %zu\n", length);
|
||||
|
||||
@ -217,25 +244,25 @@ static void group_message_handler(Tox *tox, uint32_t groupnumber, uint32_t peer_
|
||||
message_buf[length] = 0;
|
||||
|
||||
Tox_Err_Group_Peer_Query q_err;
|
||||
size_t peer_name_len = tox_group_peer_get_name_size(tox, groupnumber, peer_id, &q_err);
|
||||
size_t peer_name_len = tox_group_peer_get_name_size(autotox->tox, groupnumber, peer_id, &q_err);
|
||||
|
||||
ck_assert(q_err == TOX_ERR_GROUP_PEER_QUERY_OK);
|
||||
ck_assert(peer_name_len <= TOX_MAX_NAME_LENGTH);
|
||||
|
||||
char peer_name[TOX_MAX_NAME_LENGTH + 1];
|
||||
tox_group_peer_get_name(tox, groupnumber, peer_id, (uint8_t *) peer_name, &q_err);
|
||||
tox_group_peer_get_name(autotox->tox, groupnumber, peer_id, (uint8_t *)peer_name, &q_err);
|
||||
peer_name[peer_name_len] = 0;
|
||||
|
||||
ck_assert(q_err == TOX_ERR_GROUP_PEER_QUERY_OK);
|
||||
ck_assert(memcmp(peer_name, PEER0_NICK, peer_name_len) == 0);
|
||||
|
||||
Tox_Err_Group_Self_Query s_err;
|
||||
size_t self_name_len = tox_group_self_get_name_size(tox, groupnumber, &s_err);
|
||||
size_t self_name_len = tox_group_self_get_name_size(autotox->tox, groupnumber, &s_err);
|
||||
ck_assert(s_err == TOX_ERR_GROUP_SELF_QUERY_OK);
|
||||
ck_assert(self_name_len <= TOX_MAX_NAME_LENGTH);
|
||||
|
||||
char self_name[TOX_MAX_NAME_LENGTH + 1];
|
||||
tox_group_self_get_name(tox, groupnumber, (uint8_t *) self_name, &s_err);
|
||||
tox_group_self_get_name(autotox->tox, groupnumber, (uint8_t *)self_name, &s_err);
|
||||
self_name[self_name_len] = 0;
|
||||
|
||||
ck_assert(s_err == TOX_ERR_GROUP_SELF_QUERY_OK);
|
||||
@ -244,19 +271,24 @@ static void group_message_handler(Tox *tox, uint32_t groupnumber, uint32_t peer_
|
||||
printf("%s sent message to %s:(id:%u) %s\n", peer_name, self_name, pseudo_msg_id, message_buf);
|
||||
ck_assert(memcmp(message_buf, TEST_MESSAGE, length) == 0);
|
||||
|
||||
AutoTox *autotox = (AutoTox *)user_data;
|
||||
ck_assert(autotox != nullptr);
|
||||
|
||||
State *state = (State *)autotox->state;
|
||||
|
||||
state->message_received = true;
|
||||
|
||||
state->pseudo_msg_id = pseudo_msg_id;
|
||||
}
|
||||
|
||||
static void group_private_message_handler(Tox *tox, uint32_t groupnumber, uint32_t peer_id, TOX_MESSAGE_TYPE type,
|
||||
const uint8_t *message, size_t length, void *user_data)
|
||||
static void group_private_message_handler(const Tox_Event_Group_Private_Message *event, void *user_data)
|
||||
{
|
||||
AutoTox *autotox = (AutoTox *)user_data;
|
||||
ck_assert(autotox != nullptr);
|
||||
|
||||
const uint32_t groupnumber = tox_event_group_private_message_get_group_number(event);
|
||||
const uint32_t peer_id = tox_event_group_private_message_get_peer_id(event);
|
||||
const Tox_Message_Type type = tox_event_group_private_message_get_message_type(event);
|
||||
const uint8_t *message = tox_event_group_private_message_get_message(event);
|
||||
const size_t length = tox_event_group_private_message_get_message_length(event);
|
||||
const Tox_Group_Message_Id pseudo_msg_id = tox_event_group_private_message_get_message_id(event);
|
||||
|
||||
ck_assert_msg(length == TEST_PRIVATE_MESSAGE_LEN, "Failed to receive message. Invalid length: %zu\n", length);
|
||||
|
||||
char message_buf[TOX_GROUP_MAX_MESSAGE_LENGTH + 1];
|
||||
@ -264,46 +296,46 @@ static void group_private_message_handler(Tox *tox, uint32_t groupnumber, uint32
|
||||
message_buf[length] = 0;
|
||||
|
||||
Tox_Err_Group_Peer_Query q_err;
|
||||
size_t peer_name_len = tox_group_peer_get_name_size(tox, groupnumber, peer_id, &q_err);
|
||||
size_t peer_name_len = tox_group_peer_get_name_size(autotox->tox, groupnumber, peer_id, &q_err);
|
||||
|
||||
ck_assert(q_err == TOX_ERR_GROUP_PEER_QUERY_OK);
|
||||
ck_assert(peer_name_len <= TOX_MAX_NAME_LENGTH);
|
||||
|
||||
char peer_name[TOX_MAX_NAME_LENGTH + 1];
|
||||
tox_group_peer_get_name(tox, groupnumber, peer_id, (uint8_t *) peer_name, &q_err);
|
||||
tox_group_peer_get_name(autotox->tox, groupnumber, peer_id, (uint8_t *)peer_name, &q_err);
|
||||
peer_name[peer_name_len] = 0;
|
||||
|
||||
ck_assert(q_err == TOX_ERR_GROUP_PEER_QUERY_OK);
|
||||
ck_assert(memcmp(peer_name, PEER0_NICK, peer_name_len) == 0);
|
||||
|
||||
Tox_Err_Group_Self_Query s_err;
|
||||
size_t self_name_len = tox_group_self_get_name_size(tox, groupnumber, &s_err);
|
||||
size_t self_name_len = tox_group_self_get_name_size(autotox->tox, groupnumber, &s_err);
|
||||
ck_assert(s_err == TOX_ERR_GROUP_SELF_QUERY_OK);
|
||||
ck_assert(self_name_len <= TOX_MAX_NAME_LENGTH);
|
||||
|
||||
char self_name[TOX_MAX_NAME_LENGTH + 1];
|
||||
tox_group_self_get_name(tox, groupnumber, (uint8_t *) self_name, &s_err);
|
||||
tox_group_self_get_name(autotox->tox, groupnumber, (uint8_t *)self_name, &s_err);
|
||||
self_name[self_name_len] = 0;
|
||||
|
||||
ck_assert(s_err == TOX_ERR_GROUP_SELF_QUERY_OK);
|
||||
ck_assert(memcmp(self_name, PEER1_NICK, self_name_len) == 0);
|
||||
|
||||
printf("%s sent private action to %s: %s\n", peer_name, self_name, message_buf);
|
||||
printf("%s sent private action to %s:(id: %u) %s\n", peer_name, self_name, pseudo_msg_id, message_buf);
|
||||
ck_assert(memcmp(message_buf, TEST_PRIVATE_MESSAGE, length) == 0);
|
||||
|
||||
ck_assert(type == TOX_MESSAGE_TYPE_ACTION);
|
||||
|
||||
AutoTox *autotox = (AutoTox *)user_data;
|
||||
ck_assert(autotox != nullptr);
|
||||
|
||||
State *state = (State *)autotox->state;
|
||||
|
||||
state->private_message_received = true;
|
||||
state->pseudo_msg_id = pseudo_msg_id;
|
||||
}
|
||||
|
||||
static void group_message_handler_lossless_test(Tox *tox, uint32_t groupnumber, uint32_t peer_id, TOX_MESSAGE_TYPE type,
|
||||
const uint8_t *message, size_t length, uint32_t pseudo_msg_id, void *user_data)
|
||||
static void group_message_handler_lossless_test(const Tox_Event_Group_Message *event, void *user_data)
|
||||
{
|
||||
const uint8_t *message = tox_event_group_message_get_message(event);
|
||||
const size_t length = tox_event_group_message_get_message_length(event);
|
||||
|
||||
AutoTox *autotox = (AutoTox *)user_data;
|
||||
ck_assert(autotox != nullptr);
|
||||
|
||||
@ -325,10 +357,11 @@ static void group_message_handler_lossless_test(Tox *tox, uint32_t groupnumber,
|
||||
state->lossless_check = true;
|
||||
}
|
||||
}
|
||||
static void group_message_handler_wraparound_test(Tox *tox, uint32_t groupnumber, uint32_t peer_id,
|
||||
TOX_MESSAGE_TYPE type,
|
||||
const uint8_t *message, size_t length, uint32_t pseudo_msg_id, void *user_data)
|
||||
static void group_message_handler_wraparound_test(const Tox_Event_Group_Message *event, void *user_data)
|
||||
{
|
||||
const uint8_t *message = tox_event_group_message_get_message(event);
|
||||
const size_t length = tox_event_group_message_get_message_length(event);
|
||||
|
||||
AutoTox *autotox = (AutoTox *)user_data;
|
||||
ck_assert(autotox != nullptr);
|
||||
|
||||
@ -352,11 +385,11 @@ static void group_message_test(AutoTox *autotoxes)
|
||||
{
|
||||
ck_assert_msg(NUM_GROUP_TOXES >= 2, "NUM_GROUP_TOXES is too small: %d", NUM_GROUP_TOXES);
|
||||
|
||||
const Random *rng = system_random();
|
||||
const Random *rng = os_random();
|
||||
ck_assert(rng != nullptr);
|
||||
|
||||
Tox *tox0 = autotoxes[0].tox;
|
||||
Tox *tox1 = autotoxes[1].tox;
|
||||
const Tox *tox1 = autotoxes[1].tox;
|
||||
|
||||
State *state0 = (State *)autotoxes[0].state;
|
||||
State *state1 = (State *)autotoxes[1].state;
|
||||
@ -365,15 +398,15 @@ static void group_message_test(AutoTox *autotoxes)
|
||||
state0->pseudo_msg_id = 0;
|
||||
state1->pseudo_msg_id = 1;
|
||||
|
||||
tox_callback_group_invite(tox1, group_invite_handler);
|
||||
tox_callback_group_join_fail(tox1, group_join_fail_handler);
|
||||
tox_callback_group_peer_join(tox1, group_peer_join_handler);
|
||||
tox_callback_group_join_fail(tox0, group_join_fail_handler);
|
||||
tox_callback_group_peer_join(tox0, group_peer_join_handler);
|
||||
tox_callback_group_message(tox0, group_message_handler);
|
||||
tox_callback_group_custom_packet(tox0, group_custom_packet_handler);
|
||||
tox_callback_group_custom_private_packet(tox0, group_custom_private_packet_handler);
|
||||
tox_callback_group_private_message(tox0, group_private_message_handler);
|
||||
tox_events_callback_group_invite(autotoxes[1].dispatch, group_invite_handler);
|
||||
tox_events_callback_group_join_fail(autotoxes[1].dispatch, group_join_fail_handler);
|
||||
tox_events_callback_group_peer_join(autotoxes[1].dispatch, group_peer_join_handler);
|
||||
tox_events_callback_group_join_fail(autotoxes[0].dispatch, group_join_fail_handler);
|
||||
tox_events_callback_group_peer_join(autotoxes[0].dispatch, group_peer_join_handler);
|
||||
tox_events_callback_group_message(autotoxes[0].dispatch, group_message_handler);
|
||||
tox_events_callback_group_custom_packet(autotoxes[0].dispatch, group_custom_packet_handler);
|
||||
tox_events_callback_group_custom_private_packet(autotoxes[0].dispatch, group_custom_private_packet_handler);
|
||||
tox_events_callback_group_private_message(autotoxes[0].dispatch, group_private_message_handler);
|
||||
|
||||
Tox_Err_Group_Send_Message err_send;
|
||||
|
||||
@ -396,14 +429,15 @@ static void group_message_test(AutoTox *autotoxes)
|
||||
|
||||
if (state1->peer_joined && !state1->message_sent) {
|
||||
state1->pseudo_msg_id = tox_group_send_message(
|
||||
tox1, group_number, TOX_MESSAGE_TYPE_NORMAL, (const uint8_t *)TEST_MESSAGE,
|
||||
TEST_MESSAGE_LEN, &err_send);
|
||||
tox1, group_number, TOX_MESSAGE_TYPE_NORMAL, (const uint8_t *)TEST_MESSAGE,
|
||||
TEST_MESSAGE_LEN, &err_send);
|
||||
ck_assert(err_send == TOX_ERR_GROUP_SEND_MESSAGE_OK);
|
||||
state1->message_sent = true;
|
||||
}
|
||||
}
|
||||
|
||||
ck_assert_msg(state0->pseudo_msg_id == state1->pseudo_msg_id, "id0:%u id1:%u", state0->pseudo_msg_id, state1->pseudo_msg_id);
|
||||
ck_assert_msg(state0->pseudo_msg_id == state1->pseudo_msg_id, "id0:%u id1:%u",
|
||||
state0->pseudo_msg_id, state1->pseudo_msg_id);
|
||||
|
||||
// Make sure we're still connected to each friend
|
||||
Tox_Connection conn_1 = tox_friend_get_connection_status(tox0, 0, nullptr);
|
||||
@ -428,14 +462,23 @@ static void group_message_test(AutoTox *autotoxes)
|
||||
tox_group_set_ignore(tox0, group_number, state0->peer_id, false, &ig_err);
|
||||
ck_assert_msg(ig_err == TOX_ERR_GROUP_SET_IGNORE_OK, "%d", ig_err);
|
||||
|
||||
fprintf(stderr, "Sending private message...\n");
|
||||
fprintf(stderr, "Sending private action...\n");
|
||||
|
||||
// tox0 sends a private action to tox1
|
||||
// tox1 sends a private action to tox0
|
||||
Tox_Err_Group_Send_Private_Message m_err;
|
||||
tox_group_send_private_message(tox1, group_number, state1->peer_id, TOX_MESSAGE_TYPE_ACTION,
|
||||
(const uint8_t *)TEST_PRIVATE_MESSAGE, TEST_PRIVATE_MESSAGE_LEN, &m_err);
|
||||
state1->pseudo_msg_id = tox_group_send_private_message(tox1, group_number, state1->peer_id,
|
||||
TOX_MESSAGE_TYPE_ACTION, (const uint8_t *)TEST_PRIVATE_MESSAGE,
|
||||
TEST_PRIVATE_MESSAGE_LEN, &m_err);
|
||||
|
||||
ck_assert_msg(m_err == TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_OK, "%d", m_err);
|
||||
|
||||
while (!state0->private_message_received) {
|
||||
iterate_all_wait(autotoxes, NUM_GROUP_TOXES, ITERATION_INTERVAL);
|
||||
}
|
||||
|
||||
ck_assert_msg(state0->pseudo_msg_id == state1->pseudo_msg_id, "id0:%u id1:%u",
|
||||
state0->pseudo_msg_id, state1->pseudo_msg_id);
|
||||
|
||||
fprintf(stderr, "Sending custom packets...\n");
|
||||
|
||||
// tox0 sends a lossless and lossy custom packet to tox1
|
||||
@ -464,15 +507,14 @@ static void group_message_test(AutoTox *autotoxes)
|
||||
|
||||
ck_assert_msg(cperr == TOX_ERR_GROUP_SEND_CUSTOM_PRIVATE_PACKET_OK, "%d", cperr);
|
||||
|
||||
while (!state0->private_message_received || state0->custom_packets_received < 2
|
||||
|| state0->custom_private_packets_received < 2) {
|
||||
while (state0->custom_packets_received < 2 || state0->custom_private_packets_received < 2) {
|
||||
iterate_all_wait(autotoxes, NUM_GROUP_TOXES, ITERATION_INTERVAL);
|
||||
}
|
||||
|
||||
// tox0 sends a large max sized lossy custom packet
|
||||
|
||||
// overwrite callback for larger packet
|
||||
tox_callback_group_custom_packet(tox0, group_custom_packet_large_handler);
|
||||
tox_events_callback_group_custom_packet(autotoxes[0].dispatch, group_custom_packet_large_handler);
|
||||
|
||||
tox_group_send_custom_packet(tox1, group_number, false, (const uint8_t *)TEST_CUSTOM_PACKET_LARGE, TEST_CUSTOM_PACKET_LARGE_LEN,
|
||||
&c_err);
|
||||
@ -486,7 +528,7 @@ static void group_message_test(AutoTox *autotoxes)
|
||||
|
||||
fprintf(stderr, "Doing lossless packet test...\n");
|
||||
|
||||
tox_callback_group_message(tox1, group_message_handler_lossless_test);
|
||||
tox_events_callback_group_message(autotoxes[1].dispatch, group_message_handler_lossless_test);
|
||||
state1->last_msg_recv = -1;
|
||||
|
||||
// lossless and packet splitting/reassembly test
|
||||
@ -517,7 +559,7 @@ static void group_message_test(AutoTox *autotoxes)
|
||||
}
|
||||
|
||||
state1->last_msg_recv = -1;
|
||||
tox_callback_group_message(tox1, group_message_handler_wraparound_test);
|
||||
tox_events_callback_group_message(autotoxes[1].dispatch, group_message_handler_wraparound_test);
|
||||
|
||||
fprintf(stderr, "Doing wraparound test...\n");
|
||||
|
||||
|
@ -19,13 +19,13 @@
|
||||
#define GROUP_NAME_LEN (sizeof(GROUP_NAME) - 1)
|
||||
|
||||
typedef struct Peer {
|
||||
char name[TOX_MAX_NAME_LENGTH];
|
||||
char name[TOX_MAX_NAME_LENGTH + 1];
|
||||
size_t name_length;
|
||||
uint32_t peer_id;
|
||||
} Peer;
|
||||
|
||||
typedef struct State {
|
||||
char self_name[TOX_MAX_NAME_LENGTH];
|
||||
char self_name[TOX_MAX_NAME_LENGTH + 1];
|
||||
size_t self_name_length;
|
||||
|
||||
uint32_t group_number;
|
||||
@ -38,7 +38,6 @@ typedef struct State {
|
||||
char mod_name1[TOX_MAX_NAME_LENGTH];
|
||||
char mod_name2[TOX_MAX_NAME_LENGTH];
|
||||
|
||||
|
||||
bool observer_check;
|
||||
size_t observer_event_count;
|
||||
char observer_name1[TOX_MAX_NAME_LENGTH];
|
||||
@ -53,7 +52,7 @@ typedef struct State {
|
||||
static bool all_peers_connected(AutoTox *autotoxes)
|
||||
{
|
||||
for (size_t i = 0; i < NUM_GROUP_TOXES; ++i) {
|
||||
State *state = (State *)autotoxes[i].state;
|
||||
const State *state = (const State *)autotoxes[i].state;
|
||||
|
||||
if (state->num_peers != NUM_GROUP_TOXES - 1) {
|
||||
return false;
|
||||
@ -146,7 +145,7 @@ static size_t get_state_index_by_nick(const AutoTox *autotoxes, size_t num_peers
|
||||
ck_assert(name != nullptr && name_length <= TOX_MAX_NAME_LENGTH);
|
||||
|
||||
for (size_t i = 0; i < num_peers; ++i) {
|
||||
State *state = (State *)autotoxes[i].state;
|
||||
const State *state = (const State *)autotoxes[i].state;
|
||||
|
||||
if (memcmp(state->self_name, name, name_length) == 0) {
|
||||
return i;
|
||||
@ -156,29 +155,33 @@ static size_t get_state_index_by_nick(const AutoTox *autotoxes, size_t num_peers
|
||||
ck_assert_msg(0, "Failed to find index");
|
||||
}
|
||||
|
||||
static void group_join_fail_handler(Tox *tox, uint32_t group_number, Tox_Group_Join_Fail fail_type, void *user_data)
|
||||
static void group_join_fail_handler(const Tox_Event_Group_Join_Fail *event, void *user_data)
|
||||
{
|
||||
const Tox_Group_Join_Fail fail_type = tox_event_group_join_fail_get_fail_type(event);
|
||||
fprintf(stderr, "Failed to join group: %d", fail_type);
|
||||
}
|
||||
|
||||
static void group_peer_join_handler(Tox *tox, uint32_t group_number, uint32_t peer_id, void *user_data)
|
||||
static void group_peer_join_handler(const Tox_Event_Group_Peer_Join *event, void *user_data)
|
||||
{
|
||||
AutoTox *autotox = (AutoTox *)user_data;
|
||||
ck_assert(autotox != nullptr);
|
||||
|
||||
State *state = (State *)autotox->state;
|
||||
|
||||
const uint32_t group_number = tox_event_group_peer_join_get_group_number(event);
|
||||
const uint32_t peer_id = tox_event_group_peer_join_get_peer_id(event);
|
||||
|
||||
ck_assert(state->group_number == group_number);
|
||||
|
||||
char peer_name[TOX_MAX_NAME_LENGTH + 1];
|
||||
|
||||
Tox_Err_Group_Peer_Query q_err;
|
||||
size_t peer_name_len = tox_group_peer_get_name_size(tox, group_number, peer_id, &q_err);
|
||||
size_t peer_name_len = tox_group_peer_get_name_size(autotox->tox, group_number, peer_id, &q_err);
|
||||
|
||||
ck_assert(q_err == TOX_ERR_GROUP_PEER_QUERY_OK);
|
||||
ck_assert(peer_name_len <= TOX_MAX_NAME_LENGTH);
|
||||
|
||||
tox_group_peer_get_name(tox, group_number, peer_id, (uint8_t *) peer_name, &q_err);
|
||||
tox_group_peer_get_name(autotox->tox, group_number, peer_id, (uint8_t *) peer_name, &q_err);
|
||||
peer_name[peer_name_len] = 0;
|
||||
ck_assert(q_err == TOX_ERR_GROUP_PEER_QUERY_OK);
|
||||
|
||||
@ -193,7 +196,7 @@ static void group_peer_join_handler(Tox *tox, uint32_t group_number, uint32_t pe
|
||||
ck_assert(state->num_peers < NUM_GROUP_TOXES);
|
||||
}
|
||||
|
||||
static void handle_mod(State *state, const char *peer_name, size_t peer_name_len, Tox_Group_Role role)
|
||||
static void handle_mod(State *state, const char *peer_name, size_t peer_name_len)
|
||||
{
|
||||
if (state->mod_event_count == 0) {
|
||||
ck_assert(memcmp(peer_name, state->mod_name1, peer_name_len) == 0);
|
||||
@ -205,10 +208,9 @@ static void handle_mod(State *state, const char *peer_name, size_t peer_name_len
|
||||
|
||||
++state->mod_event_count;
|
||||
state->mod_check = true;
|
||||
ck_assert(role == TOX_GROUP_ROLE_MODERATOR);
|
||||
}
|
||||
|
||||
static void handle_observer(State *state, const char *peer_name, size_t peer_name_len, Tox_Group_Role role)
|
||||
static void handle_observer(State *state, const char *peer_name, size_t peer_name_len)
|
||||
{
|
||||
if (state->observer_event_count == 0) {
|
||||
ck_assert(memcmp(peer_name, state->observer_name1, peer_name_len) == 0);
|
||||
@ -220,10 +222,9 @@ static void handle_observer(State *state, const char *peer_name, size_t peer_nam
|
||||
|
||||
++state->observer_event_count;
|
||||
state->observer_check = true;
|
||||
ck_assert(role == TOX_GROUP_ROLE_OBSERVER);
|
||||
}
|
||||
|
||||
static void handle_user(State *state, const char *peer_name, size_t peer_name_len, Tox_Group_Role role)
|
||||
static void handle_user(State *state, const char *peer_name, size_t peer_name_len)
|
||||
{
|
||||
// event 1: observer1 gets promoted back to user
|
||||
// event 2: observer2 gets promoted to moderator
|
||||
@ -243,23 +244,25 @@ static void handle_user(State *state, const char *peer_name, size_t peer_name_le
|
||||
|
||||
++state->user_event_count;
|
||||
state->user_check = true;
|
||||
ck_assert(role == TOX_GROUP_ROLE_USER);
|
||||
}
|
||||
|
||||
static void group_mod_event_handler(Tox *tox, uint32_t group_number, uint32_t source_peer_id, uint32_t target_peer_id,
|
||||
Tox_Group_Mod_Event mod_type, void *user_data)
|
||||
static void group_mod_event_handler(const Tox_Event_Group_Moderation *event, void *user_data)
|
||||
{
|
||||
AutoTox *autotox = (AutoTox *)user_data;
|
||||
ck_assert(autotox != nullptr);
|
||||
|
||||
State *state = (State *)autotox->state;
|
||||
|
||||
const uint32_t group_number = tox_event_group_moderation_get_group_number(event);
|
||||
const uint32_t target_peer_id = tox_event_group_moderation_get_target_peer_id(event);
|
||||
const Tox_Group_Mod_Event mod_type = tox_event_group_moderation_get_mod_type(event);
|
||||
|
||||
ck_assert(state->group_number == group_number);
|
||||
|
||||
char peer_name[TOX_MAX_NAME_LENGTH + 1];
|
||||
|
||||
Tox_Err_Group_Peer_Query q_err;
|
||||
size_t peer_name_len = tox_group_peer_get_name_size(tox, group_number, target_peer_id, &q_err);
|
||||
size_t peer_name_len = tox_group_peer_get_name_size(autotox->tox, group_number, target_peer_id, &q_err);
|
||||
|
||||
if (q_err == TOX_ERR_GROUP_PEER_QUERY_PEER_NOT_FOUND) { // may occurr on sync attempts
|
||||
return;
|
||||
@ -268,12 +271,13 @@ static void group_mod_event_handler(Tox *tox, uint32_t group_number, uint32_t so
|
||||
ck_assert_msg(q_err == TOX_ERR_GROUP_PEER_QUERY_OK, "error %d", q_err);
|
||||
ck_assert(peer_name_len <= TOX_MAX_NAME_LENGTH);
|
||||
|
||||
tox_group_peer_get_name(tox, group_number, target_peer_id, (uint8_t *) peer_name, &q_err);
|
||||
tox_group_peer_get_name(autotox->tox, group_number, target_peer_id, (uint8_t *) peer_name, &q_err);
|
||||
peer_name[peer_name_len] = 0;
|
||||
ck_assert(q_err == TOX_ERR_GROUP_PEER_QUERY_OK);
|
||||
|
||||
Tox_Group_Role role = tox_group_peer_get_role(tox, group_number, target_peer_id, &q_err);
|
||||
Tox_Group_Role role = tox_group_peer_get_role(autotox->tox, group_number, target_peer_id, &q_err);
|
||||
ck_assert(q_err == TOX_ERR_GROUP_PEER_QUERY_OK);
|
||||
ck_assert(role <= TOX_GROUP_ROLE_OBSERVER);
|
||||
|
||||
fprintf(stderr, "tox%u: got moderator event %d (%s), role = %s\n",
|
||||
autotox->index, mod_type, tox_group_mod_event_to_string(mod_type),
|
||||
@ -281,17 +285,17 @@ static void group_mod_event_handler(Tox *tox, uint32_t group_number, uint32_t so
|
||||
|
||||
switch (mod_type) {
|
||||
case TOX_GROUP_MOD_EVENT_MODERATOR: {
|
||||
handle_mod(state, peer_name, peer_name_len, role);
|
||||
handle_mod(state, peer_name, peer_name_len);
|
||||
break;
|
||||
}
|
||||
|
||||
case TOX_GROUP_MOD_EVENT_OBSERVER: {
|
||||
handle_observer(state, peer_name, peer_name_len, role);
|
||||
handle_observer(state, peer_name, peer_name_len);
|
||||
break;
|
||||
}
|
||||
|
||||
case TOX_GROUP_MOD_EVENT_USER: {
|
||||
handle_user(state, peer_name, peer_name_len, role);
|
||||
handle_user(state, peer_name, peer_name_len);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -314,7 +318,7 @@ static void check_self_role(AutoTox *autotoxes, uint32_t peer_id, Tox_Group_Role
|
||||
Tox_Err_Group_Self_Query sq_err;
|
||||
|
||||
for (size_t i = 0; i < NUM_GROUP_TOXES; ++i) {
|
||||
State *state = (State *)autotoxes[i].state;
|
||||
const State *state = (const State *)autotoxes[i].state;
|
||||
|
||||
uint32_t self_peer_id = tox_group_self_get_peer_id(autotoxes[i].tox, state->group_number, &sq_err);
|
||||
ck_assert(sq_err == TOX_ERR_GROUP_SELF_QUERY_OK);
|
||||
@ -378,13 +382,13 @@ static void voice_state_message_test(AutoTox *autotox, Tox_Group_Voice_State voi
|
||||
static bool all_peers_got_voice_state_change(AutoTox *autotoxes, uint32_t num_toxes,
|
||||
Tox_Group_Voice_State expected_voice_state)
|
||||
{
|
||||
Tox_Err_Group_State_Queries query_err;
|
||||
Tox_Err_Group_State_Query query_err;
|
||||
|
||||
for (uint32_t i = 0; i < num_toxes; ++i) {
|
||||
const State *state = (State *)autotoxes[i].state;
|
||||
|
||||
Tox_Group_Voice_State voice_state = tox_group_get_voice_state(autotoxes[i].tox, state->group_number, &query_err);
|
||||
ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERIES_OK);
|
||||
ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERY_OK);
|
||||
|
||||
if (voice_state != expected_voice_state) {
|
||||
return false;
|
||||
@ -398,10 +402,10 @@ static void check_voice_state(AutoTox *autotoxes, uint32_t num_toxes)
|
||||
{
|
||||
// founder sets voice state to Moderator
|
||||
const State *state = (State *)autotoxes[0].state;
|
||||
Tox_Err_Group_Founder_Set_Voice_State voice_set_err;
|
||||
tox_group_founder_set_voice_state(autotoxes[0].tox, state->group_number, TOX_GROUP_VOICE_STATE_MODERATOR,
|
||||
&voice_set_err);
|
||||
ck_assert(voice_set_err == TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_OK);
|
||||
Tox_Err_Group_Set_Voice_State voice_set_err;
|
||||
tox_group_set_voice_state(autotoxes[0].tox, state->group_number, TOX_GROUP_VOICE_STATE_MODERATOR,
|
||||
&voice_set_err);
|
||||
ck_assert(voice_set_err == TOX_ERR_GROUP_SET_VOICE_STATE_OK);
|
||||
|
||||
for (uint32_t i = 0; i < num_toxes; ++i) {
|
||||
do {
|
||||
@ -411,8 +415,8 @@ static void check_voice_state(AutoTox *autotoxes, uint32_t num_toxes)
|
||||
voice_state_message_test(&autotoxes[i], TOX_GROUP_VOICE_STATE_MODERATOR);
|
||||
}
|
||||
|
||||
tox_group_founder_set_voice_state(autotoxes[0].tox, state->group_number, TOX_GROUP_VOICE_STATE_FOUNDER, &voice_set_err);
|
||||
ck_assert(voice_set_err == TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_OK);
|
||||
tox_group_set_voice_state(autotoxes[0].tox, state->group_number, TOX_GROUP_VOICE_STATE_FOUNDER, &voice_set_err);
|
||||
ck_assert(voice_set_err == TOX_ERR_GROUP_SET_VOICE_STATE_OK);
|
||||
|
||||
for (uint32_t i = 0; i < num_toxes; ++i) {
|
||||
do {
|
||||
@ -422,8 +426,8 @@ static void check_voice_state(AutoTox *autotoxes, uint32_t num_toxes)
|
||||
voice_state_message_test(&autotoxes[i], TOX_GROUP_VOICE_STATE_FOUNDER);
|
||||
}
|
||||
|
||||
tox_group_founder_set_voice_state(autotoxes[0].tox, state->group_number, TOX_GROUP_VOICE_STATE_ALL, &voice_set_err);
|
||||
ck_assert(voice_set_err == TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_OK);
|
||||
tox_group_set_voice_state(autotoxes[0].tox, state->group_number, TOX_GROUP_VOICE_STATE_ALL, &voice_set_err);
|
||||
ck_assert(voice_set_err == TOX_ERR_GROUP_SET_VOICE_STATE_OK);
|
||||
|
||||
for (uint32_t i = 0; i < num_toxes; ++i) {
|
||||
do {
|
||||
@ -447,9 +451,9 @@ static void group_moderation_test(AutoTox *autotoxes)
|
||||
snprintf(state->self_name, sizeof(state->self_name), "peer_%zu", i);
|
||||
state->self_name[name_length] = 0;
|
||||
|
||||
tox_callback_group_join_fail(autotoxes[i].tox, group_join_fail_handler);
|
||||
tox_callback_group_peer_join(autotoxes[i].tox, group_peer_join_handler);
|
||||
tox_callback_group_moderation(autotoxes[i].tox, group_mod_event_handler);
|
||||
tox_events_callback_group_join_fail(autotoxes[i].dispatch, group_join_fail_handler);
|
||||
tox_events_callback_group_peer_join(autotoxes[i].dispatch, group_peer_join_handler);
|
||||
tox_events_callback_group_moderation(autotoxes[i].dispatch, group_mod_event_handler);
|
||||
}
|
||||
|
||||
iterate_all_wait(autotoxes, NUM_GROUP_TOXES, ITERATION_INTERVAL);
|
||||
@ -468,11 +472,11 @@ static void group_moderation_test(AutoTox *autotoxes)
|
||||
ck_assert_msg(err_new == TOX_ERR_GROUP_NEW_OK, "Failed to create group. error: %d\n", err_new);
|
||||
|
||||
/* Founder gets chat ID */
|
||||
Tox_Err_Group_State_Queries id_err;
|
||||
Tox_Err_Group_State_Query id_err;
|
||||
uint8_t chat_id[TOX_GROUP_CHAT_ID_SIZE];
|
||||
tox_group_get_chat_id(tox0, state0->group_number, chat_id, &id_err);
|
||||
|
||||
ck_assert_msg(id_err == TOX_ERR_GROUP_STATE_QUERIES_OK, "Failed to get chat ID. error: %d", id_err);
|
||||
ck_assert_msg(id_err == TOX_ERR_GROUP_STATE_QUERY_OK, "Failed to get chat ID. error: %d", id_err);
|
||||
|
||||
fprintf(stderr, "Peers attemping to join DHT group via the chat ID\n");
|
||||
|
||||
@ -512,7 +516,7 @@ static void group_moderation_test(AutoTox *autotoxes)
|
||||
|
||||
/* all peers should be user role except founder */
|
||||
for (size_t i = 1; i < NUM_GROUP_TOXES; ++i) {
|
||||
State *state = (State *)autotoxes[i].state;
|
||||
const State *state = (const State *)autotoxes[i].state;
|
||||
self_role = tox_group_self_get_role(autotoxes[i].tox, state->group_number, &sq_err);
|
||||
ck_assert(sq_err == TOX_ERR_GROUP_SELF_QUERY_OK);
|
||||
ck_assert(self_role == TOX_GROUP_ROLE_USER);
|
||||
@ -521,9 +525,9 @@ static void group_moderation_test(AutoTox *autotoxes)
|
||||
/* founder sets first peer to moderator */
|
||||
fprintf(stderr, "Founder setting %s to moderator\n", state0->peers[0].name);
|
||||
|
||||
Tox_Err_Group_Mod_Set_Role role_err;
|
||||
tox_group_mod_set_role(tox0, state0->group_number, state0->peers[0].peer_id, TOX_GROUP_ROLE_MODERATOR, &role_err);
|
||||
ck_assert_msg(role_err == TOX_ERR_GROUP_MOD_SET_ROLE_OK, "Failed to set moderator. error: %d", role_err);
|
||||
Tox_Err_Group_Set_Role role_err;
|
||||
tox_group_set_role(tox0, state0->group_number, state0->peers[0].peer_id, TOX_GROUP_ROLE_MODERATOR, &role_err);
|
||||
ck_assert_msg(role_err == TOX_ERR_GROUP_SET_ROLE_OK, "Failed to set moderator. error: %d", role_err);
|
||||
|
||||
// manually flag the role setter because they don't get a callback
|
||||
state0->mod_check = true;
|
||||
@ -537,8 +541,8 @@ static void group_moderation_test(AutoTox *autotoxes)
|
||||
/* founder sets second and third peer to observer */
|
||||
fprintf(stderr, "Founder setting %s to observer\n", state0->peers[1].name);
|
||||
|
||||
tox_group_mod_set_role(tox0, state0->group_number, state0->peers[1].peer_id, TOX_GROUP_ROLE_OBSERVER, &role_err);
|
||||
ck_assert_msg(role_err == TOX_ERR_GROUP_MOD_SET_ROLE_OK, "Failed to set observer. error: %d", role_err);
|
||||
tox_group_set_role(tox0, state0->group_number, state0->peers[1].peer_id, TOX_GROUP_ROLE_OBSERVER, &role_err);
|
||||
ck_assert_msg(role_err == TOX_ERR_GROUP_SET_ROLE_OK, "Failed to set observer. error: %d", role_err);
|
||||
|
||||
state0->observer_check = true;
|
||||
++state0->observer_event_count;
|
||||
@ -548,8 +552,8 @@ static void group_moderation_test(AutoTox *autotoxes)
|
||||
|
||||
fprintf(stderr, "Founder setting %s to observer\n", state0->peers[2].name);
|
||||
|
||||
tox_group_mod_set_role(tox0, state0->group_number, state0->peers[2].peer_id, TOX_GROUP_ROLE_OBSERVER, &role_err);
|
||||
ck_assert_msg(role_err == TOX_ERR_GROUP_MOD_SET_ROLE_OK, "Failed to set observer. error: %d", role_err);
|
||||
tox_group_set_role(tox0, state0->group_number, state0->peers[2].peer_id, TOX_GROUP_ROLE_OBSERVER, &role_err);
|
||||
ck_assert_msg(role_err == TOX_ERR_GROUP_SET_ROLE_OK, "Failed to set observer. error: %d", role_err);
|
||||
|
||||
state0->observer_check = true;
|
||||
++state0->observer_event_count;
|
||||
@ -574,8 +578,8 @@ static void group_moderation_test(AutoTox *autotoxes)
|
||||
|
||||
fprintf(stderr, "%s is promoting %s back to user\n", state1->self_name, state0->peers[1].name);
|
||||
|
||||
tox_group_mod_set_role(tox1, state1->group_number, obs_peer_id, TOX_GROUP_ROLE_USER, &role_err);
|
||||
ck_assert_msg(role_err == TOX_ERR_GROUP_MOD_SET_ROLE_OK, "Failed to promote observer back to user. error: %d",
|
||||
tox_group_set_role(tox1, state1->group_number, obs_peer_id, TOX_GROUP_ROLE_USER, &role_err);
|
||||
ck_assert_msg(role_err == TOX_ERR_GROUP_SET_ROLE_OK, "Failed to promote observer back to user. error: %d",
|
||||
role_err);
|
||||
|
||||
state1->user_check = true;
|
||||
@ -587,8 +591,8 @@ static void group_moderation_test(AutoTox *autotoxes)
|
||||
/* founder assigns third peer to moderator (this triggers two events: user and moderator) */
|
||||
fprintf(stderr, "Founder setting %s to moderator\n", state0->peers[2].name);
|
||||
|
||||
tox_group_mod_set_role(tox0, state0->group_number, state0->peers[2].peer_id, TOX_GROUP_ROLE_MODERATOR, &role_err);
|
||||
ck_assert_msg(role_err == TOX_ERR_GROUP_MOD_SET_ROLE_OK, "Failed to set moderator. error: %d", role_err);
|
||||
tox_group_set_role(tox0, state0->group_number, state0->peers[2].peer_id, TOX_GROUP_ROLE_MODERATOR, &role_err);
|
||||
ck_assert_msg(role_err == TOX_ERR_GROUP_SET_ROLE_OK, "Failed to set moderator. error: %d", role_err);
|
||||
|
||||
state0->mod_check = true;
|
||||
++state0->mod_event_count;
|
||||
@ -600,18 +604,27 @@ static void group_moderation_test(AutoTox *autotoxes)
|
||||
|
||||
/* moderator attempts to demote and kick founder */
|
||||
uint32_t founder_peer_id = get_peer_id_by_nick(state1->peers, NUM_GROUP_TOXES - 1, state0->self_name);
|
||||
tox_group_mod_set_role(tox1, state1->group_number, founder_peer_id, TOX_GROUP_ROLE_OBSERVER, &role_err);
|
||||
ck_assert_msg(role_err != TOX_ERR_GROUP_MOD_SET_ROLE_OK, "Mod set founder to observer");
|
||||
tox_group_set_role(tox1, state1->group_number, founder_peer_id, TOX_GROUP_ROLE_OBSERVER, &role_err);
|
||||
ck_assert_msg(role_err != TOX_ERR_GROUP_SET_ROLE_OK, "Mod set founder to observer");
|
||||
|
||||
Tox_Err_Group_Mod_Kick_Peer k_err;
|
||||
tox_group_mod_kick_peer(tox1, state1->group_number, founder_peer_id, &k_err);
|
||||
ck_assert_msg(k_err != TOX_ERR_GROUP_MOD_KICK_PEER_OK, "Mod kicked founder");
|
||||
Tox_Err_Group_Kick_Peer k_err;
|
||||
tox_group_kick_peer(tox1, state1->group_number, founder_peer_id, &k_err);
|
||||
ck_assert_msg(k_err != TOX_ERR_GROUP_KICK_PEER_OK, "Mod kicked founder");
|
||||
|
||||
/* the moderator about to be kicked changes the topic to trigger the founder to
|
||||
* re-sign and redistribute it after the kick.
|
||||
*/
|
||||
const State *state_x = (const State *)autotoxes[idx].state;
|
||||
Tox *tox_x = autotoxes[idx].tox;
|
||||
Tox_Err_Group_Topic_Set topic_err;
|
||||
tox_group_set_topic(tox_x, state_x->group_number, nullptr, 0, &topic_err);
|
||||
ck_assert(topic_err == TOX_ERR_GROUP_TOPIC_SET_OK);
|
||||
|
||||
/* founder kicks moderator (this triggers two events: user and kick) */
|
||||
fprintf(stderr, "Founder is kicking %s\n", state0->peers[0].name);
|
||||
|
||||
tox_group_mod_kick_peer(tox0, state0->group_number, state0->peers[0].peer_id, &k_err);
|
||||
ck_assert_msg(k_err == TOX_ERR_GROUP_MOD_KICK_PEER_OK, "Failed to kick peer. error: %d", k_err);
|
||||
tox_group_kick_peer(tox0, state0->group_number, state0->peers[0].peer_id, &k_err);
|
||||
ck_assert_msg(k_err == TOX_ERR_GROUP_KICK_PEER_OK, "Failed to kick peer. error: %d", k_err);
|
||||
|
||||
state0->kick_check = true;
|
||||
check_mod_event(autotoxes, NUM_GROUP_TOXES, TOX_GROUP_MOD_EVENT_KICK);
|
||||
@ -619,9 +632,8 @@ static void group_moderation_test(AutoTox *autotoxes)
|
||||
fprintf(stderr, "All peers successfully received kick event\n");
|
||||
|
||||
fprintf(stderr, "Founder is demoting moderator to user\n");
|
||||
|
||||
tox_group_mod_set_role(tox0, state0->group_number, state0->peers[2].peer_id, TOX_GROUP_ROLE_USER, &role_err);
|
||||
ck_assert_msg(role_err == TOX_ERR_GROUP_MOD_SET_ROLE_OK, "Failed to demote peer 3 to User. error: %d", role_err);
|
||||
tox_group_set_role(tox0, state0->group_number, state0->peers[2].peer_id, TOX_GROUP_ROLE_USER, &role_err);
|
||||
ck_assert_msg(role_err == TOX_ERR_GROUP_SET_ROLE_OK, "Failed to demote peer 3 to User. error: %d", role_err);
|
||||
|
||||
state0->user_check = true;
|
||||
++state0->user_event_count;
|
||||
|
@ -26,17 +26,23 @@ typedef struct State {
|
||||
#define PEER0_NICK_LEN (sizeof(PEER0_NICK) -1)
|
||||
#define NEW_USER_STATUS TOX_USER_STATUS_BUSY
|
||||
|
||||
static void group_invite_handler(Tox *tox, uint32_t friend_number, const uint8_t *invite_data, size_t length,
|
||||
const uint8_t *group_name, size_t group_name_length, void *user_data)
|
||||
static void group_invite_handler(const Tox_Event_Group_Invite *event, void *user_data)
|
||||
{
|
||||
AutoTox *autotox = (AutoTox *)user_data;
|
||||
ck_assert(autotox != nullptr);
|
||||
|
||||
const uint32_t friend_number = tox_event_group_invite_get_friend_number(event);
|
||||
const uint8_t *invite_data = tox_event_group_invite_get_invite_data(event);
|
||||
const size_t length = tox_event_group_invite_get_invite_data_length(event);
|
||||
|
||||
Tox_Err_Group_Invite_Accept err_accept;
|
||||
tox_group_invite_accept(tox, friend_number, invite_data, length, (const uint8_t *)"test2", 5,
|
||||
tox_group_invite_accept(autotox->tox, friend_number, invite_data, length, (const uint8_t *)"test2", 5,
|
||||
nullptr, 0, &err_accept);
|
||||
ck_assert(err_accept == TOX_ERR_GROUP_INVITE_ACCEPT_OK);
|
||||
|
||||
}
|
||||
|
||||
static void group_peer_join_handler(Tox *tox, uint32_t group_number, uint32_t peer_id, void *user_data)
|
||||
static void group_peer_join_handler(const Tox_Event_Group_Peer_Join *event, void *user_data)
|
||||
{
|
||||
AutoTox *autotox = (AutoTox *)user_data;
|
||||
ck_assert(autotox != nullptr);
|
||||
@ -52,28 +58,28 @@ static void group_peer_join_handler(Tox *tox, uint32_t group_number, uint32_t pe
|
||||
*/
|
||||
static int has_correct_group_state(const Tox *tox, uint32_t group_number, const uint8_t *expected_chat_id)
|
||||
{
|
||||
Tox_Err_Group_State_Queries query_err;
|
||||
Tox_Err_Group_State_Query query_err;
|
||||
|
||||
Tox_Group_Privacy_State priv_state = tox_group_get_privacy_state(tox, group_number, &query_err);
|
||||
ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERIES_OK);
|
||||
ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERY_OK);
|
||||
|
||||
if (priv_state != NEW_PRIV_STATE) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
size_t pass_len = tox_group_get_password_size(tox, group_number, &query_err);
|
||||
ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERIES_OK);
|
||||
ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERY_OK);
|
||||
|
||||
uint8_t password[TOX_GROUP_MAX_PASSWORD_SIZE];
|
||||
tox_group_get_password(tox, group_number, password, &query_err);
|
||||
ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERIES_OK);
|
||||
ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERY_OK);
|
||||
|
||||
if (pass_len != PASS_LEN || memcmp(password, PASSWORD, pass_len) != 0) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
size_t gname_len = tox_group_get_name_size(tox, group_number, &query_err);
|
||||
ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERIES_OK);
|
||||
ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERY_OK);
|
||||
|
||||
uint8_t group_name[TOX_GROUP_MAX_GROUP_NAME_LENGTH];
|
||||
tox_group_get_name(tox, group_number, group_name, &query_err);
|
||||
@ -87,17 +93,17 @@ static int has_correct_group_state(const Tox *tox, uint32_t group_number, const
|
||||
}
|
||||
|
||||
Tox_Group_Topic_Lock topic_lock = tox_group_get_topic_lock(tox, group_number, &query_err);
|
||||
ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERIES_OK);
|
||||
ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERY_OK);
|
||||
|
||||
if (topic_lock != TOX_GROUP_TOPIC_LOCK_DISABLED) {
|
||||
return -5;
|
||||
}
|
||||
|
||||
Tox_Err_Group_State_Queries id_err;
|
||||
Tox_Err_Group_State_Query id_err;
|
||||
uint8_t chat_id[TOX_GROUP_CHAT_ID_SIZE];
|
||||
tox_group_get_chat_id(tox, group_number, chat_id, &id_err);
|
||||
|
||||
ck_assert(id_err == TOX_ERR_GROUP_STATE_QUERIES_OK);
|
||||
ck_assert(id_err == TOX_ERR_GROUP_STATE_QUERY_OK);
|
||||
|
||||
if (memcmp(chat_id, expected_chat_id, TOX_GROUP_CHAT_ID_SIZE) != 0) {
|
||||
return -6;
|
||||
@ -120,7 +126,7 @@ static int has_correct_self_state(const Tox *tox, uint32_t group_number, const u
|
||||
return -1;
|
||||
}
|
||||
|
||||
TOX_USER_STATUS self_status = tox_group_self_get_status(tox, group_number, &sq_err);
|
||||
Tox_User_Status self_status = tox_group_self_get_status(tox, group_number, &sq_err);
|
||||
ck_assert(sq_err == TOX_ERR_GROUP_SELF_QUERY_OK);
|
||||
|
||||
if (self_status != NEW_USER_STATUS) {
|
||||
@ -151,8 +157,8 @@ static void group_save_test(AutoTox *autotoxes)
|
||||
ck_assert_msg(NUM_GROUP_TOXES > 1, "NUM_GROUP_TOXES is too small: %d", NUM_GROUP_TOXES);
|
||||
|
||||
for (size_t i = 0; i < NUM_GROUP_TOXES; ++i) {
|
||||
tox_callback_group_invite(autotoxes[i].tox, group_invite_handler);
|
||||
tox_callback_group_peer_join(autotoxes[i].tox, group_peer_join_handler);
|
||||
tox_events_callback_group_invite(autotoxes[i].dispatch, group_invite_handler);
|
||||
tox_events_callback_group_peer_join(autotoxes[i].dispatch, group_peer_join_handler);
|
||||
}
|
||||
|
||||
Tox *tox0 = autotoxes[0].tox;
|
||||
@ -168,9 +174,9 @@ static void group_save_test(AutoTox *autotoxes)
|
||||
|
||||
uint8_t chat_id[TOX_GROUP_CHAT_ID_SIZE];
|
||||
|
||||
Tox_Err_Group_State_Queries id_err;
|
||||
Tox_Err_Group_State_Query id_err;
|
||||
tox_group_get_chat_id(tox0, group_number, chat_id, &id_err);
|
||||
ck_assert(id_err == TOX_ERR_GROUP_STATE_QUERIES_OK);
|
||||
ck_assert(id_err == TOX_ERR_GROUP_STATE_QUERY_OK);
|
||||
|
||||
uint8_t founder_pk[TOX_GROUP_PEER_PUBLIC_KEY_SIZE];
|
||||
|
||||
@ -178,7 +184,6 @@ static void group_save_test(AutoTox *autotoxes)
|
||||
tox_group_self_get_public_key(tox0, group_number, founder_pk, &sq_err);
|
||||
ck_assert(sq_err == TOX_ERR_GROUP_SELF_QUERY_OK);
|
||||
|
||||
|
||||
Tox_Err_Group_Invite_Friend err_invite;
|
||||
tox_group_invite_friend(tox0, group_number, 0, &err_invite);
|
||||
|
||||
@ -195,21 +200,21 @@ static void group_save_test(AutoTox *autotoxes)
|
||||
tox_group_set_topic(tox0, group_number, (const uint8_t *)TOPIC, TOPIC_LEN, &top_err);
|
||||
ck_assert(top_err == TOX_ERR_GROUP_TOPIC_SET_OK);
|
||||
|
||||
Tox_Err_Group_Founder_Set_Topic_Lock lock_set_err;
|
||||
tox_group_founder_set_topic_lock(tox0, group_number, TOX_GROUP_TOPIC_LOCK_DISABLED, &lock_set_err);
|
||||
ck_assert(lock_set_err == TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_OK);
|
||||
Tox_Err_Group_Set_Topic_Lock lock_set_err;
|
||||
tox_group_set_topic_lock(tox0, group_number, TOX_GROUP_TOPIC_LOCK_DISABLED, &lock_set_err);
|
||||
ck_assert(lock_set_err == TOX_ERR_GROUP_SET_TOPIC_LOCK_OK);
|
||||
|
||||
Tox_Err_Group_Founder_Set_Privacy_State priv_err;
|
||||
tox_group_founder_set_privacy_state(tox0, group_number, NEW_PRIV_STATE, &priv_err);
|
||||
ck_assert(priv_err == TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_OK);
|
||||
Tox_Err_Group_Set_Privacy_State priv_err;
|
||||
tox_group_set_privacy_state(tox0, group_number, NEW_PRIV_STATE, &priv_err);
|
||||
ck_assert(priv_err == TOX_ERR_GROUP_SET_PRIVACY_STATE_OK);
|
||||
|
||||
Tox_Err_Group_Founder_Set_Password pass_set_err;
|
||||
tox_group_founder_set_password(tox0, group_number, (const uint8_t *)PASSWORD, PASS_LEN, &pass_set_err);
|
||||
ck_assert(pass_set_err == TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_OK);
|
||||
Tox_Err_Group_Set_Password pass_set_err;
|
||||
tox_group_set_password(tox0, group_number, (const uint8_t *)PASSWORD, PASS_LEN, &pass_set_err);
|
||||
ck_assert(pass_set_err == TOX_ERR_GROUP_SET_PASSWORD_OK);
|
||||
|
||||
Tox_Err_Group_Founder_Set_Peer_Limit limit_set_err;
|
||||
tox_group_founder_set_peer_limit(tox0, group_number, PEER_LIMIT, &limit_set_err);
|
||||
ck_assert(limit_set_err == TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_OK);
|
||||
Tox_Err_Group_Set_Peer_Limit limit_set_err;
|
||||
tox_group_set_peer_limit(tox0, group_number, PEER_LIMIT, &limit_set_err);
|
||||
ck_assert(limit_set_err == TOX_ERR_GROUP_SET_PEER_LIMIT_OK);
|
||||
|
||||
// change self state
|
||||
Tox_Err_Group_Self_Name_Set n_err;
|
||||
@ -241,8 +246,8 @@ static void group_save_test(AutoTox *autotoxes)
|
||||
ck_assert(options != nullptr);
|
||||
|
||||
tox_options_set_savedata_type(options, TOX_SAVEDATA_TYPE_TOX_SAVE);
|
||||
|
||||
tox_options_set_savedata_data(options, save, save_length);
|
||||
tox_options_set_experimental_groups_persistence(options, true);
|
||||
|
||||
Tox *new_tox = tox_new_log(options, nullptr, nullptr);
|
||||
|
||||
@ -278,7 +283,11 @@ int main(void)
|
||||
Run_Auto_Options autotest_opts = default_run_auto_options();
|
||||
autotest_opts.graph = GRAPH_COMPLETE;
|
||||
|
||||
run_auto_test(nullptr, NUM_GROUP_TOXES, group_save_test, sizeof(State), &autotest_opts);
|
||||
Tox_Options *opts = tox_options_new(nullptr);
|
||||
ck_assert(opts != nullptr);
|
||||
tox_options_set_experimental_groups_persistence(opts, true);
|
||||
run_auto_test(opts, NUM_GROUP_TOXES, group_save_test, sizeof(State), &autotest_opts);
|
||||
tox_options_free(opts);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -60,66 +60,97 @@ static bool all_group_peers_connected(const AutoTox *autotoxes, uint32_t tox_cou
|
||||
return true;
|
||||
}
|
||||
|
||||
static void group_topic_lock_handler(Tox *tox, uint32_t groupnumber, Tox_Group_Topic_Lock topic_lock,
|
||||
static void group_topic_lock_handler(const Tox_Event_Group_Topic_Lock *event,
|
||||
void *user_data)
|
||||
{
|
||||
Tox_Err_Group_State_Queries err;
|
||||
Tox_Group_Topic_Lock current_topic_lock = tox_group_get_topic_lock(tox, groupnumber, &err);
|
||||
const AutoTox *autotox = (const AutoTox *)user_data;
|
||||
ck_assert(autotox != nullptr);
|
||||
|
||||
ck_assert(err == TOX_ERR_GROUP_STATE_QUERIES_OK);
|
||||
const uint32_t groupnumber = tox_event_group_topic_lock_get_group_number(event);
|
||||
const Tox_Group_Topic_Lock topic_lock = tox_event_group_topic_lock_get_topic_lock(event);
|
||||
|
||||
Tox_Err_Group_State_Query err;
|
||||
Tox_Group_Topic_Lock current_topic_lock = tox_group_get_topic_lock(autotox->tox, groupnumber, &err);
|
||||
|
||||
ck_assert(err == TOX_ERR_GROUP_STATE_QUERY_OK);
|
||||
ck_assert_msg(current_topic_lock == topic_lock, "topic locks don't match in callback: %d %d",
|
||||
topic_lock, current_topic_lock);
|
||||
}
|
||||
|
||||
static void group_voice_state_handler(Tox *tox, uint32_t groupnumber, Tox_Group_Voice_State voice_state,
|
||||
static void group_voice_state_handler(const Tox_Event_Group_Voice_State *event,
|
||||
void *user_data)
|
||||
{
|
||||
Tox_Err_Group_State_Queries err;
|
||||
Tox_Group_Voice_State current_voice_state = tox_group_get_voice_state(tox, groupnumber, &err);
|
||||
const AutoTox *autotox = (const AutoTox *)user_data;
|
||||
ck_assert(autotox != nullptr);
|
||||
|
||||
ck_assert(err == TOX_ERR_GROUP_STATE_QUERIES_OK);
|
||||
const uint32_t groupnumber = tox_event_group_voice_state_get_group_number(event);
|
||||
const Tox_Group_Voice_State voice_state = tox_event_group_voice_state_get_voice_state(event);
|
||||
|
||||
Tox_Err_Group_State_Query err;
|
||||
Tox_Group_Voice_State current_voice_state = tox_group_get_voice_state(autotox->tox, groupnumber, &err);
|
||||
|
||||
ck_assert(err == TOX_ERR_GROUP_STATE_QUERY_OK);
|
||||
ck_assert_msg(current_voice_state == voice_state, "voice states don't match in callback: %d %d",
|
||||
voice_state, current_voice_state);
|
||||
}
|
||||
|
||||
static void group_privacy_state_handler(Tox *tox, uint32_t groupnumber, Tox_Group_Privacy_State privacy_state,
|
||||
static void group_privacy_state_handler(const Tox_Event_Group_Privacy_State *event,
|
||||
void *user_data)
|
||||
{
|
||||
Tox_Err_Group_State_Queries err;
|
||||
Tox_Group_Privacy_State current_pstate = tox_group_get_privacy_state(tox, groupnumber, &err);
|
||||
const AutoTox *autotox = (const AutoTox *)user_data;
|
||||
ck_assert(autotox != nullptr);
|
||||
|
||||
ck_assert(err == TOX_ERR_GROUP_STATE_QUERIES_OK);
|
||||
const uint32_t groupnumber = tox_event_group_privacy_state_get_group_number(event);
|
||||
const Tox_Group_Privacy_State privacy_state = tox_event_group_privacy_state_get_privacy_state(event);
|
||||
|
||||
Tox_Err_Group_State_Query err;
|
||||
Tox_Group_Privacy_State current_pstate = tox_group_get_privacy_state(autotox->tox, groupnumber, &err);
|
||||
|
||||
ck_assert(err == TOX_ERR_GROUP_STATE_QUERY_OK);
|
||||
ck_assert_msg(current_pstate == privacy_state, "privacy states don't match in callback");
|
||||
}
|
||||
|
||||
static void group_peer_limit_handler(Tox *tox, uint32_t groupnumber, uint32_t peer_limit, void *user_data)
|
||||
static void group_peer_limit_handler(const Tox_Event_Group_Peer_Limit *event, void *user_data)
|
||||
{
|
||||
Tox_Err_Group_State_Queries err;
|
||||
uint32_t current_plimit = tox_group_get_peer_limit(tox, groupnumber, &err);
|
||||
const AutoTox *autotox = (const AutoTox *)user_data;
|
||||
ck_assert(autotox != nullptr);
|
||||
|
||||
ck_assert(err == TOX_ERR_GROUP_STATE_QUERIES_OK);
|
||||
const uint32_t groupnumber = tox_event_group_peer_limit_get_group_number(event);
|
||||
const uint32_t peer_limit = tox_event_group_peer_limit_get_peer_limit(event);
|
||||
|
||||
Tox_Err_Group_State_Query err;
|
||||
uint32_t current_plimit = tox_group_get_peer_limit(autotox->tox, groupnumber, &err);
|
||||
|
||||
ck_assert(err == TOX_ERR_GROUP_STATE_QUERY_OK);
|
||||
ck_assert_msg(peer_limit == current_plimit,
|
||||
"Peer limits don't match in callback: %u, %u\n", peer_limit, current_plimit);
|
||||
}
|
||||
|
||||
static void group_password_handler(Tox *tox, uint32_t groupnumber, const uint8_t *password, size_t length,
|
||||
static void group_password_handler(const Tox_Event_Group_Password *event,
|
||||
void *user_data)
|
||||
{
|
||||
Tox_Err_Group_State_Queries err;
|
||||
size_t curr_pwlength = tox_group_get_password_size(tox, groupnumber, &err);
|
||||
AutoTox *autotox = (AutoTox *)user_data;
|
||||
ck_assert(autotox != nullptr);
|
||||
|
||||
ck_assert(err == TOX_ERR_GROUP_STATE_QUERIES_OK);
|
||||
const uint32_t groupnumber = tox_event_group_password_get_group_number(event);
|
||||
const uint8_t *password = tox_event_group_password_get_password(event);
|
||||
const size_t length = tox_event_group_password_get_password_length(event);
|
||||
|
||||
Tox_Err_Group_State_Query err;
|
||||
size_t curr_pwlength = tox_group_get_password_size(autotox->tox, groupnumber, &err);
|
||||
|
||||
ck_assert(err == TOX_ERR_GROUP_STATE_QUERY_OK);
|
||||
ck_assert(length == curr_pwlength);
|
||||
|
||||
uint8_t current_password[TOX_GROUP_MAX_PASSWORD_SIZE];
|
||||
tox_group_get_password(tox, groupnumber, current_password, &err);
|
||||
tox_group_get_password(autotox->tox, groupnumber, current_password, &err);
|
||||
|
||||
ck_assert(err == TOX_ERR_GROUP_STATE_QUERIES_OK);
|
||||
ck_assert(err == TOX_ERR_GROUP_STATE_QUERY_OK);
|
||||
ck_assert_msg(memcmp(current_password, password, length) == 0,
|
||||
"Passwords don't match: %s, %s", password, current_password);
|
||||
}
|
||||
|
||||
static void group_peer_join_handler(Tox *tox, uint32_t group_number, uint32_t peer_id, void *user_data)
|
||||
static void group_peer_join_handler(const Tox_Event_Group_Peer_Join *event, void *user_data)
|
||||
{
|
||||
AutoTox *autotox = (AutoTox *)user_data;
|
||||
ck_assert(autotox != nullptr);
|
||||
@ -137,24 +168,24 @@ static int check_group_state(const Tox *tox, uint32_t groupnumber, uint32_t peer
|
||||
Tox_Group_Privacy_State priv_state, Tox_Group_Voice_State voice_state,
|
||||
const uint8_t *password, size_t pass_len, Tox_Group_Topic_Lock topic_lock)
|
||||
{
|
||||
Tox_Err_Group_State_Queries query_err;
|
||||
Tox_Err_Group_State_Query query_err;
|
||||
|
||||
Tox_Group_Privacy_State my_priv_state = tox_group_get_privacy_state(tox, groupnumber, &query_err);
|
||||
ck_assert_msg(query_err == TOX_ERR_GROUP_STATE_QUERIES_OK, "Failed to get privacy state: %d", query_err);
|
||||
ck_assert_msg(query_err == TOX_ERR_GROUP_STATE_QUERY_OK, "Failed to get privacy state: %d", query_err);
|
||||
|
||||
if (my_priv_state != priv_state) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint32_t my_peer_limit = tox_group_get_peer_limit(tox, groupnumber, &query_err);
|
||||
ck_assert_msg(query_err == TOX_ERR_GROUP_STATE_QUERIES_OK, "Failed to get peer limit: %d", query_err);
|
||||
ck_assert_msg(query_err == TOX_ERR_GROUP_STATE_QUERY_OK, "Failed to get peer limit: %d", query_err);
|
||||
|
||||
if (my_peer_limit != peer_limit) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
size_t my_pass_len = tox_group_get_password_size(tox, groupnumber, &query_err);
|
||||
ck_assert_msg(query_err == TOX_ERR_GROUP_STATE_QUERIES_OK, "Failed to get password size: %d", query_err);
|
||||
ck_assert_msg(query_err == TOX_ERR_GROUP_STATE_QUERY_OK, "Failed to get password size: %d", query_err);
|
||||
|
||||
if (my_pass_len != pass_len) {
|
||||
return -5;
|
||||
@ -163,10 +194,10 @@ static int check_group_state(const Tox *tox, uint32_t groupnumber, uint32_t peer
|
||||
if (password != nullptr && my_pass_len > 0) {
|
||||
ck_assert(my_pass_len <= TOX_GROUP_MAX_PASSWORD_SIZE);
|
||||
|
||||
uint8_t my_pass[TOX_GROUP_MAX_PASSWORD_SIZE];
|
||||
uint8_t my_pass[TOX_GROUP_MAX_PASSWORD_SIZE + 1];
|
||||
tox_group_get_password(tox, groupnumber, my_pass, &query_err);
|
||||
my_pass[my_pass_len] = 0;
|
||||
ck_assert_msg(query_err == TOX_ERR_GROUP_STATE_QUERIES_OK, "Failed to get password: %d", query_err);
|
||||
ck_assert_msg(query_err == TOX_ERR_GROUP_STATE_QUERY_OK, "Failed to get password: %d", query_err);
|
||||
|
||||
if (memcmp(my_pass, password, my_pass_len) != 0) {
|
||||
return -6;
|
||||
@ -175,7 +206,7 @@ static int check_group_state(const Tox *tox, uint32_t groupnumber, uint32_t peer
|
||||
|
||||
/* Group name should never change */
|
||||
size_t my_gname_len = tox_group_get_name_size(tox, groupnumber, &query_err);
|
||||
ck_assert_msg(query_err == TOX_ERR_GROUP_STATE_QUERIES_OK, "Failed to get group name size: %d", query_err);
|
||||
ck_assert_msg(query_err == TOX_ERR_GROUP_STATE_QUERY_OK, "Failed to get group name size: %d", query_err);
|
||||
|
||||
if (my_gname_len != GROUP_NAME_LEN) {
|
||||
return -7;
|
||||
@ -183,7 +214,7 @@ static int check_group_state(const Tox *tox, uint32_t groupnumber, uint32_t peer
|
||||
|
||||
ck_assert(my_gname_len <= TOX_GROUP_MAX_GROUP_NAME_LENGTH);
|
||||
|
||||
uint8_t my_gname[TOX_GROUP_MAX_GROUP_NAME_LENGTH];
|
||||
uint8_t my_gname[TOX_GROUP_MAX_GROUP_NAME_LENGTH + 1];
|
||||
tox_group_get_name(tox, groupnumber, my_gname, &query_err);
|
||||
my_gname[my_gname_len] = 0;
|
||||
|
||||
@ -192,14 +223,14 @@ static int check_group_state(const Tox *tox, uint32_t groupnumber, uint32_t peer
|
||||
}
|
||||
|
||||
Tox_Group_Topic_Lock current_topic_lock = tox_group_get_topic_lock(tox, groupnumber, &query_err);
|
||||
ck_assert_msg(query_err == TOX_ERR_GROUP_STATE_QUERIES_OK, "Failed to get topic lock: %d", query_err);
|
||||
ck_assert_msg(query_err == TOX_ERR_GROUP_STATE_QUERY_OK, "Failed to get topic lock: %d", query_err);
|
||||
|
||||
if (current_topic_lock != topic_lock) {
|
||||
return -9;
|
||||
}
|
||||
|
||||
Tox_Group_Voice_State current_voice_state = tox_group_get_voice_state(tox, groupnumber, &query_err);
|
||||
ck_assert_msg(query_err == TOX_ERR_GROUP_STATE_QUERIES_OK, "Failed to get voice state: %d", query_err);
|
||||
ck_assert_msg(query_err == TOX_ERR_GROUP_STATE_QUERY_OK, "Failed to get voice state: %d", query_err);
|
||||
|
||||
if (current_voice_state != voice_state) {
|
||||
return -10;
|
||||
@ -213,26 +244,26 @@ static void set_group_state(Tox *tox, uint32_t groupnumber, uint32_t peer_limit,
|
||||
Tox_Group_Topic_Lock topic_lock)
|
||||
{
|
||||
|
||||
Tox_Err_Group_Founder_Set_Peer_Limit limit_set_err;
|
||||
tox_group_founder_set_peer_limit(tox, groupnumber, peer_limit, &limit_set_err);
|
||||
ck_assert_msg(limit_set_err == TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_OK, "failed to set peer limit: %d", limit_set_err);
|
||||
Tox_Err_Group_Set_Peer_Limit limit_set_err;
|
||||
tox_group_set_peer_limit(tox, groupnumber, peer_limit, &limit_set_err);
|
||||
ck_assert_msg(limit_set_err == TOX_ERR_GROUP_SET_PEER_LIMIT_OK, "failed to set peer limit: %d", limit_set_err);
|
||||
|
||||
Tox_Err_Group_Founder_Set_Privacy_State priv_err;
|
||||
tox_group_founder_set_privacy_state(tox, groupnumber, priv_state, &priv_err);
|
||||
ck_assert_msg(priv_err == TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_OK, "failed to set privacy state: %d", priv_err);
|
||||
Tox_Err_Group_Set_Privacy_State priv_err;
|
||||
tox_group_set_privacy_state(tox, groupnumber, priv_state, &priv_err);
|
||||
ck_assert_msg(priv_err == TOX_ERR_GROUP_SET_PRIVACY_STATE_OK, "failed to set privacy state: %d", priv_err);
|
||||
|
||||
Tox_Err_Group_Founder_Set_Password pass_set_err;
|
||||
tox_group_founder_set_password(tox, groupnumber, password, pass_len, &pass_set_err);
|
||||
ck_assert_msg(pass_set_err == TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_OK, "failed to set password: %d", pass_set_err);
|
||||
Tox_Err_Group_Set_Password pass_set_err;
|
||||
tox_group_set_password(tox, groupnumber, password, pass_len, &pass_set_err);
|
||||
ck_assert_msg(pass_set_err == TOX_ERR_GROUP_SET_PASSWORD_OK, "failed to set password: %d", pass_set_err);
|
||||
|
||||
Tox_Err_Group_Founder_Set_Topic_Lock lock_set_err;
|
||||
tox_group_founder_set_topic_lock(tox, groupnumber, topic_lock, &lock_set_err);
|
||||
ck_assert_msg(lock_set_err == TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_OK, "failed to set topic lock: %d",
|
||||
Tox_Err_Group_Set_Topic_Lock lock_set_err;
|
||||
tox_group_set_topic_lock(tox, groupnumber, topic_lock, &lock_set_err);
|
||||
ck_assert_msg(lock_set_err == TOX_ERR_GROUP_SET_TOPIC_LOCK_OK, "failed to set topic lock: %d",
|
||||
lock_set_err);
|
||||
|
||||
Tox_Err_Group_Founder_Set_Voice_State voice_set_err;
|
||||
tox_group_founder_set_voice_state(tox, groupnumber, voice_state, &voice_set_err);
|
||||
ck_assert_msg(voice_set_err == TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_OK, "failed to set voice state: %d",
|
||||
Tox_Err_Group_Set_Voice_State voice_set_err;
|
||||
tox_group_set_voice_state(tox, groupnumber, voice_state, &voice_set_err);
|
||||
ck_assert_msg(voice_set_err == TOX_ERR_GROUP_SET_VOICE_STATE_OK, "failed to set voice state: %d",
|
||||
voice_set_err);
|
||||
}
|
||||
|
||||
@ -241,12 +272,12 @@ static void group_state_test(AutoTox *autotoxes)
|
||||
ck_assert_msg(NUM_GROUP_TOXES >= 3, "NUM_GROUP_TOXES is too small: %d", NUM_GROUP_TOXES);
|
||||
|
||||
for (size_t i = 0; i < NUM_GROUP_TOXES; ++i) {
|
||||
tox_callback_group_privacy_state(autotoxes[i].tox, group_privacy_state_handler);
|
||||
tox_callback_group_peer_limit(autotoxes[i].tox, group_peer_limit_handler);
|
||||
tox_callback_group_password(autotoxes[i].tox, group_password_handler);
|
||||
tox_callback_group_peer_join(autotoxes[i].tox, group_peer_join_handler);
|
||||
tox_callback_group_voice_state(autotoxes[i].tox, group_voice_state_handler);
|
||||
tox_callback_group_topic_lock(autotoxes[i].tox, group_topic_lock_handler);
|
||||
tox_events_callback_group_privacy_state(autotoxes[i].dispatch, group_privacy_state_handler);
|
||||
tox_events_callback_group_peer_limit(autotoxes[i].dispatch, group_peer_limit_handler);
|
||||
tox_events_callback_group_password(autotoxes[i].dispatch, group_password_handler);
|
||||
tox_events_callback_group_peer_join(autotoxes[i].dispatch, group_peer_join_handler);
|
||||
tox_events_callback_group_voice_state(autotoxes[i].dispatch, group_voice_state_handler);
|
||||
tox_events_callback_group_topic_lock(autotoxes[i].dispatch, group_topic_lock_handler);
|
||||
}
|
||||
|
||||
Tox *tox0 = autotoxes[0].tox;
|
||||
@ -263,11 +294,11 @@ static void group_state_test(AutoTox *autotoxes)
|
||||
(const uint8_t *)PASSWORD, PASS_LEN, TOX_GROUP_TOPIC_LOCK_ENABLED);
|
||||
|
||||
/* Founder gets the Chat ID and implicitly shares it publicly */
|
||||
Tox_Err_Group_State_Queries id_err;
|
||||
Tox_Err_Group_State_Query id_err;
|
||||
uint8_t chat_id[TOX_GROUP_CHAT_ID_SIZE];
|
||||
tox_group_get_chat_id(tox0, groupnum, chat_id, &id_err);
|
||||
|
||||
ck_assert_msg(id_err == TOX_ERR_GROUP_STATE_QUERIES_OK, "tox_group_get_chat_id failed %d", id_err);
|
||||
ck_assert_msg(id_err == TOX_ERR_GROUP_STATE_QUERY_OK, "tox_group_get_chat_id failed %d", id_err);
|
||||
|
||||
/* All other peers join the group using the Chat ID and password */
|
||||
for (size_t i = 1; i < NUM_GROUP_TOXES; ++i) {
|
||||
|
@ -96,38 +96,42 @@ static void peers_cleanup(Peers *peers)
|
||||
free(peers);
|
||||
}
|
||||
|
||||
static void group_peer_join_handler(Tox *tox, uint32_t group_number, uint32_t peer_id, void *user_data)
|
||||
static void group_peer_join_handler(const Tox_Event_Group_Peer_Join *event, void *user_data)
|
||||
{
|
||||
AutoTox *autotox = (AutoTox *)user_data;
|
||||
ck_assert(autotox != nullptr);
|
||||
|
||||
State *state = (State *)autotox->state;
|
||||
|
||||
const uint32_t peer_id = tox_event_group_peer_join_get_peer_id(event);
|
||||
|
||||
ck_assert(add_peer(state->peers, peer_id) == 0);
|
||||
|
||||
}
|
||||
|
||||
static void group_peer_exit_handler(Tox *tox, uint32_t groupnumber, uint32_t peer_id, Tox_Group_Exit_Type exit_type,
|
||||
const uint8_t *name, size_t name_length, const uint8_t *part_message,
|
||||
size_t length, void *user_data)
|
||||
static void group_peer_exit_handler(const Tox_Event_Group_Peer_Exit *event, void *user_data)
|
||||
{
|
||||
AutoTox *autotox = (AutoTox *)user_data;
|
||||
ck_assert(autotox != nullptr);
|
||||
|
||||
State *state = (State *)autotox->state;
|
||||
|
||||
const uint32_t peer_id = tox_event_group_peer_exit_get_peer_id(event);
|
||||
|
||||
ck_assert(del_peer(state->peers, peer_id) == 0);
|
||||
|
||||
}
|
||||
|
||||
static void group_topic_handler(Tox *tox, uint32_t groupnumber, uint32_t peer_id, const uint8_t *topic,
|
||||
size_t length, void *user_data)
|
||||
static void group_topic_handler(const Tox_Event_Group_Topic *event, void *user_data)
|
||||
{
|
||||
AutoTox *autotox = (AutoTox *)user_data;
|
||||
ck_assert(autotox != nullptr);
|
||||
|
||||
State *state = (State *)autotox->state;
|
||||
|
||||
const uint8_t *topic = tox_event_group_topic_get_topic(event);
|
||||
const size_t length = tox_event_group_topic_get_topic_length(event);
|
||||
|
||||
ck_assert(length <= TOX_GROUP_MAX_TOPIC_LENGTH);
|
||||
|
||||
memcpy(state->callback_topic, (const char *)topic, length);
|
||||
@ -201,7 +205,7 @@ static void role_spam(const Random *rng, AutoTox *autotoxes, uint32_t num_peers,
|
||||
int64_t peer_id = state0->peers->peer_ids[idx];
|
||||
|
||||
if (peer_id >= 0) {
|
||||
tox_group_mod_set_role(tox0, groupnumber, (uint32_t)peer_id, f_role, nullptr);
|
||||
tox_group_set_role(tox0, groupnumber, (uint32_t)peer_id, f_role, nullptr);
|
||||
}
|
||||
|
||||
// mods randomly promote or demote one of the non-mods
|
||||
@ -218,7 +222,7 @@ static void role_spam(const Random *rng, AutoTox *autotoxes, uint32_t num_peers,
|
||||
peer_id = state_j->peers->peer_ids[i];
|
||||
|
||||
if (peer_id >= 0) {
|
||||
tox_group_mod_set_role(autotoxes[j].tox, groupnumber, (uint32_t)peer_id, role, nullptr);
|
||||
tox_group_set_role(autotoxes[j].tox, groupnumber, (uint32_t)peer_id, role, nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -260,14 +264,14 @@ static bool all_peers_have_same_topic(const AutoTox *autotoxes, uint32_t num_pee
|
||||
{
|
||||
uint8_t expected_topic[TOX_GROUP_MAX_TOPIC_LENGTH];
|
||||
|
||||
Tox_Err_Group_State_Queries query_err;
|
||||
Tox_Err_Group_State_Query query_err;
|
||||
size_t expected_topic_length = tox_group_get_topic_size(autotoxes[0].tox, groupnumber, &query_err);
|
||||
|
||||
ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERIES_OK);
|
||||
ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERY_OK);
|
||||
|
||||
tox_group_get_topic(autotoxes[0].tox, groupnumber, expected_topic, &query_err);
|
||||
|
||||
ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERIES_OK);
|
||||
ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERY_OK);
|
||||
|
||||
const State *state0 = (const State *)autotoxes[0].state;
|
||||
|
||||
@ -282,7 +286,7 @@ static bool all_peers_have_same_topic(const AutoTox *autotoxes, uint32_t num_pee
|
||||
for (size_t i = 1; i < num_peers; ++i) {
|
||||
size_t topic_length = tox_group_get_topic_size(autotoxes[i].tox, groupnumber, &query_err);
|
||||
|
||||
ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERIES_OK);
|
||||
ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERY_OK);
|
||||
|
||||
if (topic_length != expected_topic_length) {
|
||||
return false;
|
||||
@ -291,7 +295,7 @@ static bool all_peers_have_same_topic(const AutoTox *autotoxes, uint32_t num_pee
|
||||
uint8_t topic[TOX_GROUP_MAX_TOPIC_LENGTH];
|
||||
tox_group_get_topic(autotoxes[i].tox, groupnumber, topic, &query_err);
|
||||
|
||||
ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERIES_OK);
|
||||
ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERY_OK);
|
||||
|
||||
if (memcmp(expected_topic, (const char *)topic, topic_length) != 0) {
|
||||
return false;
|
||||
@ -331,13 +335,13 @@ static void topic_spam(const Random *rng, AutoTox *autotoxes, uint32_t num_peers
|
||||
static void group_sync_test(AutoTox *autotoxes)
|
||||
{
|
||||
ck_assert(NUM_GROUP_TOXES >= 5);
|
||||
const Random *rng = system_random();
|
||||
const Random *rng = os_random();
|
||||
ck_assert(rng != nullptr);
|
||||
|
||||
for (size_t i = 0; i < NUM_GROUP_TOXES; ++i) {
|
||||
tox_callback_group_peer_join(autotoxes[i].tox, group_peer_join_handler);
|
||||
tox_callback_group_topic(autotoxes[i].tox, group_topic_handler);
|
||||
tox_callback_group_peer_exit(autotoxes[i].tox, group_peer_exit_handler);
|
||||
tox_events_callback_group_peer_join(autotoxes[i].dispatch, group_peer_join_handler);
|
||||
tox_events_callback_group_topic(autotoxes[i].dispatch, group_topic_handler);
|
||||
tox_events_callback_group_peer_exit(autotoxes[i].dispatch, group_peer_exit_handler);
|
||||
|
||||
State *state = (State *)autotoxes[i].state;
|
||||
state->peers = (Peers *)calloc(1, sizeof(Peers));
|
||||
@ -356,11 +360,11 @@ static void group_sync_test(AutoTox *autotoxes)
|
||||
|
||||
fprintf(stderr, "tox0 creats new group and invites all his friends");
|
||||
|
||||
Tox_Err_Group_State_Queries id_err;
|
||||
Tox_Err_Group_State_Query id_err;
|
||||
uint8_t chat_id[TOX_GROUP_CHAT_ID_SIZE];
|
||||
|
||||
tox_group_get_chat_id(tox0, groupnumber, chat_id, &id_err);
|
||||
ck_assert_msg(id_err == TOX_ERR_GROUP_STATE_QUERIES_OK, "%d", id_err);
|
||||
ck_assert_msg(id_err == TOX_ERR_GROUP_STATE_QUERY_OK, "%d", id_err);
|
||||
|
||||
for (size_t i = 1; i < NUM_GROUP_TOXES; ++i) {
|
||||
Tox_Err_Group_Join join_err;
|
||||
@ -375,9 +379,9 @@ static void group_sync_test(AutoTox *autotoxes)
|
||||
|
||||
fprintf(stderr, "%d peers joined the group\n", NUM_GROUP_TOXES);
|
||||
|
||||
Tox_Err_Group_Founder_Set_Topic_Lock lock_set_err;
|
||||
tox_group_founder_set_topic_lock(tox0, groupnumber, TOX_GROUP_TOPIC_LOCK_DISABLED, &lock_set_err);
|
||||
ck_assert_msg(lock_set_err == TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_OK, "failed to disable topic lock: %d",
|
||||
Tox_Err_Group_Set_Topic_Lock lock_set_err;
|
||||
tox_group_set_topic_lock(tox0, groupnumber, TOX_GROUP_TOPIC_LOCK_DISABLED, &lock_set_err);
|
||||
ck_assert_msg(lock_set_err == TOX_ERR_GROUP_SET_TOPIC_LOCK_OK, "failed to disable topic lock: %d",
|
||||
lock_set_err);
|
||||
|
||||
iterate_all_wait(autotoxes, NUM_GROUP_TOXES, ITERATION_INTERVAL);
|
||||
@ -388,8 +392,8 @@ static void group_sync_test(AutoTox *autotoxes)
|
||||
|
||||
iterate_all_wait(autotoxes, NUM_GROUP_TOXES, ITERATION_INTERVAL);
|
||||
|
||||
tox_group_founder_set_topic_lock(tox0, groupnumber, TOX_GROUP_TOPIC_LOCK_ENABLED, &lock_set_err);
|
||||
ck_assert_msg(lock_set_err == TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_OK, "failed to enable topic lock: %d",
|
||||
tox_group_set_topic_lock(tox0, groupnumber, TOX_GROUP_TOPIC_LOCK_ENABLED, &lock_set_err);
|
||||
ck_assert_msg(lock_set_err == TOX_ERR_GROUP_SET_TOPIC_LOCK_OK, "failed to enable topic lock: %d",
|
||||
lock_set_err);
|
||||
|
||||
do {
|
||||
@ -398,12 +402,12 @@ static void group_sync_test(AutoTox *autotoxes)
|
||||
&& !all_peers_see_same_roles(autotoxes, NUM_GROUP_TOXES, groupnumber)
|
||||
&& state0->peers->num_peers != NUM_GROUP_TOXES - 1);
|
||||
|
||||
Tox_Err_Group_Mod_Set_Role role_err;
|
||||
Tox_Err_Group_Set_Role role_err;
|
||||
|
||||
for (size_t i = 0; i < state0->peers->num_peers; ++i) {
|
||||
tox_group_mod_set_role(tox0, groupnumber, (uint32_t)state0->peers->peer_ids[i], TOX_GROUP_ROLE_MODERATOR,
|
||||
&role_err);
|
||||
ck_assert_msg(role_err == TOX_ERR_GROUP_MOD_SET_ROLE_OK, "Failed to set moderator. error: %d", role_err);
|
||||
tox_group_set_role(tox0, groupnumber, (uint32_t)state0->peers->peer_ids[i], TOX_GROUP_ROLE_MODERATOR,
|
||||
&role_err);
|
||||
ck_assert_msg(role_err == TOX_ERR_GROUP_SET_ROLE_OK, "Failed to set moderator. error: %d", role_err);
|
||||
}
|
||||
|
||||
fprintf(stderr, "founder enabled topic lock and set all peers to moderator role\n");
|
||||
@ -419,9 +423,9 @@ static void group_sync_test(AutoTox *autotoxes)
|
||||
fprintf(stderr, "founder demoting %u moderators to user\n", num_demoted);
|
||||
|
||||
for (size_t i = 0; i < num_demoted; ++i) {
|
||||
tox_group_mod_set_role(tox0, groupnumber, (uint32_t)state0->peers->peer_ids[i], TOX_GROUP_ROLE_USER,
|
||||
&role_err);
|
||||
ck_assert_msg(role_err == TOX_ERR_GROUP_MOD_SET_ROLE_OK, "Failed to set user. error: %d", role_err);
|
||||
tox_group_set_role(tox0, groupnumber, (uint32_t)state0->peers->peer_ids[i], TOX_GROUP_ROLE_USER,
|
||||
&role_err);
|
||||
ck_assert_msg(role_err == TOX_ERR_GROUP_SET_ROLE_OK, "Failed to set user. error: %d", role_err);
|
||||
}
|
||||
|
||||
do {
|
||||
|
@ -19,32 +19,43 @@ typedef struct State {
|
||||
uint32_t peer_id[NUM_GROUP_TOXES - 1];
|
||||
} State;
|
||||
|
||||
static void group_invite_handler(Tox *tox, uint32_t friend_number, const uint8_t *invite_data, size_t length,
|
||||
const uint8_t *group_name, size_t group_name_length, void *user_data)
|
||||
static void group_invite_handler(const Tox_Event_Group_Invite *event, void *user_data)
|
||||
{
|
||||
AutoTox *autotox = (AutoTox *)user_data;
|
||||
ck_assert(autotox != nullptr);
|
||||
|
||||
const uint32_t friend_number = tox_event_group_invite_get_friend_number(event);
|
||||
const uint8_t *invite_data = tox_event_group_invite_get_invite_data(event);
|
||||
const size_t length = tox_event_group_invite_get_invite_data_length(event);
|
||||
|
||||
printf("Accepting friend invite\n");
|
||||
|
||||
Tox_Err_Group_Invite_Accept err_accept;
|
||||
tox_group_invite_accept(tox, friend_number, invite_data, length, (const uint8_t *)"test", 4,
|
||||
tox_group_invite_accept(autotox->tox, friend_number, invite_data, length, (const uint8_t *)"test", 4,
|
||||
nullptr, 0, &err_accept);
|
||||
ck_assert(err_accept == TOX_ERR_GROUP_INVITE_ACCEPT_OK);
|
||||
}
|
||||
|
||||
static void group_peer_join_handler(Tox *tox, uint32_t groupnumber, uint32_t peer_id, void *user_data)
|
||||
static void group_peer_join_handler(const Tox_Event_Group_Peer_Join *event, void *user_data)
|
||||
{
|
||||
AutoTox *autotox = (AutoTox *)user_data;
|
||||
ck_assert(autotox != nullptr);
|
||||
|
||||
State *state = (State *)autotox->state;
|
||||
|
||||
const uint32_t peer_id = tox_event_group_peer_join_get_peer_id(event);
|
||||
|
||||
fprintf(stderr, "joined: %zu, %u\n", state->num_peers, peer_id);
|
||||
ck_assert_msg(state->num_peers < NUM_GROUP_TOXES - 1, "%zu", state->num_peers);
|
||||
|
||||
state->peer_id[state->num_peers++] = peer_id;
|
||||
}
|
||||
|
||||
static void group_private_message_handler(Tox *tox, uint32_t groupnumber, uint32_t peer_id, TOX_MESSAGE_TYPE type,
|
||||
const uint8_t *message, size_t length, void *user_data)
|
||||
static void group_private_message_handler(const Tox_Event_Group_Private_Message *event, void *user_data)
|
||||
{
|
||||
const uint8_t *message = tox_event_group_private_message_get_message(event);
|
||||
const size_t length = tox_event_group_private_message_get_message_length(event);
|
||||
|
||||
AutoTox *autotox = (AutoTox *)user_data;
|
||||
ck_assert(autotox != nullptr);
|
||||
|
||||
@ -58,9 +69,11 @@ static void group_private_message_handler(Tox *tox, uint32_t groupnumber, uint32
|
||||
state->got_code = true;
|
||||
}
|
||||
|
||||
static void group_message_handler(Tox *tox, uint32_t groupnumber, uint32_t peer_id, TOX_MESSAGE_TYPE type,
|
||||
const uint8_t *message, size_t length, uint32_t message_id, void *user_data)
|
||||
static void group_message_handler(const Tox_Event_Group_Message *event, void *user_data)
|
||||
{
|
||||
const uint8_t *message = tox_event_group_message_get_message(event);
|
||||
const size_t length = tox_event_group_message_get_message_length(event);
|
||||
|
||||
AutoTox *autotox = (AutoTox *)user_data;
|
||||
ck_assert(autotox != nullptr);
|
||||
|
||||
@ -133,12 +146,12 @@ static void group_tcp_test(AutoTox *autotoxes)
|
||||
State *state1 = (State *)autotoxes[1].state;
|
||||
|
||||
for (size_t i = 0; i < NUM_GROUP_TOXES; ++i) {
|
||||
tox_callback_group_peer_join(autotoxes[i].tox, group_peer_join_handler);
|
||||
tox_callback_group_private_message(autotoxes[i].tox, group_private_message_handler);
|
||||
tox_events_callback_group_peer_join(autotoxes[i].dispatch, group_peer_join_handler);
|
||||
tox_events_callback_group_private_message(autotoxes[i].dispatch, group_private_message_handler);
|
||||
}
|
||||
|
||||
tox_callback_group_message(autotoxes[1].tox, group_message_handler);
|
||||
tox_callback_group_invite(autotoxes[1].tox, group_invite_handler);
|
||||
tox_events_callback_group_message(autotoxes[1].dispatch, group_message_handler);
|
||||
tox_events_callback_group_invite(autotoxes[1].dispatch, group_invite_handler);
|
||||
|
||||
Tox_Err_Group_New new_err;
|
||||
uint32_t groupnumber = tox_group_new(autotoxes[0].tox, TOX_GROUP_PRIVACY_STATE_PUBLIC, (const uint8_t *)"test", 4,
|
||||
@ -147,11 +160,11 @@ static void group_tcp_test(AutoTox *autotoxes)
|
||||
|
||||
iterate_group(autotoxes, NUM_GROUP_TOXES, GROUP_ITERATION_INTERVAL);
|
||||
|
||||
Tox_Err_Group_State_Queries id_err;
|
||||
Tox_Err_Group_State_Query id_err;
|
||||
uint8_t chat_id[TOX_GROUP_CHAT_ID_SIZE];
|
||||
|
||||
tox_group_get_chat_id(autotoxes[0].tox, groupnumber, chat_id, &id_err);
|
||||
ck_assert_msg(id_err == TOX_ERR_GROUP_STATE_QUERIES_OK, "%d", id_err);
|
||||
ck_assert_msg(id_err == TOX_ERR_GROUP_STATE_QUERY_OK, "%d", id_err);
|
||||
|
||||
printf("Tox 0 created new group...\n");
|
||||
|
||||
@ -168,7 +181,6 @@ static void group_tcp_test(AutoTox *autotoxes)
|
||||
printf("%d peers successfully joined. Waiting for code...\n", NUM_GROUP_TOXES);
|
||||
printf("Tox 0 sending secret code to all peers\n");
|
||||
|
||||
|
||||
for (size_t i = 0; i < NUM_GROUP_TOXES - 1; ++i) {
|
||||
|
||||
Tox_Err_Group_Send_Private_Message perr;
|
||||
|
@ -55,8 +55,11 @@ static bool all_group_peers_connected(const AutoTox *autotoxes, uint32_t tox_cou
|
||||
return true;
|
||||
}
|
||||
|
||||
static void group_peer_join_handler(Tox *tox, uint32_t groupnumber, uint32_t peer_id, void *user_data)
|
||||
static void group_peer_join_handler(const Tox_Event_Group_Peer_Join *event, void *user_data)
|
||||
{
|
||||
//const uint32_t group_number = tox_event_group_peer_join_get_group_number(event);
|
||||
const uint32_t peer_id = tox_event_group_peer_join_get_peer_id(event);
|
||||
|
||||
AutoTox *autotox = (AutoTox *)user_data;
|
||||
ck_assert(autotox != nullptr);
|
||||
|
||||
@ -65,28 +68,41 @@ static void group_peer_join_handler(Tox *tox, uint32_t groupnumber, uint32_t pee
|
||||
state->peer_id = peer_id;
|
||||
}
|
||||
|
||||
static void group_topic_handler(Tox *tox, uint32_t groupnumber, uint32_t peer_id, const uint8_t *topic,
|
||||
size_t length, void *user_data)
|
||||
static void group_topic_handler(const Tox_Event_Group_Topic *event, void *user_data)
|
||||
{
|
||||
ck_assert(length <= TOX_GROUP_MAX_TOPIC_LENGTH);
|
||||
AutoTox *autotox = (AutoTox *)user_data;
|
||||
ck_assert(autotox != nullptr);
|
||||
|
||||
Tox_Err_Group_State_Queries query_err;
|
||||
const uint32_t group_number = tox_event_group_topic_get_group_number(event);
|
||||
//const uint32_t peer_id = tox_event_group_topic_get_peer_id(event);
|
||||
const uint8_t *topic = tox_event_group_topic_get_topic(event);
|
||||
const uint32_t topic_length = tox_event_group_topic_get_topic_length(event);
|
||||
|
||||
ck_assert(topic_length <= TOX_GROUP_MAX_TOPIC_LENGTH);
|
||||
|
||||
Tox_Err_Group_State_Query query_err;
|
||||
uint8_t topic2[TOX_GROUP_MAX_TOPIC_LENGTH];
|
||||
tox_group_get_topic(tox, groupnumber, topic2, &query_err);
|
||||
ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERIES_OK);
|
||||
tox_group_get_topic(autotox->tox, group_number, topic2, &query_err);
|
||||
ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERY_OK);
|
||||
|
||||
size_t topic_length = tox_group_get_topic_size(tox, groupnumber, &query_err);
|
||||
ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERIES_OK);
|
||||
ck_assert_msg(topic_length == length && memcmp(topic, topic2, length) == 0,
|
||||
size_t topic_length_getter = tox_group_get_topic_size(autotox->tox, group_number, &query_err);
|
||||
ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERY_OK);
|
||||
ck_assert_msg(topic_length_getter == topic_length && memcmp(topic, topic2, topic_length) == 0,
|
||||
"topic differs in callback: %s, %s", topic, topic2);
|
||||
}
|
||||
|
||||
static void group_topic_lock_handler(Tox *tox, uint32_t groupnumber, Tox_Group_Topic_Lock topic_lock, void *user_data)
|
||||
static void group_topic_lock_handler(const Tox_Event_Group_Topic_Lock *event, void *user_data)
|
||||
{
|
||||
Tox_Err_Group_State_Queries err;
|
||||
Tox_Group_Topic_Lock current_lock = tox_group_get_topic_lock(tox, groupnumber, &err);
|
||||
const AutoTox *autotox = (const AutoTox *)user_data;
|
||||
ck_assert(autotox != nullptr);
|
||||
|
||||
ck_assert(err == TOX_ERR_GROUP_STATE_QUERIES_OK);
|
||||
const uint32_t group_number = tox_event_group_topic_lock_get_group_number(event);
|
||||
const Tox_Group_Topic_Lock topic_lock = tox_event_group_topic_lock_get_topic_lock(event);
|
||||
|
||||
Tox_Err_Group_State_Query err;
|
||||
Tox_Group_Topic_Lock current_lock = tox_group_get_topic_lock(autotox->tox, group_number, &err);
|
||||
|
||||
ck_assert(err == TOX_ERR_GROUP_STATE_QUERY_OK);
|
||||
ck_assert_msg(topic_lock == current_lock, "topic locks differ in callback");
|
||||
}
|
||||
|
||||
@ -107,10 +123,10 @@ static bool set_topic(Tox *tox, uint32_t groupnumber, const char *topic, size_t
|
||||
*/
|
||||
static int check_topic(const Tox *tox, uint32_t groupnumber, const char *expected_topic, size_t expected_length)
|
||||
{
|
||||
Tox_Err_Group_State_Queries query_err;
|
||||
Tox_Err_Group_State_Query query_err;
|
||||
size_t topic_length = tox_group_get_topic_size(tox, groupnumber, &query_err);
|
||||
|
||||
if (query_err != TOX_ERR_GROUP_STATE_QUERIES_OK) {
|
||||
if (query_err != TOX_ERR_GROUP_STATE_QUERY_OK) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -121,7 +137,7 @@ static int check_topic(const Tox *tox, uint32_t groupnumber, const char *expecte
|
||||
uint8_t topic[TOX_GROUP_MAX_TOPIC_LENGTH];
|
||||
tox_group_get_topic(tox, groupnumber, topic, &query_err);
|
||||
|
||||
if (query_err != TOX_ERR_GROUP_STATE_QUERIES_OK) {
|
||||
if (query_err != TOX_ERR_GROUP_STATE_QUERY_OK) {
|
||||
return -3;
|
||||
}
|
||||
|
||||
@ -140,9 +156,9 @@ static void wait_topic_lock(AutoTox *autotoxes, uint32_t groupnumber, Tox_Group_
|
||||
uint32_t count = 0;
|
||||
|
||||
for (size_t i = 0; i < NUM_GROUP_TOXES; ++i) {
|
||||
Tox_Err_Group_State_Queries err;
|
||||
Tox_Err_Group_State_Query err;
|
||||
Tox_Group_Topic_Lock topic_lock = tox_group_get_topic_lock(autotoxes[i].tox, groupnumber, &err);
|
||||
ck_assert(err == TOX_ERR_GROUP_STATE_QUERIES_OK);
|
||||
ck_assert(err == TOX_ERR_GROUP_STATE_QUERY_OK);
|
||||
|
||||
if (topic_lock == expected_lock) {
|
||||
++count;
|
||||
@ -205,17 +221,18 @@ static void group_topic_test(AutoTox *autotoxes)
|
||||
{
|
||||
ck_assert_msg(NUM_GROUP_TOXES >= 3, "NUM_GROUP_TOXES is too small: %d", NUM_GROUP_TOXES);
|
||||
|
||||
const Random *rng = system_random();
|
||||
const Random *rng = os_random();
|
||||
ck_assert(rng != nullptr);
|
||||
|
||||
Tox *tox0 = autotoxes[0].tox;
|
||||
Tox_Dispatch *dispatch0 = autotoxes[0].dispatch;
|
||||
const State *state0 = (const State *)autotoxes[0].state;
|
||||
|
||||
tox_callback_group_peer_join(tox0, group_peer_join_handler);
|
||||
tox_events_callback_group_peer_join(dispatch0, group_peer_join_handler);
|
||||
|
||||
for (size_t i = 0; i < NUM_GROUP_TOXES; ++i) {
|
||||
tox_callback_group_topic(autotoxes[i].tox, group_topic_handler);
|
||||
tox_callback_group_topic_lock(autotoxes[i].tox, group_topic_lock_handler);
|
||||
tox_events_callback_group_topic(autotoxes[i].dispatch, group_topic_handler);
|
||||
tox_events_callback_group_topic_lock(autotoxes[i].dispatch, group_topic_lock_handler);
|
||||
}
|
||||
|
||||
/* Tox1 creates a group and is the founder of a newly created group */
|
||||
@ -233,11 +250,11 @@ static void group_topic_test(AutoTox *autotoxes)
|
||||
ck_assert_msg(s_ret, "Founder failed to set topic");
|
||||
|
||||
/* Founder gets the Chat ID and implicitly shares it publicly */
|
||||
Tox_Err_Group_State_Queries id_err;
|
||||
Tox_Err_Group_State_Query id_err;
|
||||
uint8_t chat_id[TOX_GROUP_CHAT_ID_SIZE];
|
||||
tox_group_get_chat_id(tox0, groupnumber, chat_id, &id_err);
|
||||
|
||||
ck_assert_msg(id_err == TOX_ERR_GROUP_STATE_QUERIES_OK, "tox_group_get_chat_id failed %d", id_err);
|
||||
ck_assert_msg(id_err == TOX_ERR_GROUP_STATE_QUERY_OK, "tox_group_get_chat_id failed %d", id_err);
|
||||
|
||||
/* All other peers join the group using the Chat ID */
|
||||
for (size_t i = 1; i < NUM_GROUP_TOXES; ++i) {
|
||||
@ -257,9 +274,9 @@ static void group_topic_test(AutoTox *autotoxes)
|
||||
wait_state_topic(autotoxes, groupnumber, TOPIC, TOPIC_LEN);
|
||||
|
||||
/* Founder disables topic lock */
|
||||
Tox_Err_Group_Founder_Set_Topic_Lock lock_set_err;
|
||||
tox_group_founder_set_topic_lock(tox0, groupnumber, TOX_GROUP_TOPIC_LOCK_DISABLED, &lock_set_err);
|
||||
ck_assert_msg(lock_set_err == TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_OK, "failed to disable topic lock: %d",
|
||||
Tox_Err_Group_Set_Topic_Lock lock_set_err;
|
||||
tox_group_set_topic_lock(tox0, groupnumber, TOX_GROUP_TOPIC_LOCK_DISABLED, &lock_set_err);
|
||||
ck_assert_msg(lock_set_err == TOX_ERR_GROUP_SET_TOPIC_LOCK_OK, "failed to disable topic lock: %d",
|
||||
lock_set_err);
|
||||
|
||||
fprintf(stderr, "Topic lock disabled\n");
|
||||
@ -273,9 +290,9 @@ static void group_topic_test(AutoTox *autotoxes)
|
||||
ck_assert_msg(change_count == NUM_GROUP_TOXES, "%u peers changed the topic with topic lock disabled", change_count);
|
||||
|
||||
/* founder silences the last peer he saw join */
|
||||
Tox_Err_Group_Mod_Set_Role merr;
|
||||
tox_group_mod_set_role(tox0, groupnumber, state0->peer_id, TOX_GROUP_ROLE_OBSERVER, &merr);
|
||||
ck_assert_msg(merr == TOX_ERR_GROUP_MOD_SET_ROLE_OK, "Failed to set %u to observer role: %d", state0->peer_id, merr);
|
||||
Tox_Err_Group_Set_Role merr;
|
||||
tox_group_set_role(tox0, groupnumber, state0->peer_id, TOX_GROUP_ROLE_OBSERVER, &merr);
|
||||
ck_assert_msg(merr == TOX_ERR_GROUP_SET_ROLE_OK, "Failed to set %u to observer role: %d", state0->peer_id, merr);
|
||||
|
||||
fprintf(stderr, "Random peer is set to observer\n");
|
||||
|
||||
@ -287,8 +304,8 @@ static void group_topic_test(AutoTox *autotoxes)
|
||||
ck_assert_msg(change_count == NUM_GROUP_TOXES - 1, "%u peers changed the topic with a silenced peer", change_count);
|
||||
|
||||
/* Founder enables topic lock and sets topic back to original */
|
||||
tox_group_founder_set_topic_lock(tox0, groupnumber, TOX_GROUP_TOPIC_LOCK_ENABLED, &lock_set_err);
|
||||
ck_assert_msg(lock_set_err == TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_OK, "failed to enable topic lock: %d",
|
||||
tox_group_set_topic_lock(tox0, groupnumber, TOX_GROUP_TOPIC_LOCK_ENABLED, &lock_set_err);
|
||||
ck_assert_msg(lock_set_err == TOX_ERR_GROUP_SET_TOPIC_LOCK_OK, "failed to enable topic lock: %d",
|
||||
lock_set_err);
|
||||
|
||||
fprintf(stderr, "Topic lock enabled\n");
|
||||
|
@ -18,13 +18,17 @@ typedef struct State {
|
||||
|
||||
#define LOSSLESS_PACKET_FILLER 160
|
||||
|
||||
static void handle_lossless_packet(Tox *tox, uint32_t friend_number, const uint8_t *data, size_t length, void *user_data)
|
||||
static void handle_lossless_packet(const Tox_Event_Friend_Lossless_Packet *event, void *user_data)
|
||||
{
|
||||
//const uint32_t friend_number = tox_event_friend_lossless_packet_get_friend_number(event);
|
||||
const uint8_t *data = tox_event_friend_lossless_packet_get_data(event);
|
||||
const uint32_t data_length = tox_event_friend_lossless_packet_get_data_length(event);
|
||||
|
||||
uint8_t *cmp_packet = (uint8_t *)malloc(tox_max_custom_packet_size());
|
||||
ck_assert(cmp_packet != nullptr);
|
||||
memset(cmp_packet, LOSSLESS_PACKET_FILLER, tox_max_custom_packet_size());
|
||||
|
||||
if (length == tox_max_custom_packet_size() && memcmp(data, cmp_packet, tox_max_custom_packet_size()) == 0) {
|
||||
if (data_length == tox_max_custom_packet_size() && memcmp(data, cmp_packet, tox_max_custom_packet_size()) == 0) {
|
||||
const AutoTox *autotox = (AutoTox *)user_data;
|
||||
State *state = (State *)autotox->state;
|
||||
state->custom_packet_received = true;
|
||||
@ -35,7 +39,7 @@ static void handle_lossless_packet(Tox *tox, uint32_t friend_number, const uint8
|
||||
|
||||
static void test_lossless_packet(AutoTox *autotoxes)
|
||||
{
|
||||
tox_callback_friend_lossless_packet(autotoxes[1].tox, &handle_lossless_packet);
|
||||
tox_events_callback_friend_lossless_packet(autotoxes[1].dispatch, &handle_lossless_packet);
|
||||
const size_t packet_size = tox_max_custom_packet_size() + 1;
|
||||
uint8_t *packet = (uint8_t *)malloc(packet_size);
|
||||
ck_assert(packet != nullptr);
|
||||
|
@ -18,13 +18,17 @@ typedef struct State {
|
||||
|
||||
#define LOSSY_PACKET_FILLER 200
|
||||
|
||||
static void handle_lossy_packet(Tox *tox, uint32_t friend_number, const uint8_t *data, size_t length, void *user_data)
|
||||
static void handle_lossy_packet(const Tox_Event_Friend_Lossy_Packet *event, void *user_data)
|
||||
{
|
||||
//const uint32_t friend_number = tox_event_friend_lossy_packet_get_friend_number(event);
|
||||
const uint8_t *data = tox_event_friend_lossy_packet_get_data(event);
|
||||
const uint32_t data_length = tox_event_friend_lossy_packet_get_data_length(event);
|
||||
|
||||
uint8_t *cmp_packet = (uint8_t *)malloc(tox_max_custom_packet_size());
|
||||
ck_assert(cmp_packet != nullptr);
|
||||
memset(cmp_packet, LOSSY_PACKET_FILLER, tox_max_custom_packet_size());
|
||||
|
||||
if (length == tox_max_custom_packet_size() && memcmp(data, cmp_packet, tox_max_custom_packet_size()) == 0) {
|
||||
if (data_length == tox_max_custom_packet_size() && memcmp(data, cmp_packet, tox_max_custom_packet_size()) == 0) {
|
||||
const AutoTox *autotox = (AutoTox *)user_data;
|
||||
State *state = (State *)autotox->state;
|
||||
state->custom_packet_received = true;
|
||||
@ -35,7 +39,7 @@ static void handle_lossy_packet(Tox *tox, uint32_t friend_number, const uint8_t
|
||||
|
||||
static void test_lossy_packet(AutoTox *autotoxes)
|
||||
{
|
||||
tox_callback_friend_lossy_packet(autotoxes[1].tox, &handle_lossy_packet);
|
||||
tox_events_callback_friend_lossy_packet(autotoxes[1].dispatch, &handle_lossy_packet);
|
||||
const size_t packet_size = tox_max_custom_packet_size() + 1;
|
||||
uint8_t *packet = (uint8_t *)malloc(packet_size);
|
||||
ck_assert(packet != nullptr);
|
||||
|
@ -20,7 +20,7 @@ static void test_addr_resolv_localhost(void)
|
||||
errno = 0;
|
||||
#endif
|
||||
|
||||
const Network *ns = system_network();
|
||||
const Network *ns = os_network();
|
||||
ck_assert(ns != nullptr);
|
||||
|
||||
const char localhost[] = "localhost";
|
||||
|
@ -37,7 +37,7 @@ static void do_onion(Mono_Time *mono_time, Onion *onion)
|
||||
static int handled_test_1;
|
||||
static int handle_test_1(void *object, const IP_Port *source, const uint8_t *packet, uint16_t length, void *userdata)
|
||||
{
|
||||
Onion *onion = (Onion *)object;
|
||||
const Onion *onion = (const Onion *)object;
|
||||
|
||||
const char req_message[] = "Install Gentoo";
|
||||
uint8_t req_packet[1 + sizeof(req_message)];
|
||||
@ -99,7 +99,7 @@ static uint8_t test_3_pub_key[CRYPTO_PUBLIC_KEY_SIZE];
|
||||
static uint8_t test_3_ping_id[CRYPTO_SHA256_SIZE];
|
||||
static int handle_test_3(void *object, const IP_Port *source, const uint8_t *packet, uint16_t length, void *userdata)
|
||||
{
|
||||
Onion *onion = (Onion *)object;
|
||||
const Onion *onion = (const Onion *)object;
|
||||
|
||||
if (length < ONION_ANNOUNCE_RESPONSE_MIN_SIZE || length > ONION_ANNOUNCE_RESPONSE_MAX_SIZE) {
|
||||
return 1;
|
||||
@ -118,7 +118,6 @@ static int handle_test_3(void *object, const IP_Port *source, const uint8_t *pac
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
if (memcmp(packet + 1, sb_data, ONION_ANNOUNCE_SENDBACK_DATA_LENGTH) != 0) {
|
||||
return 1;
|
||||
}
|
||||
@ -135,7 +134,7 @@ static int handle_test_3(void *object, const IP_Port *source, const uint8_t *pac
|
||||
static int handle_test_3_old(void *object, const IP_Port *source, const uint8_t *packet, uint16_t length,
|
||||
void *userdata)
|
||||
{
|
||||
Onion *onion = (Onion *)object;
|
||||
const Onion *onion = (const Onion *)object;
|
||||
|
||||
if (length < ONION_ANNOUNCE_RESPONSE_MIN_SIZE || length > ONION_ANNOUNCE_RESPONSE_MAX_SIZE) {
|
||||
return 1;
|
||||
@ -154,7 +153,6 @@ static int handle_test_3_old(void *object, const IP_Port *source, const uint8_t
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
if (memcmp(packet + 1, sb_data, ONION_ANNOUNCE_SENDBACK_DATA_LENGTH) != 0) {
|
||||
return 1;
|
||||
}
|
||||
@ -171,7 +169,7 @@ static uint8_t nonce[CRYPTO_NONCE_SIZE];
|
||||
static int handled_test_4;
|
||||
static int handle_test_4(void *object, const IP_Port *source, const uint8_t *packet, uint16_t length, void *userdata)
|
||||
{
|
||||
Onion *onion = (Onion *)object;
|
||||
const Onion *onion = (const Onion *)object;
|
||||
|
||||
if (length != (1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + sizeof("Install gentoo") +
|
||||
CRYPTO_MAC_SIZE)) {
|
||||
@ -223,11 +221,11 @@ static Networking_Core *new_networking(const Logger *log, const Memory *mem, con
|
||||
static void test_basic(void)
|
||||
{
|
||||
uint32_t index[] = { 1, 2, 3 };
|
||||
const Network *ns = system_network();
|
||||
const Network *ns = os_network();
|
||||
ck_assert(ns != nullptr);
|
||||
const Memory *mem = system_memory();
|
||||
const Memory *mem = os_memory();
|
||||
ck_assert(mem != nullptr);
|
||||
const Random *rng = system_random();
|
||||
const Random *rng = os_random();
|
||||
ck_assert(rng != nullptr);
|
||||
|
||||
Logger *log1 = logger_new();
|
||||
@ -288,7 +286,7 @@ static void test_basic(void)
|
||||
networking_registerhandler(onion1->net, NET_PACKET_ANNOUNCE_RESPONSE, &handle_test_3, onion1);
|
||||
networking_registerhandler(onion1->net, NET_PACKET_ANNOUNCE_RESPONSE_OLD, &handle_test_3_old, onion1);
|
||||
ck_assert_msg((onion1_a != nullptr) && (onion2_a != nullptr), "Onion_Announce failed initializing.");
|
||||
uint8_t zeroes[64] = {0};
|
||||
const uint8_t zeroes[64] = {0};
|
||||
random_bytes(rng, sb_data, sizeof(sb_data));
|
||||
uint64_t s;
|
||||
memcpy(&s, sb_data, sizeof(uint64_t));
|
||||
@ -407,7 +405,7 @@ static Onions *new_onions(const Memory *mem, const Random *rng, uint16_t port, u
|
||||
{
|
||||
IP ip = get_loopback();
|
||||
ip.ip.v6.uint8[15] = 1;
|
||||
const Network *ns = system_network();
|
||||
const Network *ns = os_network();
|
||||
Onions *on = (Onions *)malloc(sizeof(Onions));
|
||||
|
||||
if (!on) {
|
||||
@ -576,9 +574,9 @@ static void test_announce(void)
|
||||
{
|
||||
uint32_t index[NUM_ONIONS];
|
||||
Onions *onions[NUM_ONIONS];
|
||||
const Random *rng = system_random();
|
||||
const Random *rng = os_random();
|
||||
ck_assert(rng != nullptr);
|
||||
const Memory *mem = system_memory();
|
||||
const Memory *mem = os_memory();
|
||||
ck_assert(mem != nullptr);
|
||||
|
||||
for (uint32_t i = 0; i < NUM_ONIONS; ++i) {
|
||||
|
@ -11,9 +11,13 @@ typedef struct State {
|
||||
|
||||
#define NUM_MSGS 40000
|
||||
|
||||
static void handle_friend_message(Tox *tox, uint32_t friend_number, Tox_Message_Type type,
|
||||
const uint8_t *message, size_t length, void *user_data)
|
||||
static void handle_friend_message(const Tox_Event_Friend_Message *event, void *user_data)
|
||||
{
|
||||
//const uint32_t friend_number = tox_event_friend_message_get_friend_number(event);
|
||||
//const Tox_Message_Type type = tox_event_friend_message_get_type(event);
|
||||
//const uint8_t *message = tox_event_friend_message_get_message(event);
|
||||
//const uint32_t message_length = tox_event_friend_message_get_message_length(event);
|
||||
|
||||
const AutoTox *autotox = (AutoTox *)user_data;
|
||||
State *state = (State *)autotox->state;
|
||||
state->recv_count++;
|
||||
@ -21,7 +25,7 @@ static void handle_friend_message(Tox *tox, uint32_t friend_number, Tox_Message_
|
||||
|
||||
static void net_crypto_overflow_test(AutoTox *autotoxes)
|
||||
{
|
||||
tox_callback_friend_message(autotoxes[0].tox, handle_friend_message);
|
||||
tox_events_callback_friend_message(autotoxes[0].dispatch, handle_friend_message);
|
||||
|
||||
printf("sending many messages to tox0\n");
|
||||
|
||||
|
@ -24,10 +24,10 @@ static bool try_bootstrap(Tox *tox1, Tox *tox2, Tox *tox3, Tox *tox4)
|
||||
tox_self_get_connection_status(tox3) != TOX_CONNECTION_NONE &&
|
||||
tox_self_get_connection_status(tox4) != TOX_CONNECTION_NONE) {
|
||||
printf("%d %d %d %d\n",
|
||||
tox_self_get_connection_status(tox1),
|
||||
tox_self_get_connection_status(tox2),
|
||||
tox_self_get_connection_status(tox3),
|
||||
tox_self_get_connection_status(tox4));
|
||||
tox_self_get_connection_status(tox1),
|
||||
tox_self_get_connection_status(tox2),
|
||||
tox_self_get_connection_status(tox3),
|
||||
tox_self_get_connection_status(tox4));
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -38,10 +38,10 @@ static bool try_bootstrap(Tox *tox1, Tox *tox2, Tox *tox3, Tox *tox4)
|
||||
|
||||
if (i % 10 == 0) {
|
||||
printf("%d %d %d %d\n",
|
||||
tox_self_get_connection_status(tox1),
|
||||
tox_self_get_connection_status(tox2),
|
||||
tox_self_get_connection_status(tox3),
|
||||
tox_self_get_connection_status(tox4));
|
||||
tox_self_get_connection_status(tox1),
|
||||
tox_self_get_connection_status(tox2),
|
||||
tox_self_get_connection_status(tox3),
|
||||
tox_self_get_connection_status(tox4));
|
||||
}
|
||||
|
||||
c_sleep(tox_iteration_interval(tox1));
|
||||
|
@ -51,7 +51,7 @@ static bool all_disconnected_from(uint32_t tox_count, AutoTox *autotoxes, uint32
|
||||
|
||||
static void test_reconnect(AutoTox *autotoxes)
|
||||
{
|
||||
const Random *rng = system_random();
|
||||
const Random *rng = os_random();
|
||||
ck_assert(rng != nullptr);
|
||||
const time_t test_start_time = time(nullptr);
|
||||
|
||||
@ -67,7 +67,12 @@ static void test_reconnect(AutoTox *autotoxes)
|
||||
do {
|
||||
for (uint16_t i = 0; i < TOX_COUNT; ++i) {
|
||||
if (i != disconnect) {
|
||||
tox_iterate(autotoxes[i].tox, &autotoxes[i]);
|
||||
Tox_Err_Events_Iterate err = TOX_ERR_EVENTS_ITERATE_OK;
|
||||
Tox_Events *events = tox_events_iterate(autotoxes[i].tox, true, &err);
|
||||
ck_assert(err == TOX_ERR_EVENTS_ITERATE_OK);
|
||||
tox_dispatch_invoke(autotoxes[i].dispatch, events, &autotoxes[i]);
|
||||
tox_events_free(events);
|
||||
|
||||
autotoxes[i].clock += 1000;
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,8 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define LOADED_SAVE_FILE "../auto_tests/data/save.tox"
|
||||
#define LOADED_SAVE_FILE_BIG "../auto_tests/data/save.tox.big"
|
||||
#define LOADED_SAVE_FILE_LITTLE "../auto_tests/data/save.tox.little"
|
||||
|
||||
// Information from the save file
|
||||
#define EXPECTED_NAME "name"
|
||||
@ -18,7 +19,7 @@
|
||||
#define EXPECTED_STATUS_MESSAGE_SIZE strlen(EXPECTED_STATUS_MESSAGE)
|
||||
#define EXPECTED_NUM_FRIENDS 1
|
||||
#define EXPECTED_NOSPAM "4C762C7D"
|
||||
#define EXPECTED_TOX_ID "B70E97D41F69B7F4C42A5BC7BD7A76B95B8030BE1B7C0E9E6FC19FC4ABEB195B4C762C7D800B"
|
||||
#define EXPECTED_TOX_ID "E776E9A993EE3CAE04F5946D9AC66FBBAA8C63A95A94B41942353C6DC1739B4B4C762C7DA7B9"
|
||||
|
||||
static size_t get_file_size(const char *save_path)
|
||||
{
|
||||
@ -135,6 +136,13 @@ static void test_save_compatibility(const char *save_path)
|
||||
tox_kill(tox);
|
||||
}
|
||||
|
||||
static bool is_little_endian(void)
|
||||
{
|
||||
uint16_t x = 1;
|
||||
return ((uint8_t *)&x)[0] == 1;
|
||||
}
|
||||
|
||||
// cppcheck-suppress constParameter
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char base_path[4096] = {0};
|
||||
@ -152,10 +160,15 @@ int main(int argc, char *argv[])
|
||||
base_path[strrchr(base_path, '/') - base_path] = '\0';
|
||||
}
|
||||
|
||||
char save_path[4096 + sizeof(LOADED_SAVE_FILE)];
|
||||
snprintf(save_path, sizeof(save_path), "%s/%s", base_path, LOADED_SAVE_FILE);
|
||||
|
||||
test_save_compatibility(save_path);
|
||||
if (is_little_endian()) {
|
||||
char save_path[4096 + sizeof(LOADED_SAVE_FILE_LITTLE)];
|
||||
snprintf(save_path, sizeof(save_path), "%s/%s", base_path, LOADED_SAVE_FILE_LITTLE);
|
||||
test_save_compatibility(save_path);
|
||||
} else {
|
||||
char save_path[4096 + sizeof(LOADED_SAVE_FILE_BIG)];
|
||||
snprintf(save_path, sizeof(save_path), "%s/%s", base_path, LOADED_SAVE_FILE_BIG);
|
||||
test_save_compatibility(save_path);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -22,13 +22,12 @@ struct test_data {
|
||||
static void set_random(Tox *m, const Random *rng, bool (*setter)(Tox *, const uint8_t *, size_t, Tox_Err_Set_Info *), size_t length)
|
||||
{
|
||||
VLA(uint8_t, text, length);
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < length; ++i) {
|
||||
for (uint32_t i = 0; i < length; ++i) {
|
||||
text[i] = random_u08(rng);
|
||||
}
|
||||
|
||||
setter(m, text, SIZEOF_VLA(text), nullptr);
|
||||
setter(m, text, length, nullptr);
|
||||
}
|
||||
|
||||
static void alloc_string(uint8_t **to, size_t length)
|
||||
@ -44,18 +43,25 @@ static void set_string(uint8_t **to, const uint8_t *from, size_t length)
|
||||
memcpy(*to, from, length);
|
||||
}
|
||||
|
||||
static void namechange_callback(Tox *tox, uint32_t friend_number, const uint8_t *name, size_t length, void *user_data)
|
||||
static void namechange_callback(const Tox_Event_Friend_Name *event, void *user_data)
|
||||
{
|
||||
//const uint32_t friend_number = tox_event_friend_name_get_friend_number(event);
|
||||
const uint8_t *name = tox_event_friend_name_get_name(event);
|
||||
const uint32_t name_length = tox_event_friend_name_get_name_length(event);
|
||||
|
||||
struct test_data *to_compare = (struct test_data *)user_data;
|
||||
set_string(&to_compare->name, name, length);
|
||||
set_string(&to_compare->name, name, name_length);
|
||||
to_compare->received_name = true;
|
||||
}
|
||||
|
||||
static void statuschange_callback(Tox *tox, uint32_t friend_number, const uint8_t *message, size_t length,
|
||||
void *user_data)
|
||||
static void statuschange_callback(const Tox_Event_Friend_Status_Message *event, void *user_data)
|
||||
{
|
||||
//const uint32_t friend_number = tox_event_friend_status_message_get_friend_number(event);
|
||||
const uint8_t *message = tox_event_friend_status_message_get_message(event);
|
||||
const uint32_t message_length = tox_event_friend_status_message_get_message_length(event);
|
||||
|
||||
struct test_data *to_compare = (struct test_data *)user_data;
|
||||
set_string(&to_compare->status_message, message, length);
|
||||
set_string(&to_compare->status_message, message, message_length);
|
||||
to_compare->received_status_message = true;
|
||||
}
|
||||
|
||||
@ -65,6 +71,12 @@ int main(void)
|
||||
|
||||
Tox *const tox1 = tox_new_log(nullptr, nullptr, nullptr);
|
||||
Tox *const tox2 = tox_new_log(nullptr, nullptr, nullptr);
|
||||
ck_assert(tox1 != nullptr);
|
||||
ck_assert(tox2 != nullptr);
|
||||
|
||||
tox_events_init(tox1);
|
||||
Tox_Dispatch *dispatch1 = tox_dispatch_new(nullptr);
|
||||
ck_assert(dispatch1 != nullptr);
|
||||
|
||||
printf("bootstrapping tox2 off tox1\n");
|
||||
uint8_t dht_key[TOX_PUBLIC_KEY_SIZE];
|
||||
@ -86,7 +98,7 @@ int main(void)
|
||||
ck_assert(reference_name != nullptr);
|
||||
ck_assert(reference_status != nullptr);
|
||||
|
||||
const Random *rng = system_random();
|
||||
const Random *rng = os_random();
|
||||
ck_assert(rng != nullptr);
|
||||
set_random(tox1, rng, tox_self_set_name, tox_max_name_length());
|
||||
set_random(tox2, rng, tox_self_set_name, tox_max_name_length());
|
||||
@ -96,8 +108,8 @@ int main(void)
|
||||
tox_self_get_name(tox2, reference_name);
|
||||
tox_self_get_status_message(tox2, reference_status);
|
||||
|
||||
tox_callback_friend_name(tox1, namechange_callback);
|
||||
tox_callback_friend_status_message(tox1, statuschange_callback);
|
||||
tox_events_callback_friend_name(dispatch1, namechange_callback);
|
||||
tox_events_callback_friend_status_message(dispatch1, statuschange_callback);
|
||||
|
||||
while (true) {
|
||||
if (tox_self_get_connection_status(tox1) &&
|
||||
@ -107,7 +119,12 @@ int main(void)
|
||||
break;
|
||||
}
|
||||
|
||||
tox_iterate(tox1, &to_compare);
|
||||
Tox_Err_Events_Iterate err = TOX_ERR_EVENTS_ITERATE_OK;
|
||||
Tox_Events *events = tox_events_iterate(tox1, true, &err);
|
||||
ck_assert(err == TOX_ERR_EVENTS_ITERATE_OK);
|
||||
tox_dispatch_invoke(dispatch1, events, &to_compare);
|
||||
tox_events_free(events);
|
||||
|
||||
tox_iterate(tox2, nullptr);
|
||||
|
||||
c_sleep(tox_iteration_interval(tox1));
|
||||
@ -119,7 +136,12 @@ int main(void)
|
||||
break;
|
||||
}
|
||||
|
||||
tox_iterate(tox1, &to_compare);
|
||||
Tox_Err_Events_Iterate err = TOX_ERR_EVENTS_ITERATE_OK;
|
||||
Tox_Events *events = tox_events_iterate(tox1, true, &err);
|
||||
ck_assert(err == TOX_ERR_EVENTS_ITERATE_OK);
|
||||
tox_dispatch_invoke(dispatch1, events, &to_compare);
|
||||
tox_events_free(events);
|
||||
|
||||
tox_iterate(tox2, nullptr);
|
||||
|
||||
c_sleep(tox_iteration_interval(tox1));
|
||||
@ -146,6 +168,7 @@ int main(void)
|
||||
"incorrect status message: should be all zeroes");
|
||||
|
||||
tox_options_free(options);
|
||||
tox_dispatch_free(dispatch1);
|
||||
tox_kill(tox1);
|
||||
tox_kill(tox2);
|
||||
tox_kill(tox_to_compare);
|
||||
|
@ -32,16 +32,24 @@
|
||||
#endif
|
||||
#define TCP_RELAY_PORT 33431
|
||||
|
||||
static void accept_friend_request(Tox *m, const uint8_t *public_key, const uint8_t *data, size_t length, void *userdata)
|
||||
static void accept_friend_request(const Tox_Event_Friend_Request *event, void *userdata)
|
||||
{
|
||||
if (length == 7 && memcmp("Gentoo", data, 7) == 0) {
|
||||
tox_friend_add_norequest(m, public_key, nullptr);
|
||||
Tox *tox = (Tox *)userdata;
|
||||
|
||||
const uint8_t *public_key = tox_event_friend_request_get_public_key(event);
|
||||
const uint8_t *message = tox_event_friend_request_get_message(event);
|
||||
uint32_t message_length = tox_event_friend_request_get_message_length(event);
|
||||
|
||||
if (message_length == 7 && memcmp("Gentoo", message, 7) == 0) {
|
||||
tox_friend_add_norequest(tox, public_key, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int connected_t1;
|
||||
static void tox_connection_status(Tox *tox, Tox_Connection connection_status, void *user_data)
|
||||
static void tox_connection_status(const Tox_Event_Self_Connection_Status *event, void *user_data)
|
||||
{
|
||||
const Tox_Connection connection_status = tox_event_self_connection_status_get_connection_status(event);
|
||||
|
||||
if (connected_t1 && !connection_status) {
|
||||
ck_abort_msg("Tox went offline");
|
||||
}
|
||||
@ -147,6 +155,9 @@ static void test_few_clients(void)
|
||||
Tox *tox1 = tox_new_log(opts1, &t_n_error, &index[0]);
|
||||
ck_assert_msg(t_n_error == TOX_ERR_NEW_OK, "Failed to create tox instance: %d", t_n_error);
|
||||
tox_options_free(opts1);
|
||||
tox_events_init(tox1);
|
||||
Tox_Dispatch *dispatch1 = tox_dispatch_new(nullptr);
|
||||
ck_assert(dispatch1 != nullptr);
|
||||
|
||||
struct Tox_Options *opts2 = tox_options_new(nullptr);
|
||||
tox_options_set_ipv6_enabled(opts2, USE_IPV6);
|
||||
@ -154,6 +165,9 @@ static void test_few_clients(void)
|
||||
tox_options_set_local_discovery_enabled(opts2, false);
|
||||
Tox *tox2 = tox_new_log(opts2, &t_n_error, &index[1]);
|
||||
ck_assert_msg(t_n_error == TOX_ERR_NEW_OK, "Failed to create tox instance: %d", t_n_error);
|
||||
tox_events_init(tox2);
|
||||
Tox_Dispatch *dispatch2 = tox_dispatch_new(nullptr);
|
||||
ck_assert(dispatch2 != nullptr);
|
||||
|
||||
struct Tox_Options *opts3 = tox_options_new(nullptr);
|
||||
tox_options_set_ipv6_enabled(opts3, USE_IPV6);
|
||||
@ -163,7 +177,6 @@ static void test_few_clients(void)
|
||||
|
||||
ck_assert_msg(tox1 && tox2 && tox3, "Failed to create 3 tox instances");
|
||||
|
||||
|
||||
Time_Data time_data;
|
||||
ck_assert_msg(pthread_mutex_init(&time_data.lock, nullptr) == 0, "Failed to init time_data mutex");
|
||||
time_data.clock = current_time_monotonic(tox1->mono_time);
|
||||
@ -183,8 +196,8 @@ static void test_few_clients(void)
|
||||
tox_bootstrap(tox3, "localhost", dht_port, dht_key, nullptr);
|
||||
|
||||
connected_t1 = 0;
|
||||
tox_callback_self_connection_status(tox1, tox_connection_status);
|
||||
tox_callback_friend_request(tox2, accept_friend_request);
|
||||
tox_events_callback_self_connection_status(dispatch1, tox_connection_status);
|
||||
tox_events_callback_friend_request(dispatch2, accept_friend_request);
|
||||
uint8_t address[TOX_ADDRESS_SIZE];
|
||||
tox_self_get_address(tox2, address);
|
||||
uint32_t test = tox_friend_add(tox3, address, (const uint8_t *)"Gentoo", 7, nullptr);
|
||||
@ -193,8 +206,20 @@ static void test_few_clients(void)
|
||||
uint8_t off = 1;
|
||||
|
||||
while (true) {
|
||||
tox_iterate(tox1, nullptr);
|
||||
tox_iterate(tox2, nullptr);
|
||||
{
|
||||
Tox_Err_Events_Iterate err = TOX_ERR_EVENTS_ITERATE_OK;
|
||||
Tox_Events *events = tox_events_iterate(tox1, true, &err);
|
||||
ck_assert(err == TOX_ERR_EVENTS_ITERATE_OK);
|
||||
tox_dispatch_invoke(dispatch1, events, tox1);
|
||||
tox_events_free(events);
|
||||
}
|
||||
{
|
||||
Tox_Err_Events_Iterate err = TOX_ERR_EVENTS_ITERATE_OK;
|
||||
Tox_Events *events = tox_events_iterate(tox2, true, &err);
|
||||
ck_assert(err == TOX_ERR_EVENTS_ITERATE_OK);
|
||||
tox_dispatch_invoke(dispatch2, events, tox2);
|
||||
tox_events_free(events);
|
||||
}
|
||||
tox_iterate(tox3, nullptr);
|
||||
|
||||
if (tox_self_get_connection_status(tox1) && tox_self_get_connection_status(tox2)
|
||||
@ -220,9 +245,10 @@ static void test_few_clients(void)
|
||||
|
||||
// We're done with this callback, so unset it to ensure we don't fail the
|
||||
// test if tox1 goes offline while tox2 and 3 are reloaded.
|
||||
tox_callback_self_connection_status(tox1, nullptr);
|
||||
tox_events_callback_self_connection_status(dispatch1, nullptr);
|
||||
|
||||
reload_tox(&tox2, opts2, &index[1]);
|
||||
tox_events_init(tox2);
|
||||
|
||||
reload_tox(&tox3, opts3, &index[2]);
|
||||
|
||||
@ -231,8 +257,20 @@ static void test_few_clients(void)
|
||||
off = 1;
|
||||
|
||||
while (true) {
|
||||
tox_iterate(tox1, nullptr);
|
||||
tox_iterate(tox2, nullptr);
|
||||
{
|
||||
Tox_Err_Events_Iterate err = TOX_ERR_EVENTS_ITERATE_OK;
|
||||
Tox_Events *events = tox_events_iterate(tox1, true, &err);
|
||||
ck_assert(err == TOX_ERR_EVENTS_ITERATE_OK);
|
||||
tox_dispatch_invoke(dispatch1, events, tox1);
|
||||
tox_events_free(events);
|
||||
}
|
||||
{
|
||||
Tox_Err_Events_Iterate err = TOX_ERR_EVENTS_ITERATE_OK;
|
||||
Tox_Events *events = tox_events_iterate(tox2, true, &err);
|
||||
ck_assert(err == TOX_ERR_EVENTS_ITERATE_OK);
|
||||
tox_dispatch_invoke(dispatch2, events, tox2);
|
||||
tox_events_free(events);
|
||||
}
|
||||
tox_iterate(tox3, nullptr);
|
||||
|
||||
if (tox_self_get_connection_status(tox1) && tox_self_get_connection_status(tox2)
|
||||
@ -257,6 +295,9 @@ static void test_few_clients(void)
|
||||
|
||||
printf("test_few_clients succeeded, took %lu seconds\n", (unsigned long)(time(nullptr) - cur_time));
|
||||
|
||||
tox_dispatch_free(dispatch1);
|
||||
tox_dispatch_free(dispatch2);
|
||||
|
||||
tox_kill(tox1);
|
||||
tox_kill(tox2);
|
||||
tox_kill(tox3);
|
||||
|
@ -14,12 +14,15 @@ typedef struct State {
|
||||
#define MESSAGE_FILLER 'G'
|
||||
|
||||
static void message_callback(
|
||||
Tox *m, uint32_t friendnumber, Tox_Message_Type type,
|
||||
const uint8_t *string, size_t length, void *user_data)
|
||||
const Tox_Event_Friend_Message *event, void *user_data)
|
||||
{
|
||||
const AutoTox *autotox = (AutoTox *)user_data;
|
||||
State *state = (State *)autotox->state;
|
||||
|
||||
const Tox_Message_Type type = tox_event_friend_message_get_type(event);
|
||||
const uint8_t *string = tox_event_friend_message_get_message(event);
|
||||
const uint32_t length = tox_event_friend_message_get_message_length(event);
|
||||
|
||||
if (type != TOX_MESSAGE_TYPE_NORMAL) {
|
||||
ck_abort_msg("Bad type");
|
||||
}
|
||||
@ -38,7 +41,7 @@ static void message_callback(
|
||||
|
||||
static void send_message_test(AutoTox *autotoxes)
|
||||
{
|
||||
tox_callback_friend_message(autotoxes[1].tox, &message_callback);
|
||||
tox_events_callback_friend_message(autotoxes[1].dispatch, &message_callback);
|
||||
|
||||
const size_t msgs_len = tox_max_message_length() + 1;
|
||||
uint8_t *msgs = (uint8_t *)malloc(msgs_len);
|
||||
|
@ -15,12 +15,16 @@
|
||||
|
||||
#define NICKNAME "Gentoo"
|
||||
|
||||
static void nickchange_callback(Tox *tox, uint32_t friendnumber, const uint8_t *string, size_t length, void *userdata)
|
||||
static void nickchange_callback(const Tox_Event_Friend_Name *event, void *user_data)
|
||||
{
|
||||
ck_assert_msg(length == sizeof(NICKNAME), "Name length not correct: %d != %d", (uint16_t)length,
|
||||
//const uint32_t friend_number = tox_event_friend_name_get_friend_number(event);
|
||||
const uint8_t *name = tox_event_friend_name_get_name(event);
|
||||
const uint32_t name_length = tox_event_friend_name_get_name_length(event);
|
||||
|
||||
ck_assert_msg(name_length == sizeof(NICKNAME), "Name length not correct: %d != %d", (uint16_t)name_length,
|
||||
(uint16_t)sizeof(NICKNAME));
|
||||
ck_assert_msg(memcmp(string, NICKNAME, sizeof(NICKNAME)) == 0, "Name not correct: %s", (const char *)string);
|
||||
bool *nickname_updated = (bool *)userdata;
|
||||
ck_assert_msg(memcmp(name, NICKNAME, sizeof(NICKNAME)) == 0, "Name not correct: %s", (const char *)name);
|
||||
bool *nickname_updated = (bool *)user_data;
|
||||
*nickname_updated = true;
|
||||
}
|
||||
|
||||
@ -34,6 +38,12 @@ static void test_set_name(void)
|
||||
|
||||
ck_assert_msg(tox1 && tox2, "failed to create 2 tox instances");
|
||||
|
||||
// we only run events on tox2 in this test case
|
||||
tox_events_init(tox2);
|
||||
|
||||
Tox_Dispatch *dispatch2 = tox_dispatch_new(nullptr);
|
||||
ck_assert(dispatch2 != nullptr);
|
||||
|
||||
printf("tox1 adds tox2 as friend, tox2 adds tox1\n");
|
||||
uint8_t public_key[TOX_PUBLIC_KEY_SIZE];
|
||||
tox_self_get_public_key(tox2, public_key);
|
||||
@ -50,7 +60,13 @@ static void test_set_name(void)
|
||||
|
||||
do {
|
||||
tox_iterate(tox1, nullptr);
|
||||
tox_iterate(tox2, nullptr);
|
||||
|
||||
Tox_Err_Events_Iterate err = TOX_ERR_EVENTS_ITERATE_OK;
|
||||
Tox_Events *events = tox_events_iterate(tox2, true, &err);
|
||||
ck_assert(err == TOX_ERR_EVENTS_ITERATE_OK);
|
||||
//tox_dispatch_invoke(dispatch2, events, nullptr);
|
||||
tox_events_free(events);
|
||||
|
||||
c_sleep(ITERATION_INTERVAL);
|
||||
} while (tox_self_get_connection_status(tox1) == TOX_CONNECTION_NONE ||
|
||||
tox_self_get_connection_status(tox2) == TOX_CONNECTION_NONE);
|
||||
@ -60,14 +76,20 @@ static void test_set_name(void)
|
||||
|
||||
do {
|
||||
tox_iterate(tox1, nullptr);
|
||||
tox_iterate(tox2, nullptr);
|
||||
|
||||
Tox_Err_Events_Iterate err = TOX_ERR_EVENTS_ITERATE_OK;
|
||||
Tox_Events *events = tox_events_iterate(tox2, true, &err);
|
||||
ck_assert(err == TOX_ERR_EVENTS_ITERATE_OK);
|
||||
//tox_dispatch_invoke(dispatch2, events, nullptr);
|
||||
tox_events_free(events);
|
||||
|
||||
c_sleep(ITERATION_INTERVAL);
|
||||
} while (tox_friend_get_connection_status(tox1, 0, nullptr) != TOX_CONNECTION_UDP ||
|
||||
tox_friend_get_connection_status(tox2, 0, nullptr) != TOX_CONNECTION_UDP);
|
||||
|
||||
printf("tox clients connected took %lu seconds\n", (unsigned long)(time(nullptr) - con_time));
|
||||
|
||||
tox_callback_friend_name(tox2, nickchange_callback);
|
||||
tox_events_callback_friend_name(dispatch2, nickchange_callback);
|
||||
Tox_Err_Set_Info err_n;
|
||||
bool ret = tox_self_set_name(tox1, (const uint8_t *)NICKNAME, sizeof(NICKNAME), &err_n);
|
||||
ck_assert_msg(ret && err_n == TOX_ERR_SET_INFO_OK, "tox_self_set_name failed because %d\n", err_n);
|
||||
@ -76,7 +98,13 @@ static void test_set_name(void)
|
||||
|
||||
do {
|
||||
tox_iterate(tox1, nullptr);
|
||||
tox_iterate(tox2, &nickname_updated);
|
||||
|
||||
Tox_Err_Events_Iterate err = TOX_ERR_EVENTS_ITERATE_OK;
|
||||
Tox_Events *events = tox_events_iterate(tox2, true, &err);
|
||||
ck_assert(err == TOX_ERR_EVENTS_ITERATE_OK);
|
||||
tox_dispatch_invoke(dispatch2, events, &nickname_updated);
|
||||
tox_events_free(events);
|
||||
|
||||
c_sleep(ITERATION_INTERVAL);
|
||||
} while (!nickname_updated);
|
||||
|
||||
@ -87,6 +115,8 @@ static void test_set_name(void)
|
||||
|
||||
printf("test_set_name succeeded, took %lu seconds\n", (unsigned long)(time(nullptr) - cur_time));
|
||||
|
||||
tox_dispatch_free(dispatch2);
|
||||
|
||||
tox_kill(tox1);
|
||||
tox_kill(tox2);
|
||||
}
|
||||
|
@ -15,9 +15,13 @@
|
||||
|
||||
#define STATUS_MESSAGE "Installing Gentoo"
|
||||
|
||||
static void status_callback(Tox *tox, uint32_t friend_number, const uint8_t *message, size_t length, void *user_data)
|
||||
static void status_callback(const Tox_Event_Friend_Status_Message *event, void *user_data)
|
||||
{
|
||||
ck_assert_msg(length == sizeof(STATUS_MESSAGE) &&
|
||||
//uint32_t friend_number = tox_event_friend_status_message_get_friend_number(event);
|
||||
const uint8_t *message = tox_event_friend_status_message_get_message(event);
|
||||
uint32_t message_length = tox_event_friend_status_message_get_message_length(event);
|
||||
|
||||
ck_assert_msg(message_length == sizeof(STATUS_MESSAGE) &&
|
||||
memcmp(message, STATUS_MESSAGE, sizeof(STATUS_MESSAGE)) == 0,
|
||||
"incorrect data in status callback");
|
||||
bool *status_updated = (bool *)user_data;
|
||||
@ -34,6 +38,12 @@ static void test_set_status_message(void)
|
||||
|
||||
ck_assert_msg(tox1 && tox2, "failed to create 2 tox instances");
|
||||
|
||||
// we only run events on tox2 in this test case
|
||||
tox_events_init(tox2);
|
||||
|
||||
Tox_Dispatch *dispatch2 = tox_dispatch_new(nullptr);
|
||||
ck_assert(dispatch2 != nullptr);
|
||||
|
||||
printf("tox1 adds tox2 as friend, tox2 adds tox1\n");
|
||||
uint8_t public_key[TOX_PUBLIC_KEY_SIZE];
|
||||
tox_self_get_public_key(tox2, public_key);
|
||||
@ -50,7 +60,12 @@ static void test_set_status_message(void)
|
||||
|
||||
do {
|
||||
tox_iterate(tox1, nullptr);
|
||||
tox_iterate(tox2, nullptr);
|
||||
|
||||
Tox_Err_Events_Iterate err = TOX_ERR_EVENTS_ITERATE_OK;
|
||||
Tox_Events *events = tox_events_iterate(tox2, true, &err);
|
||||
ck_assert(err == TOX_ERR_EVENTS_ITERATE_OK);
|
||||
//tox_dispatch_invoke(dispatch2, events, nullptr);
|
||||
tox_events_free(events);
|
||||
|
||||
c_sleep(ITERATION_INTERVAL);
|
||||
} while (tox_self_get_connection_status(tox1) == TOX_CONNECTION_NONE ||
|
||||
@ -61,7 +76,12 @@ static void test_set_status_message(void)
|
||||
|
||||
do {
|
||||
tox_iterate(tox1, nullptr);
|
||||
tox_iterate(tox2, nullptr);
|
||||
|
||||
Tox_Err_Events_Iterate err = TOX_ERR_EVENTS_ITERATE_OK;
|
||||
Tox_Events *events = tox_events_iterate(tox2, true, &err);
|
||||
ck_assert(err == TOX_ERR_EVENTS_ITERATE_OK);
|
||||
//tox_dispatch_invoke(dispatch2, events, nullptr);
|
||||
tox_events_free(events);
|
||||
|
||||
c_sleep(ITERATION_INTERVAL);
|
||||
} while (tox_friend_get_connection_status(tox1, 0, nullptr) != TOX_CONNECTION_UDP ||
|
||||
@ -69,8 +89,8 @@ static void test_set_status_message(void)
|
||||
|
||||
printf("tox clients connected took %lu seconds\n", (unsigned long)(time(nullptr) - con_time));
|
||||
|
||||
tox_events_callback_friend_status_message(dispatch2, status_callback);
|
||||
Tox_Err_Set_Info err_n;
|
||||
tox_callback_friend_status_message(tox2, status_callback);
|
||||
bool ret = tox_self_set_status_message(tox1, (const uint8_t *)STATUS_MESSAGE, sizeof(STATUS_MESSAGE),
|
||||
&err_n);
|
||||
ck_assert_msg(ret && err_n == TOX_ERR_SET_INFO_OK, "tox_self_set_status_message failed because %d\n", err_n);
|
||||
@ -79,7 +99,13 @@ static void test_set_status_message(void)
|
||||
|
||||
do {
|
||||
tox_iterate(tox1, nullptr);
|
||||
tox_iterate(tox2, &status_updated);
|
||||
|
||||
Tox_Err_Events_Iterate err = TOX_ERR_EVENTS_ITERATE_OK;
|
||||
Tox_Events *events = tox_events_iterate(tox2, true, &err);
|
||||
ck_assert(err == TOX_ERR_EVENTS_ITERATE_OK);
|
||||
tox_dispatch_invoke(dispatch2, events, &status_updated);
|
||||
tox_events_free(events);
|
||||
|
||||
c_sleep(ITERATION_INTERVAL);
|
||||
} while (!status_updated);
|
||||
|
||||
@ -92,6 +118,8 @@ static void test_set_status_message(void)
|
||||
|
||||
printf("test_set_status_message succeeded, took %lu seconds\n", (unsigned long)(time(nullptr) - cur_time));
|
||||
|
||||
tox_dispatch_free(dispatch2);
|
||||
|
||||
tox_kill(tox1);
|
||||
tox_kill(tox2);
|
||||
}
|
||||
|
@ -18,7 +18,7 @@
|
||||
// Set to true to produce an msgpack file at /tmp/test.mp.
|
||||
static const bool want_dump_events = false;
|
||||
|
||||
static void handle_events_friend_message(Tox *tox, const Tox_Event_Friend_Message *event, void *user_data)
|
||||
static void handle_events_friend_message(const Tox_Event_Friend_Message *event, void *user_data)
|
||||
{
|
||||
bool *success = (bool *)user_data;
|
||||
|
||||
@ -84,7 +84,7 @@ static bool await_message(Tox **toxes, const Tox_Dispatch *dispatch)
|
||||
}
|
||||
|
||||
bool success = false;
|
||||
tox_dispatch_invoke(dispatch, events, toxes[1], &success);
|
||||
tox_dispatch_invoke(dispatch, events, &success);
|
||||
print_events(sys, events);
|
||||
|
||||
if (success) {
|
||||
@ -169,22 +169,9 @@ static void test_tox_events(void)
|
||||
}
|
||||
}
|
||||
|
||||
static void fake_test_unpack(void)
|
||||
{
|
||||
// TODO(Green-Sky): add proper unpack tests and/or implement ngc events
|
||||
(void)tox_group_privacy_state_unpack;
|
||||
(void)tox_group_privacy_state_unpack;
|
||||
(void)tox_group_voice_state_unpack;
|
||||
(void)tox_group_topic_lock_unpack;
|
||||
(void)tox_group_join_fail_unpack;
|
||||
(void)tox_group_mod_event_unpack;
|
||||
(void)tox_group_exit_type_unpack;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
setvbuf(stdout, nullptr, _IONBF, 0);
|
||||
test_tox_events();
|
||||
fake_test_unpack();
|
||||
return 0;
|
||||
}
|
||||
|
@ -26,16 +26,27 @@
|
||||
#define TOX_LOCALHOST "127.0.0.1"
|
||||
#endif
|
||||
|
||||
typedef struct State {
|
||||
uint32_t to_comp;
|
||||
Tox *tox;
|
||||
} State;
|
||||
|
||||
static bool enable_broken_tests = false;
|
||||
|
||||
static void accept_friend_request(Tox *m, const uint8_t *public_key, const uint8_t *data, size_t length, void *userdata)
|
||||
static void accept_friend_request(const Tox_Event_Friend_Request *event, void *userdata)
|
||||
{
|
||||
if (*((uint32_t *)userdata) != 974536) {
|
||||
State *state = (State *)userdata;
|
||||
|
||||
const uint8_t *public_key = tox_event_friend_request_get_public_key(event);
|
||||
const uint8_t *message = tox_event_friend_request_get_message(event);
|
||||
const uint32_t message_length = tox_event_friend_request_get_message_length(event);
|
||||
|
||||
if (state->to_comp != 974536) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (length == 7 && memcmp("Gentoo", data, 7) == 0) {
|
||||
tox_friend_add_norequest(m, public_key, nullptr);
|
||||
if (message_length == 7 && memcmp("Gentoo", message, 7) == 0) {
|
||||
tox_friend_add_norequest(state->tox, public_key, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
@ -46,7 +57,7 @@ static uint16_t tcp_relay_port = 33448;
|
||||
|
||||
static void test_many_clients_tcp(void)
|
||||
{
|
||||
const Random *rng = system_random();
|
||||
const Random *rng = os_random();
|
||||
ck_assert(rng != nullptr);
|
||||
long long unsigned int cur_time = time(nullptr);
|
||||
Tox *toxes[NUM_TOXES_TCP];
|
||||
@ -73,7 +84,7 @@ static void test_many_clients_tcp(void)
|
||||
continue;
|
||||
}
|
||||
ck_assert_msg(toxes[i] != nullptr, "Failed to create tox instances %u", i);
|
||||
tox_callback_friend_request(toxes[i], accept_friend_request);
|
||||
tox_events_init(toxes[i]);
|
||||
uint8_t dpk[TOX_PUBLIC_KEY_SIZE];
|
||||
tox_self_get_dht_id(toxes[0], dpk);
|
||||
Tox_Err_Bootstrap error;
|
||||
@ -85,6 +96,11 @@ static void test_many_clients_tcp(void)
|
||||
tox_options_free(opts);
|
||||
}
|
||||
|
||||
Tox_Dispatch *dispatch = tox_dispatch_new(nullptr);
|
||||
ck_assert(dispatch != nullptr);
|
||||
|
||||
tox_events_callback_friend_request(dispatch, accept_friend_request);
|
||||
|
||||
struct {
|
||||
uint16_t tox1;
|
||||
uint16_t tox2;
|
||||
@ -131,12 +147,18 @@ loop_top:
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < NUM_TOXES_TCP; ++i) {
|
||||
tox_iterate(toxes[i], &to_comp);
|
||||
Tox_Err_Events_Iterate err = TOX_ERR_EVENTS_ITERATE_OK;
|
||||
Tox_Events *events = tox_events_iterate(toxes[i], true, &err);
|
||||
ck_assert(err == TOX_ERR_EVENTS_ITERATE_OK);
|
||||
State state = {to_comp, toxes[i]};
|
||||
tox_dispatch_invoke(dispatch, events, &state);
|
||||
tox_events_free(events);
|
||||
}
|
||||
|
||||
c_sleep(50);
|
||||
}
|
||||
|
||||
tox_dispatch_free(dispatch);
|
||||
for (uint32_t i = 0; i < NUM_TOXES_TCP; ++i) {
|
||||
tox_kill(toxes[i]);
|
||||
}
|
||||
@ -148,7 +170,7 @@ loop_top:
|
||||
|
||||
static void test_many_clients_tcp_b(void)
|
||||
{
|
||||
const Random *rng = system_random();
|
||||
const Random *rng = os_random();
|
||||
ck_assert(rng != nullptr);
|
||||
long long unsigned int cur_time = time(nullptr);
|
||||
Tox *toxes[NUM_TOXES_TCP];
|
||||
@ -167,7 +189,7 @@ static void test_many_clients_tcp_b(void)
|
||||
index[i] = i + 1;
|
||||
toxes[i] = tox_new_log(opts, nullptr, &index[i]);
|
||||
ck_assert_msg(toxes[i] != nullptr, "Failed to create tox instances %u", i);
|
||||
tox_callback_friend_request(toxes[i], accept_friend_request);
|
||||
tox_events_init(toxes[i]);
|
||||
uint8_t dpk[TOX_PUBLIC_KEY_SIZE];
|
||||
tox_self_get_dht_id(toxes[(i % NUM_TCP_RELAYS)], dpk);
|
||||
ck_assert_msg(tox_add_tcp_relay(toxes[i], TOX_LOCALHOST, tcp_relay_port + (i % NUM_TCP_RELAYS), dpk, nullptr),
|
||||
@ -179,6 +201,11 @@ static void test_many_clients_tcp_b(void)
|
||||
tox_options_free(opts);
|
||||
}
|
||||
|
||||
Tox_Dispatch *dispatch = tox_dispatch_new(nullptr);
|
||||
ck_assert(dispatch != nullptr);
|
||||
|
||||
tox_events_callback_friend_request(dispatch, accept_friend_request);
|
||||
|
||||
struct {
|
||||
uint16_t tox1;
|
||||
uint16_t tox2;
|
||||
@ -232,12 +259,18 @@ loop_top:
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < NUM_TOXES_TCP; ++i) {
|
||||
tox_iterate(toxes[i], &to_comp);
|
||||
Tox_Err_Events_Iterate err = TOX_ERR_EVENTS_ITERATE_OK;
|
||||
Tox_Events *events = tox_events_iterate(toxes[i], true, &err);
|
||||
ck_assert(err == TOX_ERR_EVENTS_ITERATE_OK);
|
||||
State state = {to_comp, toxes[i]};
|
||||
tox_dispatch_invoke(dispatch, events, &state);
|
||||
tox_events_free(events);
|
||||
}
|
||||
|
||||
c_sleep(30);
|
||||
}
|
||||
|
||||
tox_dispatch_free(dispatch);
|
||||
for (uint32_t i = 0; i < NUM_TOXES_TCP; ++i) {
|
||||
tox_kill(toxes[i]);
|
||||
}
|
||||
@ -245,7 +278,6 @@ loop_top:
|
||||
printf("test_many_clients_tcp_b succeeded, took %llu seconds\n", time(nullptr) - cur_time);
|
||||
}
|
||||
|
||||
|
||||
static void tox_suite(void)
|
||||
{
|
||||
/* Each tox connects to a single tox TCP */
|
||||
|
@ -13,20 +13,25 @@
|
||||
#include "auto_test_support.h"
|
||||
#include "check_compat.h"
|
||||
|
||||
static void accept_friend_request(Tox *m, const uint8_t *public_key, const uint8_t *data, size_t length, void *userdata)
|
||||
static void accept_friend_request(const Tox_Event_Friend_Request *event, void *userdata)
|
||||
{
|
||||
if (length == 7 && memcmp("Gentoo", data, 7) == 0) {
|
||||
tox_friend_add_norequest(m, public_key, nullptr);
|
||||
Tox *tox = (Tox *)userdata;
|
||||
|
||||
const uint8_t *public_key = tox_event_friend_request_get_public_key(event);
|
||||
const uint8_t *message = tox_event_friend_request_get_message(event);
|
||||
const uint32_t message_length = tox_event_friend_request_get_message_length(event);
|
||||
|
||||
if (message_length == 7 && memcmp("Gentoo", message, 7) == 0) {
|
||||
tox_friend_add_norequest(tox, public_key, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define TCP_TEST_NUM_TOXES 90
|
||||
#define TCP_TEST_NUM_FRIENDS 50
|
||||
|
||||
static void test_many_clients(void)
|
||||
{
|
||||
const Random *rng = system_random();
|
||||
const Random *rng = os_random();
|
||||
ck_assert(rng != nullptr);
|
||||
time_t cur_time = time(nullptr);
|
||||
Tox *toxes[TCP_TEST_NUM_TOXES];
|
||||
@ -36,9 +41,14 @@ static void test_many_clients(void)
|
||||
index[i] = i + 1;
|
||||
toxes[i] = tox_new_log(nullptr, nullptr, &index[i]);
|
||||
ck_assert_msg(toxes[i] != nullptr, "failed to create tox instances %u", i);
|
||||
tox_callback_friend_request(toxes[i], accept_friend_request);
|
||||
tox_events_init(toxes[i]);
|
||||
}
|
||||
|
||||
Tox_Dispatch *dispatch = tox_dispatch_new(nullptr);
|
||||
ck_assert(dispatch != nullptr);
|
||||
|
||||
tox_events_callback_friend_request(dispatch, accept_friend_request);
|
||||
|
||||
struct {
|
||||
uint16_t tox1;
|
||||
uint16_t tox2;
|
||||
@ -112,12 +122,17 @@ loop_top:
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < TCP_TEST_NUM_TOXES; ++i) {
|
||||
tox_iterate(toxes[i], nullptr);
|
||||
Tox_Err_Events_Iterate err = TOX_ERR_EVENTS_ITERATE_OK;
|
||||
Tox_Events *events = tox_events_iterate(toxes[i], true, &err);
|
||||
ck_assert(err == TOX_ERR_EVENTS_ITERATE_OK);
|
||||
tox_dispatch_invoke(dispatch, events, toxes[i]);
|
||||
tox_events_free(events);
|
||||
}
|
||||
|
||||
c_sleep(50);
|
||||
}
|
||||
|
||||
tox_dispatch_free(dispatch);
|
||||
for (uint32_t i = 0; i < TCP_TEST_NUM_TOXES; ++i) {
|
||||
tox_kill(toxes[i]);
|
||||
}
|
||||
|
9
external/toxcore/c-toxcore/auto_tests/tox_new_test.c
vendored
Normal file
9
external/toxcore/c-toxcore/auto_tests/tox_new_test.c
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
#include "../toxcore/tox.h"
|
||||
|
||||
#include "../toxcore/ccompat.h"
|
||||
|
||||
int main(void)
|
||||
{
|
||||
tox_kill(tox_new(nullptr, nullptr));
|
||||
return 0;
|
||||
}
|
@ -23,7 +23,6 @@
|
||||
#define TEST_STOP_RESUME_PAYLOAD 1
|
||||
#define TEST_PAUSE_RESUME_SEND 1
|
||||
|
||||
|
||||
#define ck_assert_call_control(a, b, c) do { \
|
||||
Toxav_Err_Call_Control cc_err; \
|
||||
bool ok = toxav_call_control(a, b, c, &cc_err); \
|
||||
@ -34,7 +33,6 @@
|
||||
ck_assert(cc_err == TOXAV_ERR_CALL_CONTROL_OK); \
|
||||
} while (0)
|
||||
|
||||
|
||||
typedef struct {
|
||||
bool incoming;
|
||||
uint32_t state;
|
||||
@ -46,7 +44,6 @@ static void clear_call_control(CallControl *cc)
|
||||
*cc = empty;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Callbacks
|
||||
*/
|
||||
@ -89,7 +86,6 @@ static void t_accept_friend_request_cb(Tox *m, const uint8_t *public_key, const
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Iterate helper
|
||||
*/
|
||||
@ -207,7 +203,6 @@ static void test_av_flows(void)
|
||||
c_sleep(20);
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
Toxav_Err_New error;
|
||||
alice_av = toxav_new(alice, &error);
|
||||
|
@ -74,7 +74,6 @@ static void t_accept_friend_request_cb(Tox *m, const uint8_t *public_key, const
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Iterate helper
|
||||
*/
|
||||
@ -299,7 +298,6 @@ static void test_av_three_calls(void)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
do {
|
||||
tox_iterate(bootstrap, nullptr);
|
||||
tox_iterate(alice, nullptr);
|
||||
|
@ -17,10 +17,14 @@ typedef struct State {
|
||||
|
||||
#include "auto_test_support.h"
|
||||
|
||||
static void typing_callback(Tox *m, uint32_t friendnumber, bool typing, void *user_data)
|
||||
static void typing_callback(const Tox_Event_Friend_Typing *event, void *user_data)
|
||||
{
|
||||
const AutoTox *autotox = (AutoTox *)user_data;
|
||||
State *state = (State *)autotox->state;
|
||||
|
||||
//const uint32_t friend_number = tox_event_friend_typing_get_friend_number(event);
|
||||
const bool typing = tox_event_friend_typing_get_typing(event);
|
||||
|
||||
state->friend_is_typing = typing;
|
||||
}
|
||||
|
||||
@ -28,7 +32,7 @@ static void test_typing(AutoTox *autotoxes)
|
||||
{
|
||||
time_t cur_time = time(nullptr);
|
||||
|
||||
tox_callback_friend_typing(autotoxes[1].tox, &typing_callback);
|
||||
tox_events_callback_friend_typing(autotoxes[1].dispatch, &typing_callback);
|
||||
tox_self_set_typing(autotoxes[0].tox, 0, true, nullptr);
|
||||
|
||||
do {
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user