mirror of
https://github.com/icewind1991/notify-redis.git
synced 2026-06-03 18:24:12 +02:00
better tests
This commit is contained in:
parent
49652b7288
commit
90af4a497c
9 changed files with 568 additions and 163 deletions
71
.github/workflows/rust.yml
vendored
Normal file
71
.github/workflows/rust.yml
vendored
Normal file
|
|
@ -0,0 +1,71 @@
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
name: CI
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
check:
|
||||||
|
name: Check
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- uses: actions-rs/toolchain@v1
|
||||||
|
with:
|
||||||
|
profile: minimal
|
||||||
|
toolchain: stable
|
||||||
|
override: true
|
||||||
|
- uses: Swatinem/rust-cache@v1
|
||||||
|
- uses: actions-rs/cargo@v1
|
||||||
|
with:
|
||||||
|
command: check
|
||||||
|
|
||||||
|
build:
|
||||||
|
name: Build
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
target:
|
||||||
|
- x86_64-unknown-linux-musl
|
||||||
|
- armv7-unknown-linux-musleabihf
|
||||||
|
- aarch64-unknown-linux-musl
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- uses: actions-rs/toolchain@v1
|
||||||
|
with:
|
||||||
|
profile: minimal
|
||||||
|
toolchain: stable
|
||||||
|
override: true
|
||||||
|
target: ${{ matrix.target }}
|
||||||
|
- uses: Swatinem/rust-cache@v1
|
||||||
|
- uses: actions-rs/cargo@v1
|
||||||
|
with:
|
||||||
|
use-cross: true
|
||||||
|
command: build
|
||||||
|
args: --release --target ${{ matrix.target }}
|
||||||
|
- uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: notify-redis-${{ matrix.target }}
|
||||||
|
path: target/${{ matrix.target }}/release/notify-redis
|
||||||
|
|
||||||
|
test:
|
||||||
|
name: Tests
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
|
||||||
|
services:
|
||||||
|
redis:
|
||||||
|
image: redis
|
||||||
|
ports:
|
||||||
|
- 6379:6379
|
||||||
|
options: --entrypoint redis-server
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- uses: actions-rs/toolchain@v1
|
||||||
|
with:
|
||||||
|
profile: minimal
|
||||||
|
toolchain: stable
|
||||||
|
override: true
|
||||||
|
- uses: Swatinem/rust-cache@v1
|
||||||
|
- uses: actions-rs/cargo@v1
|
||||||
|
with:
|
||||||
|
command: test
|
||||||
18
.travis.yml
18
.travis.yml
|
|
@ -1,18 +0,0 @@
|
||||||
sudo: required
|
|
||||||
services:
|
|
||||||
- docker
|
|
||||||
- redis-server
|
|
||||||
install:
|
|
||||||
- docker pull ekidd/rust-musl-builder:latest
|
|
||||||
script:
|
|
||||||
- "./travis-build.sh notify-redis ${TRAVIS_OS_NAME}"
|
|
||||||
- "./test.sh ./notify-redis-${TRAVIS_OS_NAME}"
|
|
||||||
deploy:
|
|
||||||
provider: releases
|
|
||||||
api_key:
|
|
||||||
secure: GBWfTW08qT3K9W9zeVteUJ9RTDnaIguH5Zoe7N+GOTPBGUDscL/3vfCOj5PyfhLgHuPXzlMAGCM42MZFknL5PXFO4ZMFuiTtcSbiSEQNPArQjDrWbCPxU9IrXN7W/94EEcdWmSSpkT/Fc3XRgx9z2BjUSfXCv4R4owwtRWhWlNNnmqVIe7OEfCQEKBCsuGB9PmLTShUd33ztVqVt2+WMC8kT9Wrk9KmeeEANx/K1rz18sMOphd7Ruqx9z1tLF0nFaRGBSRPV4EhpBGLahdglRtq9uvHFA4iMmpf1HWWE/TDVLI/tykE1B39gYfzEircLAJw+D6orO3kPsjqH8gzwwUyZKQr5OmEZUExtdHp/K606Doo3fwdWty3CqZYzDI+p4YwXDL8cI2TShGaQpXVwKXpJK+5RXrsYNY+tBvsQ2BpW4Z5US+uqESUBX4dbdrjZyXKfIJFHRpzn8COa02Hc0nFYf/hqakzTqTylVYTTQaZ4VdgPuU7zUFPHg7rBEPbuv0ncxDOgLjjYLHl00CSSsqiRezJzW2TUEFW6xXI8qz9QTnOAyVM4aBStxF1oAtOia4jcMu7gjIJeeAOZnYSqryW/Xy8YuzRE07axXNk90Uma+Gxn3zcgvGAdwct2jq+iPQ8yvqirCJFNMxfu8pDTYbLZcFNZEvOfLVQv9OmPNqE=
|
|
||||||
file: notify-redis-linux
|
|
||||||
skip_cleanup: true
|
|
||||||
on:
|
|
||||||
repo: icewind1991/notify-redis
|
|
||||||
tags: true
|
|
||||||
246
Cargo.lock
generated
246
Cargo.lock
generated
|
|
@ -194,12 +194,32 @@ version = "0.3.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
|
checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "getrandom"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if 1.0.0",
|
||||||
|
"libc",
|
||||||
|
"wasi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gimli"
|
name = "gimli"
|
||||||
version = "0.23.0"
|
version = "0.23.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f6503fe142514ca4799d4c26297c4248239fe8838d827db6bd6065c6ed29a6ce"
|
checksum = "f6503fe142514ca4799d4c26297c4248239fe8838d827db6bd6065c6ed29a6ce"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hermit-abi"
|
||||||
|
version = "0.1.18"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "idna"
|
name = "idna"
|
||||||
version = "0.2.2"
|
version = "0.2.2"
|
||||||
|
|
@ -237,6 +257,15 @@ dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "instant"
|
||||||
|
version = "0.1.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "61124eeebbd69b8190558df225adf7e4caafce0d743919e5d6b19652314ec5ec"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if 1.0.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "iovec"
|
name = "iovec"
|
||||||
version = "0.1.4"
|
version = "0.1.4"
|
||||||
|
|
@ -280,6 +309,15 @@ version = "0.2.86"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b7282d924be3275cec7f6756ff4121987bc6481325397dde6ba3e7802b1a8b1c"
|
checksum = "b7282d924be3275cec7f6756ff4121987bc6481325397dde6ba3e7802b1a8b1c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lock_api"
|
||||||
|
version = "0.4.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dd96ffd135b2fd7b973ac026d28085defbe8983df057ced3eb4f2130b0831312"
|
||||||
|
dependencies = [
|
||||||
|
"scopeguard",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "log"
|
name = "log"
|
||||||
version = "0.4.14"
|
version = "0.4.14"
|
||||||
|
|
@ -324,12 +362,25 @@ dependencies = [
|
||||||
"kernel32-sys",
|
"kernel32-sys",
|
||||||
"libc",
|
"libc",
|
||||||
"log",
|
"log",
|
||||||
"miow",
|
"miow 0.2.2",
|
||||||
"net2",
|
"net2",
|
||||||
"slab",
|
"slab",
|
||||||
"winapi 0.2.8",
|
"winapi 0.2.8",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mio"
|
||||||
|
version = "0.7.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dc250d6848c90d719ea2ce34546fb5df7af1d3fd189d10bf7bad80bfcebecd95"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"log",
|
||||||
|
"miow 0.3.6",
|
||||||
|
"ntapi",
|
||||||
|
"winapi 0.3.9",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mio-extras"
|
name = "mio-extras"
|
||||||
version = "2.0.6"
|
version = "2.0.6"
|
||||||
|
|
@ -338,7 +389,7 @@ checksum = "52403fe290012ce777c4626790c8951324a2b9e3316b3143779c72b029742f19"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"lazycell",
|
"lazycell",
|
||||||
"log",
|
"log",
|
||||||
"mio",
|
"mio 0.6.23",
|
||||||
"slab",
|
"slab",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
@ -354,6 +405,16 @@ dependencies = [
|
||||||
"ws2_32-sys",
|
"ws2_32-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "miow"
|
||||||
|
version = "0.3.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5a33c1b55807fbed163481b5ba66db4b2fa6cde694a5027be10fb724206c5897"
|
||||||
|
dependencies = [
|
||||||
|
"socket2",
|
||||||
|
"winapi 0.3.9",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "net2"
|
name = "net2"
|
||||||
version = "0.2.37"
|
version = "0.2.37"
|
||||||
|
|
@ -377,7 +438,7 @@ dependencies = [
|
||||||
"fsevent-sys",
|
"fsevent-sys",
|
||||||
"inotify",
|
"inotify",
|
||||||
"libc",
|
"libc",
|
||||||
"mio",
|
"mio 0.6.23",
|
||||||
"mio-extras",
|
"mio-extras",
|
||||||
"walkdir",
|
"walkdir",
|
||||||
"winapi 0.3.9",
|
"winapi 0.3.9",
|
||||||
|
|
@ -390,9 +451,21 @@ dependencies = [
|
||||||
"chrono",
|
"chrono",
|
||||||
"color-eyre",
|
"color-eyre",
|
||||||
"notify",
|
"notify",
|
||||||
|
"rand",
|
||||||
"redis",
|
"redis",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
"tempfile",
|
||||||
|
"tokio",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ntapi"
|
||||||
|
version = "0.3.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44"
|
||||||
|
dependencies = [
|
||||||
|
"winapi 0.3.9",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -414,6 +487,16 @@ dependencies = [
|
||||||
"autocfg",
|
"autocfg",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num_cpus"
|
||||||
|
version = "1.13.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3"
|
||||||
|
dependencies = [
|
||||||
|
"hermit-abi",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "object"
|
name = "object"
|
||||||
version = "0.23.0"
|
version = "0.23.0"
|
||||||
|
|
@ -432,6 +515,31 @@ version = "1.3.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2386b4ebe91c2f7f51082d4cefa145d030e33a1842a96b12e4885cc3c01f7a55"
|
checksum = "2386b4ebe91c2f7f51082d4cefa145d030e33a1842a96b12e4885cc3c01f7a55"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "parking_lot"
|
||||||
|
version = "0.11.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6d7744ac029df22dca6284efe4e898991d28e3085c706c972bcd7da4a27a15eb"
|
||||||
|
dependencies = [
|
||||||
|
"instant",
|
||||||
|
"lock_api",
|
||||||
|
"parking_lot_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "parking_lot_core"
|
||||||
|
version = "0.8.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fa7a782938e745763fe6907fc6ba86946d72f49fe7e21de074e08128a99fb018"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if 1.0.0",
|
||||||
|
"instant",
|
||||||
|
"libc",
|
||||||
|
"redox_syscall",
|
||||||
|
"smallvec",
|
||||||
|
"winapi 0.3.9",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "percent-encoding"
|
name = "percent-encoding"
|
||||||
version = "2.1.0"
|
version = "2.1.0"
|
||||||
|
|
@ -444,6 +552,12 @@ version = "0.2.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "439697af366c49a6d0a010c56a0d97685bc140ce0d377b13a2ea2aa42d64a827"
|
checksum = "439697af366c49a6d0a010c56a0d97685bc140ce0d377b13a2ea2aa42d64a827"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ppv-lite86"
|
||||||
|
version = "0.2.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.24"
|
version = "1.0.24"
|
||||||
|
|
@ -462,6 +576,46 @@ dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand"
|
||||||
|
version = "0.8.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"rand_chacha",
|
||||||
|
"rand_core",
|
||||||
|
"rand_hc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_chacha"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d"
|
||||||
|
dependencies = [
|
||||||
|
"ppv-lite86",
|
||||||
|
"rand_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_core"
|
||||||
|
version = "0.6.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "34cf66eb183df1c5876e2dcf6b13d57340741e8dc255b48e40a26de954d06ae7"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_hc"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73"
|
||||||
|
dependencies = [
|
||||||
|
"rand_core",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "redis"
|
name = "redis"
|
||||||
version = "0.20.0"
|
version = "0.20.0"
|
||||||
|
|
@ -486,6 +640,15 @@ dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "remove_dir_all"
|
||||||
|
version = "0.5.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
|
||||||
|
dependencies = [
|
||||||
|
"winapi 0.3.9",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc-demangle"
|
name = "rustc-demangle"
|
||||||
version = "0.1.18"
|
version = "0.1.18"
|
||||||
|
|
@ -507,6 +670,12 @@ dependencies = [
|
||||||
"winapi-util",
|
"winapi-util",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "scopeguard"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.123"
|
version = "1.0.123"
|
||||||
|
|
@ -553,12 +722,38 @@ dependencies = [
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "signal-hook-registry"
|
||||||
|
version = "1.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "16f1d0fef1604ba8f7a073c7e701f213e056707210e9020af4528e0101ce11a6"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "slab"
|
name = "slab"
|
||||||
version = "0.4.2"
|
version = "0.4.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
|
checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "smallvec"
|
||||||
|
version = "1.6.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "socket2"
|
||||||
|
version = "0.3.19"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "122e570113d28d773067fab24266b66753f6ea915758651696b6e35e49f88d6e"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if 1.0.0",
|
||||||
|
"libc",
|
||||||
|
"winapi 0.3.9",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "1.0.60"
|
version = "1.0.60"
|
||||||
|
|
@ -570,6 +765,20 @@ dependencies = [
|
||||||
"unicode-xid",
|
"unicode-xid",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tempfile"
|
||||||
|
version = "3.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if 1.0.0",
|
||||||
|
"libc",
|
||||||
|
"rand",
|
||||||
|
"redox_syscall",
|
||||||
|
"remove_dir_all",
|
||||||
|
"winapi 0.3.9",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thread_local"
|
name = "thread_local"
|
||||||
version = "1.1.3"
|
version = "1.1.3"
|
||||||
|
|
@ -605,6 +814,37 @@ version = "0.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
|
checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tokio"
|
||||||
|
version = "1.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e8190d04c665ea9e6b6a0dc45523ade572c088d2e6566244c1122671dbf4ae3a"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"bytes",
|
||||||
|
"libc",
|
||||||
|
"memchr",
|
||||||
|
"mio 0.7.8",
|
||||||
|
"num_cpus",
|
||||||
|
"once_cell",
|
||||||
|
"parking_lot",
|
||||||
|
"pin-project-lite",
|
||||||
|
"signal-hook-registry",
|
||||||
|
"tokio-macros",
|
||||||
|
"winapi 0.3.9",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tokio-macros"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "caf7b11a536f46a809a8a9f0bb4237020f70ecbf115b842360afb127ea2fda57"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tracing"
|
name = "tracing"
|
||||||
version = "0.1.24"
|
version = "0.1.24"
|
||||||
|
|
|
||||||
|
|
@ -11,3 +11,8 @@ chrono = { version = "0.4", features = ["serde"] }
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
color-eyre = "0.5"
|
color-eyre = "0.5"
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
rand = "0.8.3"
|
||||||
|
tokio = { version = "1.2", features = ["full"] }
|
||||||
|
tempfile = "3"
|
||||||
83
src/lib.rs
Normal file
83
src/lib.rs
Normal file
|
|
@ -0,0 +1,83 @@
|
||||||
|
use chrono::{DateTime, Timelike, Utc};
|
||||||
|
use color_eyre::{eyre::WrapErr, Result};
|
||||||
|
use notify::{DebouncedEvent, RecommendedWatcher, RecursiveMode, Watcher};
|
||||||
|
use redis::{Client, Commands, Connection, IntoConnectionInfo};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::path::{Path, PathBuf};
|
||||||
|
use std::sync::mpsc::channel;
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
#[serde(tag = "event")]
|
||||||
|
#[serde(rename_all = "snake_case")]
|
||||||
|
pub enum Event {
|
||||||
|
Modify {
|
||||||
|
path: PathBuf,
|
||||||
|
time: DateTime<Utc>,
|
||||||
|
},
|
||||||
|
Move {
|
||||||
|
from: PathBuf,
|
||||||
|
to: PathBuf,
|
||||||
|
time: DateTime<Utc>,
|
||||||
|
},
|
||||||
|
Delete {
|
||||||
|
path: PathBuf,
|
||||||
|
time: DateTime<Utc>,
|
||||||
|
},
|
||||||
|
None,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<DebouncedEvent> for Event {
|
||||||
|
fn from(event: DebouncedEvent) -> Self {
|
||||||
|
let time = Utc::now().with_nanosecond(0).unwrap();
|
||||||
|
|
||||||
|
match event {
|
||||||
|
DebouncedEvent::Write(path)
|
||||||
|
| DebouncedEvent::Create(path)
|
||||||
|
| DebouncedEvent::Chmod(path) => Event::Modify { path, time },
|
||||||
|
DebouncedEvent::Rename(from, to) => Event::Move { from, to, time },
|
||||||
|
DebouncedEvent::Remove(path) => Event::Delete { path, time },
|
||||||
|
_ => Event::None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn watch(
|
||||||
|
path: impl AsRef<Path>,
|
||||||
|
redis_connect: impl IntoConnectionInfo,
|
||||||
|
redis_list: &str,
|
||||||
|
debounce: Duration,
|
||||||
|
) -> Result<()> {
|
||||||
|
let (tx, rx) = channel();
|
||||||
|
|
||||||
|
let mut watcher: RecommendedWatcher = Watcher::new(tx, debounce)?;
|
||||||
|
let client = Client::open(redis_connect).wrap_err("Invalid redis connection")?;
|
||||||
|
let mut con = client
|
||||||
|
.get_connection()
|
||||||
|
.wrap_err("Failed to open redis connection")?;
|
||||||
|
|
||||||
|
watcher.watch(path, RecursiveMode::Recursive)?;
|
||||||
|
|
||||||
|
while let Ok(event) = rx.recv() {
|
||||||
|
push_event(event, &mut con, redis_list).wrap_err("Failed to send event to redis")?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn push_event(event: DebouncedEvent, con: &mut Connection, list: &str) -> Result<()> {
|
||||||
|
match format_event(event) {
|
||||||
|
Some(formatted_event) => {
|
||||||
|
println!("{}", formatted_event);
|
||||||
|
Ok(con.lpush(list, formatted_event)?)
|
||||||
|
}
|
||||||
|
None => Ok(()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn format_event(event: DebouncedEvent) -> Option<String> {
|
||||||
|
let event: Event = event.into();
|
||||||
|
match &event {
|
||||||
|
Event::None => None,
|
||||||
|
_ => serde_json::to_string(&event).ok(),
|
||||||
|
}
|
||||||
|
}
|
||||||
81
src/main.rs
81
src/main.rs
|
|
@ -1,87 +1,12 @@
|
||||||
use chrono::{DateTime, Timelike, Utc};
|
use color_eyre::Result;
|
||||||
use color_eyre::{eyre::WrapErr, Result};
|
use notify_redis::watch;
|
||||||
use notify::{DebouncedEvent, RecommendedWatcher, RecursiveMode, Watcher};
|
|
||||||
use redis::{Client, Commands, Connection};
|
|
||||||
use serde::Serialize;
|
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::path::PathBuf;
|
|
||||||
use std::sync::mpsc::channel;
|
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
#[derive(Serialize, Debug)]
|
|
||||||
#[serde(tag = "event")]
|
|
||||||
#[serde(rename_all = "snake_case")]
|
|
||||||
enum Event {
|
|
||||||
Modify {
|
|
||||||
path: PathBuf,
|
|
||||||
time: DateTime<Utc>,
|
|
||||||
},
|
|
||||||
Move {
|
|
||||||
from: PathBuf,
|
|
||||||
to: PathBuf,
|
|
||||||
time: DateTime<Utc>,
|
|
||||||
},
|
|
||||||
Delete {
|
|
||||||
path: PathBuf,
|
|
||||||
time: DateTime<Utc>,
|
|
||||||
},
|
|
||||||
None,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<DebouncedEvent> for Event {
|
|
||||||
fn from(event: DebouncedEvent) -> Self {
|
|
||||||
let time = Utc::now().with_nanosecond(0).unwrap();
|
|
||||||
|
|
||||||
match event {
|
|
||||||
DebouncedEvent::Write(path)
|
|
||||||
| DebouncedEvent::Create(path)
|
|
||||||
| DebouncedEvent::Chmod(path) => Event::Modify { path, time },
|
|
||||||
DebouncedEvent::Rename(from, to) => Event::Move { from, to, time },
|
|
||||||
DebouncedEvent::Remove(path) => Event::Delete { path, time },
|
|
||||||
_ => Event::None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn watch(path: &str, redis_connect: &str, redis_list: &str) -> Result<()> {
|
|
||||||
let (tx, rx) = channel();
|
|
||||||
|
|
||||||
let mut watcher: RecommendedWatcher = Watcher::new(tx, Duration::from_secs(2))?;
|
|
||||||
let client = Client::open(redis_connect).wrap_err("Invalid redis connection")?;
|
|
||||||
let mut con = client
|
|
||||||
.get_connection()
|
|
||||||
.wrap_err("Failed to open redis connection")?;
|
|
||||||
|
|
||||||
watcher.watch(path, RecursiveMode::Recursive)?;
|
|
||||||
|
|
||||||
while let Ok(event) = rx.recv() {
|
|
||||||
push_event(event, &mut con, redis_list).wrap_err("Failed to send event to redis")?;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn push_event(event: DebouncedEvent, con: &mut Connection, list: &str) -> Result<()> {
|
|
||||||
match format_event(event) {
|
|
||||||
Some(formatted_event) => {
|
|
||||||
println!("{}", formatted_event);
|
|
||||||
Ok(con.lpush(list, formatted_event)?)
|
|
||||||
}
|
|
||||||
None => Ok(()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn format_event(event: DebouncedEvent) -> Option<String> {
|
|
||||||
let event: Event = event.into();
|
|
||||||
match &event {
|
|
||||||
Event::None => None,
|
|
||||||
_ => serde_json::to_string(&event).ok(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() -> Result<()> {
|
fn main() -> Result<()> {
|
||||||
let args: Vec<_> = env::args().collect();
|
let args: Vec<_> = env::args().collect();
|
||||||
if let [_, path, redis, list] = args.as_slice() {
|
if let [_, path, redis, list] = args.as_slice() {
|
||||||
watch(path, redis, list)?;
|
watch(path, redis.as_str(), list, Duration::from_secs(2))?;
|
||||||
} else {
|
} else {
|
||||||
println!("usage: {} <path> <redis_connect> <redis_list>", args[0])
|
println!("usage: {} <path> <redis_connect> <redis_list>", args[0])
|
||||||
}
|
}
|
||||||
|
|
|
||||||
56
test.sh
56
test.sh
|
|
@ -1,56 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
function assert_notify {
|
|
||||||
actual="$(echo $(redis-cli rpop notify) | sed -e 's/,\"time\":[^Z]*Z\"//g')" # strip time
|
|
||||||
if [ "$actual" != "$1" ]
|
|
||||||
then
|
|
||||||
echo "'$actual' not equal to expected '$1'"
|
|
||||||
killall $(basename $bin)
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
mkdir -p test
|
|
||||||
rm test/*
|
|
||||||
redis-cli del notify
|
|
||||||
|
|
||||||
bin=$1;
|
|
||||||
: ${bin:="target/x86_64-unknown-linux-musl/release/notify-redis"}
|
|
||||||
|
|
||||||
echo "running tests with $bin"
|
|
||||||
|
|
||||||
$bin "$PWD/test" redis://localhost notify &
|
|
||||||
|
|
||||||
sleep 1
|
|
||||||
|
|
||||||
echo foo > test/foo.txt
|
|
||||||
sleep 2
|
|
||||||
|
|
||||||
assert_notify "{\"event\":\"modify\",\"path\":\"$(pwd)/test/foo.txt\"}"
|
|
||||||
assert_notify ''
|
|
||||||
|
|
||||||
mv test/foo.txt test/bar.txt
|
|
||||||
sleep 2
|
|
||||||
|
|
||||||
assert_notify "{\"event\":\"move\",\"from\":\"$(pwd)/test/foo.txt\",\"to\":\"$(pwd)/test/bar.txt\"}"
|
|
||||||
assert_notify ""
|
|
||||||
|
|
||||||
rm test/bar.txt
|
|
||||||
echo asd > test/bar.txt
|
|
||||||
|
|
||||||
sleep 2
|
|
||||||
|
|
||||||
assert_notify "{\"event\":\"modify\",\"path\":\"$(pwd)/test/bar.txt\"}"
|
|
||||||
assert_notify ""
|
|
||||||
|
|
||||||
rm test/bar.txt
|
|
||||||
sleep 2
|
|
||||||
echo asd > test/bar.txt
|
|
||||||
|
|
||||||
sleep 2
|
|
||||||
|
|
||||||
assert_notify "{\"event\":\"delete\",\"path\":\"$(pwd)/test/bar.txt\"}"
|
|
||||||
assert_notify "{\"event\":\"modify\",\"path\":\"$(pwd)/test/bar.txt\"}"
|
|
||||||
assert_notify ""
|
|
||||||
|
|
||||||
killall $(basename $bin)
|
|
||||||
162
tests/tests.rs
Normal file
162
tests/tests.rs
Normal file
|
|
@ -0,0 +1,162 @@
|
||||||
|
use notify_redis::{watch, Event};
|
||||||
|
use redis::{Client, Commands, Connection, ConnectionInfo};
|
||||||
|
use std::fs::{remove_file, rename, write};
|
||||||
|
use std::path::Path;
|
||||||
|
use std::thread::sleep;
|
||||||
|
use std::time::Duration;
|
||||||
|
use tempfile::tempdir;
|
||||||
|
|
||||||
|
fn cleanup(redis: ConnectionInfo, list: &str) {
|
||||||
|
let client = Client::open(redis).unwrap();
|
||||||
|
let mut con = client.get_connection().unwrap();
|
||||||
|
con.del::<_, ()>(list).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
struct EventList {
|
||||||
|
redis: Connection,
|
||||||
|
list: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EventList {
|
||||||
|
fn new(redis: ConnectionInfo, list: &str) -> Self {
|
||||||
|
let client = Client::open(redis).unwrap();
|
||||||
|
let redis = client.get_connection().unwrap();
|
||||||
|
EventList {
|
||||||
|
redis,
|
||||||
|
list: list.into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Event> {
|
||||||
|
let raw: Option<String> = self.redis.rpop(&self.list).unwrap();
|
||||||
|
raw.map(|raw| serde_json::from_str(&raw).unwrap())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn spawn_watch(
|
||||||
|
path: &Path,
|
||||||
|
redis_connect: ConnectionInfo,
|
||||||
|
list: &str,
|
||||||
|
) -> std::thread::JoinHandle<()> {
|
||||||
|
let path = path.to_path_buf();
|
||||||
|
let list = list.to_string();
|
||||||
|
std::thread::spawn(move || {
|
||||||
|
if let Err(e) = watch(path, redis_connect, &list, Duration::from_millis(1)) {
|
||||||
|
eprintln!("watch error {:#}", e);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_basic() {
|
||||||
|
let list = format!("notify_redis_test_{}", rand::random::<u16>());
|
||||||
|
let redis_connect: ConnectionInfo = "redis://localhost".parse().unwrap();
|
||||||
|
cleanup(redis_connect.clone(), &list);
|
||||||
|
let dir = tempdir().unwrap();
|
||||||
|
let mut event_list = EventList::new(redis_connect.clone(), &list);
|
||||||
|
spawn_watch(dir.path(), redis_connect.clone(), &list);
|
||||||
|
|
||||||
|
sleep(Duration::from_millis(10));
|
||||||
|
|
||||||
|
write(dir.path().join("foo.txt"), "foo").unwrap();
|
||||||
|
|
||||||
|
sleep(Duration::from_millis(10));
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
matches!(event_list.next(), Some(Event::Modify {path ,..}) if path.ends_with("foo.txt"))
|
||||||
|
);
|
||||||
|
assert!(matches!(event_list.next(), None));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_rename_debounce() {
|
||||||
|
let list = format!("notify_redis_test_{}", rand::random::<u16>());
|
||||||
|
let redis_connect: ConnectionInfo = "redis://localhost".parse().unwrap();
|
||||||
|
cleanup(redis_connect.clone(), &list);
|
||||||
|
let dir = tempdir().unwrap();
|
||||||
|
let mut event_list = EventList::new(redis_connect.clone(), &list);
|
||||||
|
spawn_watch(dir.path(), redis_connect.clone(), &list);
|
||||||
|
|
||||||
|
sleep(Duration::from_millis(10));
|
||||||
|
|
||||||
|
write(dir.path().join("foo.txt"), "foo").unwrap();
|
||||||
|
rename(dir.path().join("foo.txt"), dir.path().join("bar.txt")).unwrap();
|
||||||
|
|
||||||
|
sleep(Duration::from_millis(10));
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
matches!(event_list.next(), Some(Event::Modify {path ,..}) if path.ends_with("bar.txt"))
|
||||||
|
);
|
||||||
|
assert!(matches!(event_list.next(), None));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_rename() {
|
||||||
|
let list = format!("notify_redis_test_{}", rand::random::<u16>());
|
||||||
|
let redis_connect: ConnectionInfo = "redis://localhost".parse().unwrap();
|
||||||
|
cleanup(redis_connect.clone(), &list);
|
||||||
|
let dir = tempdir().unwrap();
|
||||||
|
let mut event_list = EventList::new(redis_connect.clone(), &list);
|
||||||
|
spawn_watch(dir.path(), redis_connect.clone(), &list);
|
||||||
|
|
||||||
|
sleep(Duration::from_millis(10));
|
||||||
|
|
||||||
|
write(dir.path().join("foo.txt"), "foo").unwrap();
|
||||||
|
sleep(Duration::from_millis(10));
|
||||||
|
rename(dir.path().join("foo.txt"), dir.path().join("bar.txt")).unwrap();
|
||||||
|
|
||||||
|
sleep(Duration::from_millis(10));
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
matches!(event_list.next(), Some(Event::Modify {path ,..}) if path.ends_with("foo.txt"))
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
matches!(event_list.next(), Some(Event::Move {from, to ,..}) if from.ends_with("foo.txt") && to.ends_with("bar.txt"))
|
||||||
|
);
|
||||||
|
assert!(matches!(dbg!(event_list.next()), None));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_delete() {
|
||||||
|
let list = format!("notify_redis_test_{}", rand::random::<u16>());
|
||||||
|
let redis_connect: ConnectionInfo = "redis://localhost".parse().unwrap();
|
||||||
|
cleanup(redis_connect.clone(), &list);
|
||||||
|
let dir = tempdir().unwrap();
|
||||||
|
let mut event_list = EventList::new(redis_connect.clone(), &list);
|
||||||
|
spawn_watch(dir.path(), redis_connect.clone(), &list);
|
||||||
|
|
||||||
|
sleep(Duration::from_millis(10));
|
||||||
|
|
||||||
|
write(dir.path().join("foo.txt"), "foo").unwrap();
|
||||||
|
sleep(Duration::from_millis(10));
|
||||||
|
remove_file(dir.path().join("foo.txt")).unwrap();
|
||||||
|
|
||||||
|
sleep(Duration::from_millis(10));
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
matches!(event_list.next(), Some(Event::Modify {path ,..}) if path.ends_with("foo.txt"))
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
matches!(event_list.next(), Some(Event::Delete {path ,..}) if path.ends_with("foo.txt"))
|
||||||
|
);
|
||||||
|
assert!(matches!(dbg!(event_list.next()), None));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_delete_debounce() {
|
||||||
|
let list = format!("notify_redis_test_{}", rand::random::<u16>());
|
||||||
|
let redis_connect: ConnectionInfo = "redis://localhost".parse().unwrap();
|
||||||
|
cleanup(redis_connect.clone(), &list);
|
||||||
|
let dir = tempdir().unwrap();
|
||||||
|
let mut event_list = EventList::new(redis_connect.clone(), &list);
|
||||||
|
spawn_watch(dir.path(), redis_connect.clone(), &list);
|
||||||
|
|
||||||
|
sleep(Duration::from_millis(10));
|
||||||
|
|
||||||
|
write(dir.path().join("foo.txt"), "foo").unwrap();
|
||||||
|
remove_file(dir.path().join("foo.txt")).unwrap();
|
||||||
|
|
||||||
|
sleep(Duration::from_millis(10));
|
||||||
|
|
||||||
|
assert!(matches!(dbg!(event_list.next()), None));
|
||||||
|
}
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
echo "Building static binaries using ekidd/rust-musl-builder"
|
|
||||||
docker build -t build-"$1"-image .
|
|
||||||
docker run -it --name build-"$1" build-"$1"-image
|
|
||||||
docker cp build-"$1":/home/rust/src/target/x86_64-unknown-linux-musl/release/"$1" "$1-$2"
|
|
||||||
docker rm build-"$1"
|
|
||||||
docker rmi build-"$1"-image
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue