fix: add testing-torrents params
This commit is contained in:
parent
ecb56013a5
commit
3dfcf2a536
@ -209,6 +209,7 @@ pub struct QBittorrentDownloaderCreation {
|
||||
pub save_path: String,
|
||||
pub subscriber_id: i32,
|
||||
pub downloader_id: i32,
|
||||
pub wait_sync_timeout: Option<Duration>,
|
||||
}
|
||||
|
||||
pub type QBittorrentHashSelector = DownloadIdSelector<QBittorrentTask>;
|
||||
@ -354,7 +355,9 @@ impl QBittorrentDownloader {
|
||||
endpoint_url,
|
||||
subscriber_id: creation.subscriber_id,
|
||||
save_path: creation.save_path.into(),
|
||||
wait_sync_timeout: Duration::from_millis(10000),
|
||||
wait_sync_timeout: creation
|
||||
.wait_sync_timeout
|
||||
.unwrap_or(Duration::from_millis(10000)),
|
||||
downloader_id: creation.downloader_id,
|
||||
sync_watch: watch::channel(Utc::now()).0,
|
||||
sync_data: Arc::new(RwLock::new(QBittorrentSyncData::default())),
|
||||
@ -610,7 +613,7 @@ impl QBittorrentDownloader {
|
||||
let mut receiver = self.sync_watch.subscribe();
|
||||
while let Ok(()) = receiver.changed().await {
|
||||
let has_timeout = {
|
||||
let sync_time = receiver.borrow().clone();
|
||||
let sync_time = *receiver.borrow();
|
||||
sync_time
|
||||
.signed_duration_since(start_time)
|
||||
.num_milliseconds()
|
||||
@ -625,7 +628,7 @@ impl QBittorrentDownloader {
|
||||
}
|
||||
{
|
||||
let sync_data = &self.sync_data.read().await;
|
||||
if stop_wait_fn(&sync_data) {
|
||||
if stop_wait_fn(sync_data) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -827,6 +830,8 @@ impl Debug for QBittorrentDownloader {
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod tests {
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use super::*;
|
||||
use crate::{
|
||||
downloader::core::DownloadIdSelectorTrait,
|
||||
@ -842,27 +847,47 @@ pub mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct MockFileItem {
|
||||
path: String,
|
||||
size: u64,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
struct MockRequest {
|
||||
id: String,
|
||||
file_list: Vec<MockFileItem>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[allow(dead_code)]
|
||||
pub struct MockResponse {
|
||||
torrent_url: String,
|
||||
magnet_url: String,
|
||||
hash: String,
|
||||
}
|
||||
|
||||
#[cfg(feature = "testcontainers")]
|
||||
pub async fn create_torrents_testcontainers()
|
||||
-> RResult<testcontainers::ContainerRequest<testcontainers::GenericImage>> {
|
||||
use testcontainers::{
|
||||
GenericImage,
|
||||
core::{
|
||||
ContainerPort,
|
||||
// ReuseDirective,
|
||||
WaitFor,
|
||||
},
|
||||
core::{ContainerPort, WaitFor},
|
||||
};
|
||||
use testcontainers_modules::testcontainers::ImageExt;
|
||||
|
||||
use crate::test_utils::testcontainers::ContainerRequestEnhancedExt;
|
||||
|
||||
let container = GenericImage::new("ghcr.io/dumtruck/konobangu-testing-torrents", "latest")
|
||||
.with_exposed_port()
|
||||
.with_wait_for(WaitFor::message_on_stderr("Connection to localhost"))
|
||||
.with_wait_for(WaitFor::message_on_stdout("Listening on"))
|
||||
.with_mapped_port(6080, ContainerPort::Tcp(6080))
|
||||
.with_mapped_port(6081, ContainerPort::Tcp(6081))
|
||||
.with_mapped_port(6082, ContainerPort::Tcp(6082))
|
||||
// .with_reuse(ReuseDirective::Always)
|
||||
.with_default_log_consumer()
|
||||
.with_prune_existed_label("qbit-downloader", true, true)
|
||||
.with_prune_existed_label("konobangu-testing-torrents", true, true)
|
||||
.await?;
|
||||
|
||||
Ok(container)
|
||||
@ -913,17 +938,40 @@ pub mod tests {
|
||||
use tokio::io::AsyncReadExt;
|
||||
|
||||
tracing_subscriber::fmt()
|
||||
.with_max_level(tracing::Level::DEBUG)
|
||||
.with_max_level(tracing::Level::TRACE)
|
||||
.with_test_writer()
|
||||
.init();
|
||||
|
||||
let image = create_qbit_testcontainers().await?;
|
||||
let torrents_image = create_torrents_testcontainers().await?;
|
||||
let torrents_container = torrents_image.start().await?;
|
||||
|
||||
let container = image.start().await?;
|
||||
let torrents_req = MockRequest {
|
||||
id: "test".into(),
|
||||
file_list: vec![MockFileItem {
|
||||
path: "test.torrent".into(),
|
||||
size: 1024,
|
||||
}],
|
||||
};
|
||||
|
||||
let torrent_res: MockResponse = reqwest::Client::builder()
|
||||
.pool_max_idle_per_host(0)
|
||||
.build()?
|
||||
.post("http://127.0.0.1:6080/api/torrents/mock")
|
||||
.json(&torrents_req)
|
||||
.send()
|
||||
.await?
|
||||
.json()
|
||||
.await?;
|
||||
|
||||
let qbit_image = create_qbit_testcontainers().await?;
|
||||
let qbit_container = qbit_image.start().await?;
|
||||
|
||||
let mut logs = String::new();
|
||||
|
||||
container.stdout(false).read_to_string(&mut logs).await?;
|
||||
qbit_container
|
||||
.stdout(false)
|
||||
.read_to_string(&mut logs)
|
||||
.await?;
|
||||
|
||||
let username = logs
|
||||
.lines()
|
||||
@ -940,7 +988,10 @@ pub mod tests {
|
||||
let password = logs
|
||||
.lines()
|
||||
.find_map(|line| {
|
||||
if line.contains("A temporary password is provided for this session") {
|
||||
if line.contains(
|
||||
"A temporary password is provided for this
|
||||
session",
|
||||
) {
|
||||
line.split_whitespace().last()
|
||||
} else {
|
||||
None
|
||||
@ -951,7 +1002,15 @@ pub mod tests {
|
||||
|
||||
tracing::info!(username, password);
|
||||
|
||||
test_qbittorrent_downloader_impl(Some(username), Some(password)).await?;
|
||||
test_qbittorrent_downloader_impl(
|
||||
torrent_res.torrent_url,
|
||||
torrent_res.hash,
|
||||
Some(username),
|
||||
Some(password),
|
||||
)
|
||||
.await?;
|
||||
|
||||
torrents_container.stop().await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -965,31 +1024,25 @@ pub mod tests {
|
||||
let http_client = build_testing_http_client()?;
|
||||
let base_save_path = Path::new(get_tmp_qbit_test_folder());
|
||||
|
||||
let hash = "47ee2d69e7f19af783ad896541a07b012676f858".to_string();
|
||||
|
||||
let mut downloader = QBittorrentDownloader::from_creation(QBittorrentDownloaderCreation {
|
||||
let downloader = QBittorrentDownloader::from_creation(QBittorrentDownloaderCreation {
|
||||
endpoint: "http://127.0.0.1:8080".to_string(),
|
||||
password: password.unwrap_or_default().to_string(),
|
||||
username: username.unwrap_or_default().to_string(),
|
||||
subscriber_id: 0,
|
||||
save_path: base_save_path.to_string(),
|
||||
downloader_id: 0,
|
||||
wait_sync_timeout: Some(Duration::from_secs(3)),
|
||||
})
|
||||
.await?;
|
||||
|
||||
downloader.wait_sync_timeout = Duration::from_secs(3);
|
||||
|
||||
downloader.check_connection().await?;
|
||||
|
||||
downloader
|
||||
.remove_torrents(vec![hash.clone()].into())
|
||||
.remove_torrents(vec![torrent_hash.clone()].into())
|
||||
.await?;
|
||||
|
||||
let torrent_source = HashTorrentSource::from_url_and_http_client(
|
||||
&http_client,
|
||||
format!("https://mikanani.me/Download/20240301/{}.torrent", &hash),
|
||||
)
|
||||
.await?;
|
||||
let torrent_source =
|
||||
HashTorrentSource::from_url_and_http_client(&http_client, torrent_url).await?;
|
||||
|
||||
let folder_name = format!("torrent_test_{}", Utc::now().timestamp());
|
||||
let save_path = base_save_path.join(&folder_name);
|
||||
@ -1006,13 +1059,13 @@ pub mod tests {
|
||||
let get_torrent = async || -> Result<QBittorrentTask, DownloaderError> {
|
||||
let torrent_infos = downloader
|
||||
.query_downloads(QBittorrentSelector::Hash(QBittorrentHashSelector::from_id(
|
||||
hash.clone(),
|
||||
torrent_hash.clone(),
|
||||
)))
|
||||
.await?;
|
||||
|
||||
let result = torrent_infos
|
||||
.into_iter()
|
||||
.find(|t| t.hash_info() == hash)
|
||||
.find(|t| t.hash_info() == torrent_hash)
|
||||
.whatever_context::<_, DownloaderError>("no bittorrent")?;
|
||||
|
||||
Ok(result)
|
||||
@ -1032,7 +1085,7 @@ pub mod tests {
|
||||
let test_tag = format!("test_tag_{}", Utc::now().timestamp());
|
||||
|
||||
downloader
|
||||
.add_torrent_tags(vec![hash.clone()], vec![test_tag.clone()])
|
||||
.add_torrent_tags(vec![torrent_hash.clone()], vec![test_tag.clone()])
|
||||
.await?;
|
||||
|
||||
let target_torrent = get_torrent().await?;
|
||||
@ -1042,7 +1095,7 @@ pub mod tests {
|
||||
let test_category = format!("test_category_{}", Utc::now().timestamp());
|
||||
|
||||
downloader
|
||||
.set_torrents_category(vec![hash.clone()], &test_category)
|
||||
.set_torrents_category(vec![torrent_hash.clone()], &test_category)
|
||||
.await?;
|
||||
|
||||
let target_torrent = get_torrent().await?;
|
||||
@ -1055,7 +1108,7 @@ pub mod tests {
|
||||
let moved_torrent_path = base_save_path.join(format!("moved_{}", Utc::now().timestamp()));
|
||||
|
||||
downloader
|
||||
.move_torrents(vec![hash.clone()], moved_torrent_path.as_str())
|
||||
.move_torrents(vec![torrent_hash.clone()], moved_torrent_path.as_str())
|
||||
.await?;
|
||||
|
||||
let target_torrent = get_torrent().await?;
|
||||
@ -1073,7 +1126,7 @@ pub mod tests {
|
||||
);
|
||||
|
||||
downloader
|
||||
.move_torrent_contents(&hash, |f| {
|
||||
.move_torrent_contents(&torrent_hash, |f| {
|
||||
f.replace(&folder_name, &format!("moved_{}", &folder_name))
|
||||
})
|
||||
.await?;
|
||||
@ -1096,7 +1149,7 @@ pub mod tests {
|
||||
);
|
||||
|
||||
downloader
|
||||
.remove_torrents(vec![hash.clone()].into())
|
||||
.remove_torrents(vec![torrent_hash.clone()].into())
|
||||
.await?;
|
||||
|
||||
let torrent_infos1 = downloader
|
||||
|
@ -79,7 +79,9 @@ where
|
||||
.await
|
||||
.map_err(|error| TestcontainersError::Other(Box::new(error)))?;
|
||||
|
||||
tracing::warn!(name = "stop running containers", result = ?remove_containers);
|
||||
if !remove_containers.is_empty() {
|
||||
tracing::warn!(name = "stop running containers", result = ?remove_containers);
|
||||
}
|
||||
}
|
||||
|
||||
let result = client
|
||||
@ -87,7 +89,13 @@ where
|
||||
.await
|
||||
.map_err(|err| TestcontainersError::Other(Box::new(err)))?;
|
||||
|
||||
tracing::warn!(name = "prune existed containers", result = ?result);
|
||||
if result
|
||||
.containers_deleted
|
||||
.as_ref()
|
||||
.is_some_and(|c| !c.is_empty())
|
||||
{
|
||||
tracing::warn!(name = "prune existed containers", result = ?result);
|
||||
}
|
||||
}
|
||||
|
||||
let result = self.with_labels([
|
||||
|
@ -8,11 +8,14 @@ FROM nodebt AS deps
|
||||
RUN mkdir -p /app/workspace
|
||||
WORKDIR /app
|
||||
COPY package.json /app/
|
||||
RUN pnpm approve-builds utf-8-validate node-datachannel utp-native
|
||||
RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --no-frozen-lockfile
|
||||
|
||||
FROM deps AS app
|
||||
|
||||
COPY main.ts /app/
|
||||
|
||||
EXPOSE 6080
|
||||
EXPOSE 6081
|
||||
EXPOSE 6082
|
||||
|
||||
CMD [ "npm", "start" ]
|
||||
|
@ -1,5 +1,11 @@
|
||||
# Konobangu Testing Torrents Container
|
||||
|
||||
## Development
|
||||
|
||||
```bash
|
||||
pnpm install --ignore-workspace
|
||||
```
|
||||
|
||||
## Build
|
||||
|
||||
```bash
|
||||
@ -17,4 +23,4 @@ docker run --network_mode=host --name konobangu-testing-torrents konobangu-testi
|
||||
```bash
|
||||
docker tag konobangu-testing-torrents:latest ghcr.io/dumtruck/konobangu-testing-torrents:latest
|
||||
docker push ghcr.io/dumtruck/konobangu-testing-torrents:latest
|
||||
```
|
||||
```
|
||||
|
@ -1,5 +1,8 @@
|
||||
services:
|
||||
konobangu-testing-torrents:
|
||||
build: .
|
||||
network_mode: host
|
||||
container_name: konobangu-testing-torrents
|
||||
konobangu-testing-torrents:
|
||||
build: .
|
||||
ports:
|
||||
- 6080:6080
|
||||
- 6081:6081
|
||||
- 6082:6082
|
||||
container_name: konobangu-testing-torrents
|
||||
|
@ -29,9 +29,9 @@ app.register(fastifyStatic, {
|
||||
});
|
||||
|
||||
const tracker = new TrackerServer({
|
||||
udp: true, // enable udp server? [default=true]
|
||||
udp: false, // enable udp server? [default=true]
|
||||
http: true, // enable http server? [default=true]
|
||||
ws: true, // enable websocket server? [default=true]
|
||||
ws: false, // enable websocket server? [default=true]
|
||||
stats: true, // enable web-based statistics? [default=true]
|
||||
trustProxy: true, // enable trusting x-forwarded-for header for remote IP [default=false]
|
||||
});
|
||||
@ -50,12 +50,13 @@ interface RequestSchema {
|
||||
interface ResponseSchema {
|
||||
torrentUrl: string;
|
||||
magnetUrl: string;
|
||||
hash: string;
|
||||
}
|
||||
|
||||
// Start local Tracker
|
||||
async function startTracker(): Promise<void> {
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
tracker.listen(TRACKER_PORT, 'localhost', () => {
|
||||
tracker.listen(TRACKER_PORT, '0.0.0.0', () => {
|
||||
console.log(`Tracker listening on port ${TRACKER_PORT}`);
|
||||
resolve();
|
||||
});
|
||||
@ -85,6 +86,7 @@ async function generateMockFile(filePath: string, size: number) {
|
||||
await fsp.mkdir(dir, { recursive: true });
|
||||
}
|
||||
|
||||
await fsp.writeFile(filePath, Buffer.alloc(0));
|
||||
await fsp.truncate(filePath, size);
|
||||
}
|
||||
|
||||
@ -162,6 +164,7 @@ app.post<{ Body: RequestSchema }>('/api/torrents/mock', async (req, _reply) => {
|
||||
return {
|
||||
torrentUrl: `${API_BASE_URL}${id}.torrent`,
|
||||
magnetUrl,
|
||||
hash: torrent.infoHash,
|
||||
} as ResponseSchema;
|
||||
});
|
||||
|
||||
@ -169,7 +172,8 @@ app.post<{ Body: RequestSchema }>('/api/torrents/mock', async (req, _reply) => {
|
||||
async function main() {
|
||||
try {
|
||||
await startTracker();
|
||||
await app.listen({ port: API_PORT, host: LOCAL_IP });
|
||||
const address = await app.listen({ port: API_PORT, host: '0.0.0.0' });
|
||||
console.log('Listening on:', address);
|
||||
} catch (err) {
|
||||
console.error('Startup error:', err);
|
||||
webTorrent.destroy();
|
||||
|
@ -18,5 +18,14 @@
|
||||
"devDependencies": {
|
||||
"@types/create-torrent": "^5.0.2",
|
||||
"@types/webtorrent": "^0.110.0"
|
||||
},
|
||||
"pnpm": {
|
||||
"onlyBuiltDependencies": [
|
||||
"bufferutil",
|
||||
"esbuild",
|
||||
"node-datachannel",
|
||||
"utf-8-validate",
|
||||
"utp-native"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
2461
packages/testing-torrents/pnpm-lock.yaml
generated
Normal file
2461
packages/testing-torrents/pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load Diff
1567
pnpm-lock.yaml
generated
1567
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@ -1,3 +1,11 @@
|
||||
packages:
|
||||
- packages/*
|
||||
- apps/*
|
||||
- packages/*
|
||||
- apps/*
|
||||
- '!packages/testing-torrents'
|
||||
onlyBuiltDependencies:
|
||||
- '@biomejs/biome'
|
||||
- bufferutil
|
||||
- core-js
|
||||
- esbuild
|
||||
- sharp
|
||||
- utf-8-validate
|
||||
|
Loading…
Reference in New Issue
Block a user