mirror of
https://github.com/storytold/artcraft.git
synced 2026-10-25 02:29:37 +00:00
more thorough
This commit is contained in:
+1
-1
@@ -24,4 +24,4 @@
|
||||
pub mod support;
|
||||
|
||||
mod seedance_2p0;
|
||||
mod seedance_2p5_tests;
|
||||
mod seedance_2p5;
|
||||
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
//! Seedance 2.5 family pricing tests.
|
||||
|
||||
mod seedance_2p5_tests;
|
||||
+967
@@ -0,0 +1,967 @@
|
||||
//! Seedance 2.5 family pricing tests: 2.5 and 2.5 Ultra through the real
|
||||
//! generate endpoint against the test database, asserting exact wallet
|
||||
//! debits — including the reference-video input-seconds dimension.
|
||||
//!
|
||||
//! Rate cards (ceil-rounded once):
|
||||
//! - Seedance 2.5: 480p 11.76954733 ¢/s, 720p 26.70781893 ¢/s;
|
||||
//! with video refs 480p 7.24279835 ¢/s, 720p 15.84362140 ¢/s over
|
||||
//! (output + input) seconds
|
||||
//! - Seedance 2.5 Ultra: 480p 13.90946502 ¢/s, 720p 31.56378601 ¢/s;
|
||||
//! with video refs 480p 8.55967078 ¢/s, 720p 18.72427984 ¢/s
|
||||
//!
|
||||
//! Only 480p and 720p are offered (1080p/4K downgrade to 720p), durations
|
||||
//! run 4-30s, and every request generates a single video regardless of the
|
||||
//! requested batch size.
|
||||
|
||||
use enums::common::generation::common_resolution::CommonResolution;
|
||||
use enums::common::generation::common_video_model::CommonVideoModel;
|
||||
|
||||
use crate::http_server::endpoints::omni_gen::generate::video::tests::support::{
|
||||
assert_reference_video_charge_then_refund, assert_successful_generation_charges,
|
||||
assert_variant_charges_premium, Batch, CreditsDelta, ExpectedCredits, Seconds, TestHarness,
|
||||
};
|
||||
|
||||
// ── Seedance 2.5 ──
|
||||
mod seedance_2p5 {
|
||||
use super::*;
|
||||
|
||||
/// Every duration 4-30s at every resolution, single video.
|
||||
/// Seedance 2.5 offers 480p and 720p; 1080p and 4K downgrade to 720p (and price accordingly).
|
||||
#[tokio::test]
|
||||
#[cfg_attr(feature = "skip_database_tests", ignore)]
|
||||
async fn charges_every_duration_at_every_resolution() {
|
||||
let harness = TestHarness::create().await;
|
||||
|
||||
let cases: &[(Option<CommonResolution>, Seconds, Batch, ExpectedCredits)] = &[
|
||||
(Some(CommonResolution::FourEightyP), Seconds(4), Batch(1), ExpectedCredits(48)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(5), Batch(1), ExpectedCredits(59)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(6), Batch(1), ExpectedCredits(71)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(7), Batch(1), ExpectedCredits(83)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(8), Batch(1), ExpectedCredits(95)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(9), Batch(1), ExpectedCredits(106)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(10), Batch(1), ExpectedCredits(118)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(11), Batch(1), ExpectedCredits(130)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(12), Batch(1), ExpectedCredits(142)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(13), Batch(1), ExpectedCredits(154)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(14), Batch(1), ExpectedCredits(165)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(15), Batch(1), ExpectedCredits(177)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(16), Batch(1), ExpectedCredits(189)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(17), Batch(1), ExpectedCredits(201)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(18), Batch(1), ExpectedCredits(212)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(19), Batch(1), ExpectedCredits(224)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(20), Batch(1), ExpectedCredits(236)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(21), Batch(1), ExpectedCredits(248)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(22), Batch(1), ExpectedCredits(259)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(23), Batch(1), ExpectedCredits(271)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(24), Batch(1), ExpectedCredits(283)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(25), Batch(1), ExpectedCredits(295)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(26), Batch(1), ExpectedCredits(307)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(27), Batch(1), ExpectedCredits(318)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(28), Batch(1), ExpectedCredits(330)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(29), Batch(1), ExpectedCredits(342)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(30), Batch(1), ExpectedCredits(354)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(4), Batch(1), ExpectedCredits(107)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(5), Batch(1), ExpectedCredits(134)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(6), Batch(1), ExpectedCredits(161)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(7), Batch(1), ExpectedCredits(187)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(8), Batch(1), ExpectedCredits(214)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(9), Batch(1), ExpectedCredits(241)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(10), Batch(1), ExpectedCredits(268)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(11), Batch(1), ExpectedCredits(294)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(12), Batch(1), ExpectedCredits(321)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(13), Batch(1), ExpectedCredits(348)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(14), Batch(1), ExpectedCredits(374)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(15), Batch(1), ExpectedCredits(401)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(16), Batch(1), ExpectedCredits(428)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(17), Batch(1), ExpectedCredits(455)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(18), Batch(1), ExpectedCredits(481)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(19), Batch(1), ExpectedCredits(508)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(20), Batch(1), ExpectedCredits(535)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(21), Batch(1), ExpectedCredits(561)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(22), Batch(1), ExpectedCredits(588)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(23), Batch(1), ExpectedCredits(615)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(24), Batch(1), ExpectedCredits(641)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(25), Batch(1), ExpectedCredits(668)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(26), Batch(1), ExpectedCredits(695)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(27), Batch(1), ExpectedCredits(722)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(28), Batch(1), ExpectedCredits(748)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(29), Batch(1), ExpectedCredits(775)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(30), Batch(1), ExpectedCredits(802)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(4), Batch(1), ExpectedCredits(107)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(5), Batch(1), ExpectedCredits(134)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(6), Batch(1), ExpectedCredits(161)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(7), Batch(1), ExpectedCredits(187)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(8), Batch(1), ExpectedCredits(214)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(9), Batch(1), ExpectedCredits(241)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(10), Batch(1), ExpectedCredits(268)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(11), Batch(1), ExpectedCredits(294)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(12), Batch(1), ExpectedCredits(321)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(13), Batch(1), ExpectedCredits(348)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(14), Batch(1), ExpectedCredits(374)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(15), Batch(1), ExpectedCredits(401)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(16), Batch(1), ExpectedCredits(428)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(17), Batch(1), ExpectedCredits(455)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(18), Batch(1), ExpectedCredits(481)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(19), Batch(1), ExpectedCredits(508)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(20), Batch(1), ExpectedCredits(535)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(21), Batch(1), ExpectedCredits(561)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(22), Batch(1), ExpectedCredits(588)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(23), Batch(1), ExpectedCredits(615)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(24), Batch(1), ExpectedCredits(641)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(25), Batch(1), ExpectedCredits(668)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(26), Batch(1), ExpectedCredits(695)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(27), Batch(1), ExpectedCredits(722)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(28), Batch(1), ExpectedCredits(748)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(29), Batch(1), ExpectedCredits(775)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(30), Batch(1), ExpectedCredits(802)),
|
||||
(Some(CommonResolution::FourK), Seconds(4), Batch(1), ExpectedCredits(107)),
|
||||
(Some(CommonResolution::FourK), Seconds(5), Batch(1), ExpectedCredits(134)),
|
||||
(Some(CommonResolution::FourK), Seconds(6), Batch(1), ExpectedCredits(161)),
|
||||
(Some(CommonResolution::FourK), Seconds(7), Batch(1), ExpectedCredits(187)),
|
||||
(Some(CommonResolution::FourK), Seconds(8), Batch(1), ExpectedCredits(214)),
|
||||
(Some(CommonResolution::FourK), Seconds(9), Batch(1), ExpectedCredits(241)),
|
||||
(Some(CommonResolution::FourK), Seconds(10), Batch(1), ExpectedCredits(268)),
|
||||
(Some(CommonResolution::FourK), Seconds(11), Batch(1), ExpectedCredits(294)),
|
||||
(Some(CommonResolution::FourK), Seconds(12), Batch(1), ExpectedCredits(321)),
|
||||
(Some(CommonResolution::FourK), Seconds(13), Batch(1), ExpectedCredits(348)),
|
||||
(Some(CommonResolution::FourK), Seconds(14), Batch(1), ExpectedCredits(374)),
|
||||
(Some(CommonResolution::FourK), Seconds(15), Batch(1), ExpectedCredits(401)),
|
||||
(Some(CommonResolution::FourK), Seconds(16), Batch(1), ExpectedCredits(428)),
|
||||
(Some(CommonResolution::FourK), Seconds(17), Batch(1), ExpectedCredits(455)),
|
||||
(Some(CommonResolution::FourK), Seconds(18), Batch(1), ExpectedCredits(481)),
|
||||
(Some(CommonResolution::FourK), Seconds(19), Batch(1), ExpectedCredits(508)),
|
||||
(Some(CommonResolution::FourK), Seconds(20), Batch(1), ExpectedCredits(535)),
|
||||
(Some(CommonResolution::FourK), Seconds(21), Batch(1), ExpectedCredits(561)),
|
||||
(Some(CommonResolution::FourK), Seconds(22), Batch(1), ExpectedCredits(588)),
|
||||
(Some(CommonResolution::FourK), Seconds(23), Batch(1), ExpectedCredits(615)),
|
||||
(Some(CommonResolution::FourK), Seconds(24), Batch(1), ExpectedCredits(641)),
|
||||
(Some(CommonResolution::FourK), Seconds(25), Batch(1), ExpectedCredits(668)),
|
||||
(Some(CommonResolution::FourK), Seconds(26), Batch(1), ExpectedCredits(695)),
|
||||
(Some(CommonResolution::FourK), Seconds(27), Batch(1), ExpectedCredits(722)),
|
||||
(Some(CommonResolution::FourK), Seconds(28), Batch(1), ExpectedCredits(748)),
|
||||
(Some(CommonResolution::FourK), Seconds(29), Batch(1), ExpectedCredits(775)),
|
||||
(Some(CommonResolution::FourK), Seconds(30), Batch(1), ExpectedCredits(802)),
|
||||
];
|
||||
|
||||
for (resolution, seconds, batch, expected) in cases {
|
||||
assert_successful_generation_charges(
|
||||
&harness, CommonVideoModel::Seedance2p5, *resolution, *seconds, *batch, *expected,
|
||||
).await;
|
||||
}
|
||||
}
|
||||
|
||||
/// Every batch size 1-10 at every resolution (5s).
|
||||
/// Seedance 2.5 generates a single video per request: every requested batch size 1-10 bills exactly one video.
|
||||
/// Seedance 2.5 offers 480p and 720p; 1080p and 4K downgrade to 720p (and price accordingly).
|
||||
#[tokio::test]
|
||||
#[cfg_attr(feature = "skip_database_tests", ignore)]
|
||||
async fn charges_every_batch_size_at_every_resolution() {
|
||||
let harness = TestHarness::create().await;
|
||||
|
||||
let cases: &[(Option<CommonResolution>, Seconds, Batch, ExpectedCredits)] = &[
|
||||
(Some(CommonResolution::FourEightyP), Seconds(5), Batch(1), ExpectedCredits(59)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(5), Batch(2), ExpectedCredits(59)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(5), Batch(3), ExpectedCredits(59)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(5), Batch(4), ExpectedCredits(59)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(5), Batch(5), ExpectedCredits(59)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(5), Batch(6), ExpectedCredits(59)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(5), Batch(7), ExpectedCredits(59)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(5), Batch(8), ExpectedCredits(59)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(5), Batch(9), ExpectedCredits(59)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(5), Batch(10), ExpectedCredits(59)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(5), Batch(1), ExpectedCredits(134)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(5), Batch(2), ExpectedCredits(134)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(5), Batch(3), ExpectedCredits(134)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(5), Batch(4), ExpectedCredits(134)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(5), Batch(5), ExpectedCredits(134)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(5), Batch(6), ExpectedCredits(134)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(5), Batch(7), ExpectedCredits(134)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(5), Batch(8), ExpectedCredits(134)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(5), Batch(9), ExpectedCredits(134)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(5), Batch(10), ExpectedCredits(134)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(5), Batch(1), ExpectedCredits(134)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(5), Batch(2), ExpectedCredits(134)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(5), Batch(3), ExpectedCredits(134)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(5), Batch(4), ExpectedCredits(134)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(5), Batch(5), ExpectedCredits(134)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(5), Batch(6), ExpectedCredits(134)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(5), Batch(7), ExpectedCredits(134)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(5), Batch(8), ExpectedCredits(134)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(5), Batch(9), ExpectedCredits(134)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(5), Batch(10), ExpectedCredits(134)),
|
||||
(Some(CommonResolution::FourK), Seconds(5), Batch(1), ExpectedCredits(134)),
|
||||
(Some(CommonResolution::FourK), Seconds(5), Batch(2), ExpectedCredits(134)),
|
||||
(Some(CommonResolution::FourK), Seconds(5), Batch(3), ExpectedCredits(134)),
|
||||
(Some(CommonResolution::FourK), Seconds(5), Batch(4), ExpectedCredits(134)),
|
||||
(Some(CommonResolution::FourK), Seconds(5), Batch(5), ExpectedCredits(134)),
|
||||
(Some(CommonResolution::FourK), Seconds(5), Batch(6), ExpectedCredits(134)),
|
||||
(Some(CommonResolution::FourK), Seconds(5), Batch(7), ExpectedCredits(134)),
|
||||
(Some(CommonResolution::FourK), Seconds(5), Batch(8), ExpectedCredits(134)),
|
||||
(Some(CommonResolution::FourK), Seconds(5), Batch(9), ExpectedCredits(134)),
|
||||
(Some(CommonResolution::FourK), Seconds(5), Batch(10), ExpectedCredits(134)),
|
||||
];
|
||||
|
||||
for (resolution, seconds, batch, expected) in cases {
|
||||
assert_successful_generation_charges(
|
||||
&harness, CommonVideoModel::Seedance2p5, *resolution, *seconds, *batch, *expected,
|
||||
).await;
|
||||
}
|
||||
}
|
||||
|
||||
/// Spot checks across duration x batch x resolution (batch always bills as one video).
|
||||
#[tokio::test]
|
||||
#[cfg_attr(feature = "skip_database_tests", ignore)]
|
||||
async fn charges_spot_checked_combinations() {
|
||||
let harness = TestHarness::create().await;
|
||||
|
||||
let cases: &[(Option<CommonResolution>, Seconds, Batch, ExpectedCredits)] = &[
|
||||
(Some(CommonResolution::FourEightyP), Seconds(6), Batch(2), ExpectedCredits(71)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(7), Batch(3), ExpectedCredits(83)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(9), Batch(4), ExpectedCredits(106)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(11), Batch(5), ExpectedCredits(130)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(13), Batch(8), ExpectedCredits(154)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(15), Batch(10), ExpectedCredits(177)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(6), Batch(2), ExpectedCredits(161)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(7), Batch(3), ExpectedCredits(187)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(9), Batch(4), ExpectedCredits(241)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(11), Batch(5), ExpectedCredits(294)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(13), Batch(8), ExpectedCredits(348)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(15), Batch(10), ExpectedCredits(401)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(6), Batch(2), ExpectedCredits(161)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(7), Batch(3), ExpectedCredits(187)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(9), Batch(4), ExpectedCredits(241)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(11), Batch(5), ExpectedCredits(294)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(13), Batch(8), ExpectedCredits(348)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(15), Batch(10), ExpectedCredits(401)),
|
||||
(Some(CommonResolution::FourK), Seconds(6), Batch(2), ExpectedCredits(161)),
|
||||
(Some(CommonResolution::FourK), Seconds(7), Batch(3), ExpectedCredits(187)),
|
||||
(Some(CommonResolution::FourK), Seconds(9), Batch(4), ExpectedCredits(241)),
|
||||
(Some(CommonResolution::FourK), Seconds(11), Batch(5), ExpectedCredits(294)),
|
||||
(Some(CommonResolution::FourK), Seconds(13), Batch(8), ExpectedCredits(348)),
|
||||
(Some(CommonResolution::FourK), Seconds(15), Batch(10), ExpectedCredits(401)),
|
||||
];
|
||||
|
||||
for (resolution, seconds, batch, expected) in cases {
|
||||
assert_successful_generation_charges(
|
||||
&harness, CommonVideoModel::Seedance2p5, *resolution, *seconds, *batch, *expected,
|
||||
).await;
|
||||
}
|
||||
}
|
||||
|
||||
/// With video references the per-second rate drops but billed seconds = output duration + probed input seconds. The fixture media is unreachable, so the probe fails open to the worst-case 30 input seconds, the upload then fails, and the exact charge is asserted on the refunded ledger entry.
|
||||
/// Every duration 4-30s at every resolution.
|
||||
#[tokio::test]
|
||||
#[cfg_attr(feature = "skip_database_tests", ignore)]
|
||||
async fn video_references_charge_every_duration_at_every_resolution() {
|
||||
let harness = TestHarness::create().await;
|
||||
|
||||
let cases: &[(Option<CommonResolution>, Seconds, Batch, ExpectedCredits)] = &[
|
||||
(Some(CommonResolution::FourEightyP), Seconds(4), Batch(1), ExpectedCredits(247)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(5), Batch(1), ExpectedCredits(254)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(6), Batch(1), ExpectedCredits(261)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(7), Batch(1), ExpectedCredits(268)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(8), Batch(1), ExpectedCredits(276)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(9), Batch(1), ExpectedCredits(283)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(10), Batch(1), ExpectedCredits(290)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(11), Batch(1), ExpectedCredits(297)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(12), Batch(1), ExpectedCredits(305)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(13), Batch(1), ExpectedCredits(312)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(14), Batch(1), ExpectedCredits(319)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(15), Batch(1), ExpectedCredits(326)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(16), Batch(1), ExpectedCredits(334)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(17), Batch(1), ExpectedCredits(341)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(18), Batch(1), ExpectedCredits(348)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(19), Batch(1), ExpectedCredits(355)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(20), Batch(1), ExpectedCredits(363)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(21), Batch(1), ExpectedCredits(370)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(22), Batch(1), ExpectedCredits(377)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(23), Batch(1), ExpectedCredits(384)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(24), Batch(1), ExpectedCredits(392)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(25), Batch(1), ExpectedCredits(399)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(26), Batch(1), ExpectedCredits(406)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(27), Batch(1), ExpectedCredits(413)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(28), Batch(1), ExpectedCredits(421)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(29), Batch(1), ExpectedCredits(428)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(30), Batch(1), ExpectedCredits(435)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(4), Batch(1), ExpectedCredits(539)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(5), Batch(1), ExpectedCredits(555)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(6), Batch(1), ExpectedCredits(571)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(7), Batch(1), ExpectedCredits(587)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(8), Batch(1), ExpectedCredits(603)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(9), Batch(1), ExpectedCredits(618)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(10), Batch(1), ExpectedCredits(634)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(11), Batch(1), ExpectedCredits(650)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(12), Batch(1), ExpectedCredits(666)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(13), Batch(1), ExpectedCredits(682)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(14), Batch(1), ExpectedCredits(698)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(15), Batch(1), ExpectedCredits(713)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(16), Batch(1), ExpectedCredits(729)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(17), Batch(1), ExpectedCredits(745)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(18), Batch(1), ExpectedCredits(761)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(19), Batch(1), ExpectedCredits(777)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(20), Batch(1), ExpectedCredits(793)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(21), Batch(1), ExpectedCredits(809)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(22), Batch(1), ExpectedCredits(824)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(23), Batch(1), ExpectedCredits(840)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(24), Batch(1), ExpectedCredits(856)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(25), Batch(1), ExpectedCredits(872)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(26), Batch(1), ExpectedCredits(888)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(27), Batch(1), ExpectedCredits(904)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(28), Batch(1), ExpectedCredits(919)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(29), Batch(1), ExpectedCredits(935)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(30), Batch(1), ExpectedCredits(951)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(4), Batch(1), ExpectedCredits(539)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(5), Batch(1), ExpectedCredits(555)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(6), Batch(1), ExpectedCredits(571)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(7), Batch(1), ExpectedCredits(587)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(8), Batch(1), ExpectedCredits(603)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(9), Batch(1), ExpectedCredits(618)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(10), Batch(1), ExpectedCredits(634)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(11), Batch(1), ExpectedCredits(650)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(12), Batch(1), ExpectedCredits(666)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(13), Batch(1), ExpectedCredits(682)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(14), Batch(1), ExpectedCredits(698)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(15), Batch(1), ExpectedCredits(713)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(16), Batch(1), ExpectedCredits(729)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(17), Batch(1), ExpectedCredits(745)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(18), Batch(1), ExpectedCredits(761)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(19), Batch(1), ExpectedCredits(777)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(20), Batch(1), ExpectedCredits(793)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(21), Batch(1), ExpectedCredits(809)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(22), Batch(1), ExpectedCredits(824)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(23), Batch(1), ExpectedCredits(840)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(24), Batch(1), ExpectedCredits(856)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(25), Batch(1), ExpectedCredits(872)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(26), Batch(1), ExpectedCredits(888)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(27), Batch(1), ExpectedCredits(904)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(28), Batch(1), ExpectedCredits(919)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(29), Batch(1), ExpectedCredits(935)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(30), Batch(1), ExpectedCredits(951)),
|
||||
(Some(CommonResolution::FourK), Seconds(4), Batch(1), ExpectedCredits(539)),
|
||||
(Some(CommonResolution::FourK), Seconds(5), Batch(1), ExpectedCredits(555)),
|
||||
(Some(CommonResolution::FourK), Seconds(6), Batch(1), ExpectedCredits(571)),
|
||||
(Some(CommonResolution::FourK), Seconds(7), Batch(1), ExpectedCredits(587)),
|
||||
(Some(CommonResolution::FourK), Seconds(8), Batch(1), ExpectedCredits(603)),
|
||||
(Some(CommonResolution::FourK), Seconds(9), Batch(1), ExpectedCredits(618)),
|
||||
(Some(CommonResolution::FourK), Seconds(10), Batch(1), ExpectedCredits(634)),
|
||||
(Some(CommonResolution::FourK), Seconds(11), Batch(1), ExpectedCredits(650)),
|
||||
(Some(CommonResolution::FourK), Seconds(12), Batch(1), ExpectedCredits(666)),
|
||||
(Some(CommonResolution::FourK), Seconds(13), Batch(1), ExpectedCredits(682)),
|
||||
(Some(CommonResolution::FourK), Seconds(14), Batch(1), ExpectedCredits(698)),
|
||||
(Some(CommonResolution::FourK), Seconds(15), Batch(1), ExpectedCredits(713)),
|
||||
(Some(CommonResolution::FourK), Seconds(16), Batch(1), ExpectedCredits(729)),
|
||||
(Some(CommonResolution::FourK), Seconds(17), Batch(1), ExpectedCredits(745)),
|
||||
(Some(CommonResolution::FourK), Seconds(18), Batch(1), ExpectedCredits(761)),
|
||||
(Some(CommonResolution::FourK), Seconds(19), Batch(1), ExpectedCredits(777)),
|
||||
(Some(CommonResolution::FourK), Seconds(20), Batch(1), ExpectedCredits(793)),
|
||||
(Some(CommonResolution::FourK), Seconds(21), Batch(1), ExpectedCredits(809)),
|
||||
(Some(CommonResolution::FourK), Seconds(22), Batch(1), ExpectedCredits(824)),
|
||||
(Some(CommonResolution::FourK), Seconds(23), Batch(1), ExpectedCredits(840)),
|
||||
(Some(CommonResolution::FourK), Seconds(24), Batch(1), ExpectedCredits(856)),
|
||||
(Some(CommonResolution::FourK), Seconds(25), Batch(1), ExpectedCredits(872)),
|
||||
(Some(CommonResolution::FourK), Seconds(26), Batch(1), ExpectedCredits(888)),
|
||||
(Some(CommonResolution::FourK), Seconds(27), Batch(1), ExpectedCredits(904)),
|
||||
(Some(CommonResolution::FourK), Seconds(28), Batch(1), ExpectedCredits(919)),
|
||||
(Some(CommonResolution::FourK), Seconds(29), Batch(1), ExpectedCredits(935)),
|
||||
(Some(CommonResolution::FourK), Seconds(30), Batch(1), ExpectedCredits(951)),
|
||||
];
|
||||
|
||||
for (resolution, seconds, batch, expected) in cases {
|
||||
assert_reference_video_charge_then_refund(
|
||||
&harness, CommonVideoModel::Seedance2p5, *resolution, *seconds, *batch, *expected,
|
||||
).await;
|
||||
}
|
||||
}
|
||||
|
||||
/// With video references the per-second rate drops but billed seconds = output duration + probed input seconds. The fixture media is unreachable, so the probe fails open to the worst-case 30 input seconds, the upload then fails, and the exact charge is asserted on the refunded ledger entry.
|
||||
/// Every batch size 1-10 at every resolution (5s).
|
||||
/// Seedance 2.5 generates a single video per request: every requested batch size 1-10 bills exactly one video.
|
||||
#[tokio::test]
|
||||
#[cfg_attr(feature = "skip_database_tests", ignore)]
|
||||
async fn video_references_charge_every_batch_size_at_every_resolution() {
|
||||
let harness = TestHarness::create().await;
|
||||
|
||||
let cases: &[(Option<CommonResolution>, Seconds, Batch, ExpectedCredits)] = &[
|
||||
(Some(CommonResolution::FourEightyP), Seconds(5), Batch(1), ExpectedCredits(254)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(5), Batch(2), ExpectedCredits(254)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(5), Batch(3), ExpectedCredits(254)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(5), Batch(4), ExpectedCredits(254)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(5), Batch(5), ExpectedCredits(254)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(5), Batch(6), ExpectedCredits(254)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(5), Batch(7), ExpectedCredits(254)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(5), Batch(8), ExpectedCredits(254)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(5), Batch(9), ExpectedCredits(254)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(5), Batch(10), ExpectedCredits(254)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(5), Batch(1), ExpectedCredits(555)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(5), Batch(2), ExpectedCredits(555)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(5), Batch(3), ExpectedCredits(555)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(5), Batch(4), ExpectedCredits(555)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(5), Batch(5), ExpectedCredits(555)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(5), Batch(6), ExpectedCredits(555)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(5), Batch(7), ExpectedCredits(555)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(5), Batch(8), ExpectedCredits(555)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(5), Batch(9), ExpectedCredits(555)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(5), Batch(10), ExpectedCredits(555)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(5), Batch(1), ExpectedCredits(555)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(5), Batch(2), ExpectedCredits(555)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(5), Batch(3), ExpectedCredits(555)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(5), Batch(4), ExpectedCredits(555)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(5), Batch(5), ExpectedCredits(555)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(5), Batch(6), ExpectedCredits(555)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(5), Batch(7), ExpectedCredits(555)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(5), Batch(8), ExpectedCredits(555)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(5), Batch(9), ExpectedCredits(555)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(5), Batch(10), ExpectedCredits(555)),
|
||||
(Some(CommonResolution::FourK), Seconds(5), Batch(1), ExpectedCredits(555)),
|
||||
(Some(CommonResolution::FourK), Seconds(5), Batch(2), ExpectedCredits(555)),
|
||||
(Some(CommonResolution::FourK), Seconds(5), Batch(3), ExpectedCredits(555)),
|
||||
(Some(CommonResolution::FourK), Seconds(5), Batch(4), ExpectedCredits(555)),
|
||||
(Some(CommonResolution::FourK), Seconds(5), Batch(5), ExpectedCredits(555)),
|
||||
(Some(CommonResolution::FourK), Seconds(5), Batch(6), ExpectedCredits(555)),
|
||||
(Some(CommonResolution::FourK), Seconds(5), Batch(7), ExpectedCredits(555)),
|
||||
(Some(CommonResolution::FourK), Seconds(5), Batch(8), ExpectedCredits(555)),
|
||||
(Some(CommonResolution::FourK), Seconds(5), Batch(9), ExpectedCredits(555)),
|
||||
(Some(CommonResolution::FourK), Seconds(5), Batch(10), ExpectedCredits(555)),
|
||||
];
|
||||
|
||||
for (resolution, seconds, batch, expected) in cases {
|
||||
assert_reference_video_charge_then_refund(
|
||||
&harness, CommonVideoModel::Seedance2p5, *resolution, *seconds, *batch, *expected,
|
||||
).await;
|
||||
}
|
||||
}
|
||||
|
||||
/// With video references the per-second rate drops but billed seconds = output duration + probed input seconds. The fixture media is unreachable, so the probe fails open to the worst-case 30 input seconds, the upload then fails, and the exact charge is asserted on the refunded ledger entry.
|
||||
/// Spot checks across duration x batch x resolution.
|
||||
#[tokio::test]
|
||||
#[cfg_attr(feature = "skip_database_tests", ignore)]
|
||||
async fn video_references_charge_spot_checked_combinations() {
|
||||
let harness = TestHarness::create().await;
|
||||
|
||||
let cases: &[(Option<CommonResolution>, Seconds, Batch, ExpectedCredits)] = &[
|
||||
(Some(CommonResolution::FourEightyP), Seconds(6), Batch(2), ExpectedCredits(261)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(7), Batch(3), ExpectedCredits(268)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(9), Batch(4), ExpectedCredits(283)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(11), Batch(5), ExpectedCredits(297)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(13), Batch(8), ExpectedCredits(312)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(15), Batch(10), ExpectedCredits(326)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(6), Batch(2), ExpectedCredits(571)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(7), Batch(3), ExpectedCredits(587)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(9), Batch(4), ExpectedCredits(618)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(11), Batch(5), ExpectedCredits(650)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(13), Batch(8), ExpectedCredits(682)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(15), Batch(10), ExpectedCredits(713)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(6), Batch(2), ExpectedCredits(571)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(7), Batch(3), ExpectedCredits(587)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(9), Batch(4), ExpectedCredits(618)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(11), Batch(5), ExpectedCredits(650)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(13), Batch(8), ExpectedCredits(682)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(15), Batch(10), ExpectedCredits(713)),
|
||||
(Some(CommonResolution::FourK), Seconds(6), Batch(2), ExpectedCredits(571)),
|
||||
(Some(CommonResolution::FourK), Seconds(7), Batch(3), ExpectedCredits(587)),
|
||||
(Some(CommonResolution::FourK), Seconds(9), Batch(4), ExpectedCredits(618)),
|
||||
(Some(CommonResolution::FourK), Seconds(11), Batch(5), ExpectedCredits(650)),
|
||||
(Some(CommonResolution::FourK), Seconds(13), Batch(8), ExpectedCredits(682)),
|
||||
(Some(CommonResolution::FourK), Seconds(15), Batch(10), ExpectedCredits(713)),
|
||||
];
|
||||
|
||||
for (resolution, seconds, batch, expected) in cases {
|
||||
assert_reference_video_charge_then_refund(
|
||||
&harness, CommonVideoModel::Seedance2p5, *resolution, *seconds, *batch, *expected,
|
||||
).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ── Seedance 2.5 Ultra ──
|
||||
// Fulfilled by Seedance 2.5 (same execution request), priced as itself and
|
||||
// routed to a different provider account. If the pipeline ever collapses
|
||||
// the model before billing, every row here fails with the regular 2.5
|
||||
// numbers.
|
||||
mod seedance_2p5_u {
|
||||
use super::*;
|
||||
|
||||
/// Every duration 4-30s at every resolution, single video.
|
||||
/// Seedance 2.5 offers 480p and 720p; 1080p and 4K downgrade to 720p (and price accordingly).
|
||||
#[tokio::test]
|
||||
#[cfg_attr(feature = "skip_database_tests", ignore)]
|
||||
async fn charges_every_duration_at_every_resolution() {
|
||||
let harness = TestHarness::create().await;
|
||||
|
||||
let cases: &[(Option<CommonResolution>, Seconds, Batch, ExpectedCredits)] = &[
|
||||
(Some(CommonResolution::FourEightyP), Seconds(4), Batch(1), ExpectedCredits(56)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(5), Batch(1), ExpectedCredits(70)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(6), Batch(1), ExpectedCredits(84)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(7), Batch(1), ExpectedCredits(98)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(8), Batch(1), ExpectedCredits(112)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(9), Batch(1), ExpectedCredits(126)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(10), Batch(1), ExpectedCredits(140)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(11), Batch(1), ExpectedCredits(154)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(12), Batch(1), ExpectedCredits(167)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(13), Batch(1), ExpectedCredits(181)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(14), Batch(1), ExpectedCredits(195)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(15), Batch(1), ExpectedCredits(209)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(16), Batch(1), ExpectedCredits(223)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(17), Batch(1), ExpectedCredits(237)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(18), Batch(1), ExpectedCredits(251)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(19), Batch(1), ExpectedCredits(265)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(20), Batch(1), ExpectedCredits(279)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(21), Batch(1), ExpectedCredits(293)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(22), Batch(1), ExpectedCredits(307)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(23), Batch(1), ExpectedCredits(320)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(24), Batch(1), ExpectedCredits(334)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(25), Batch(1), ExpectedCredits(348)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(26), Batch(1), ExpectedCredits(362)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(27), Batch(1), ExpectedCredits(376)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(28), Batch(1), ExpectedCredits(390)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(29), Batch(1), ExpectedCredits(404)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(30), Batch(1), ExpectedCredits(418)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(4), Batch(1), ExpectedCredits(127)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(5), Batch(1), ExpectedCredits(158)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(6), Batch(1), ExpectedCredits(190)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(7), Batch(1), ExpectedCredits(221)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(8), Batch(1), ExpectedCredits(253)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(9), Batch(1), ExpectedCredits(285)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(10), Batch(1), ExpectedCredits(316)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(11), Batch(1), ExpectedCredits(348)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(12), Batch(1), ExpectedCredits(379)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(13), Batch(1), ExpectedCredits(411)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(14), Batch(1), ExpectedCredits(442)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(15), Batch(1), ExpectedCredits(474)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(16), Batch(1), ExpectedCredits(506)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(17), Batch(1), ExpectedCredits(537)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(18), Batch(1), ExpectedCredits(569)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(19), Batch(1), ExpectedCredits(600)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(20), Batch(1), ExpectedCredits(632)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(21), Batch(1), ExpectedCredits(663)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(22), Batch(1), ExpectedCredits(695)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(23), Batch(1), ExpectedCredits(726)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(24), Batch(1), ExpectedCredits(758)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(25), Batch(1), ExpectedCredits(790)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(26), Batch(1), ExpectedCredits(821)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(27), Batch(1), ExpectedCredits(853)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(28), Batch(1), ExpectedCredits(884)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(29), Batch(1), ExpectedCredits(916)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(30), Batch(1), ExpectedCredits(947)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(4), Batch(1), ExpectedCredits(127)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(5), Batch(1), ExpectedCredits(158)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(6), Batch(1), ExpectedCredits(190)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(7), Batch(1), ExpectedCredits(221)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(8), Batch(1), ExpectedCredits(253)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(9), Batch(1), ExpectedCredits(285)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(10), Batch(1), ExpectedCredits(316)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(11), Batch(1), ExpectedCredits(348)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(12), Batch(1), ExpectedCredits(379)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(13), Batch(1), ExpectedCredits(411)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(14), Batch(1), ExpectedCredits(442)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(15), Batch(1), ExpectedCredits(474)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(16), Batch(1), ExpectedCredits(506)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(17), Batch(1), ExpectedCredits(537)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(18), Batch(1), ExpectedCredits(569)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(19), Batch(1), ExpectedCredits(600)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(20), Batch(1), ExpectedCredits(632)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(21), Batch(1), ExpectedCredits(663)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(22), Batch(1), ExpectedCredits(695)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(23), Batch(1), ExpectedCredits(726)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(24), Batch(1), ExpectedCredits(758)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(25), Batch(1), ExpectedCredits(790)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(26), Batch(1), ExpectedCredits(821)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(27), Batch(1), ExpectedCredits(853)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(28), Batch(1), ExpectedCredits(884)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(29), Batch(1), ExpectedCredits(916)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(30), Batch(1), ExpectedCredits(947)),
|
||||
(Some(CommonResolution::FourK), Seconds(4), Batch(1), ExpectedCredits(127)),
|
||||
(Some(CommonResolution::FourK), Seconds(5), Batch(1), ExpectedCredits(158)),
|
||||
(Some(CommonResolution::FourK), Seconds(6), Batch(1), ExpectedCredits(190)),
|
||||
(Some(CommonResolution::FourK), Seconds(7), Batch(1), ExpectedCredits(221)),
|
||||
(Some(CommonResolution::FourK), Seconds(8), Batch(1), ExpectedCredits(253)),
|
||||
(Some(CommonResolution::FourK), Seconds(9), Batch(1), ExpectedCredits(285)),
|
||||
(Some(CommonResolution::FourK), Seconds(10), Batch(1), ExpectedCredits(316)),
|
||||
(Some(CommonResolution::FourK), Seconds(11), Batch(1), ExpectedCredits(348)),
|
||||
(Some(CommonResolution::FourK), Seconds(12), Batch(1), ExpectedCredits(379)),
|
||||
(Some(CommonResolution::FourK), Seconds(13), Batch(1), ExpectedCredits(411)),
|
||||
(Some(CommonResolution::FourK), Seconds(14), Batch(1), ExpectedCredits(442)),
|
||||
(Some(CommonResolution::FourK), Seconds(15), Batch(1), ExpectedCredits(474)),
|
||||
(Some(CommonResolution::FourK), Seconds(16), Batch(1), ExpectedCredits(506)),
|
||||
(Some(CommonResolution::FourK), Seconds(17), Batch(1), ExpectedCredits(537)),
|
||||
(Some(CommonResolution::FourK), Seconds(18), Batch(1), ExpectedCredits(569)),
|
||||
(Some(CommonResolution::FourK), Seconds(19), Batch(1), ExpectedCredits(600)),
|
||||
(Some(CommonResolution::FourK), Seconds(20), Batch(1), ExpectedCredits(632)),
|
||||
(Some(CommonResolution::FourK), Seconds(21), Batch(1), ExpectedCredits(663)),
|
||||
(Some(CommonResolution::FourK), Seconds(22), Batch(1), ExpectedCredits(695)),
|
||||
(Some(CommonResolution::FourK), Seconds(23), Batch(1), ExpectedCredits(726)),
|
||||
(Some(CommonResolution::FourK), Seconds(24), Batch(1), ExpectedCredits(758)),
|
||||
(Some(CommonResolution::FourK), Seconds(25), Batch(1), ExpectedCredits(790)),
|
||||
(Some(CommonResolution::FourK), Seconds(26), Batch(1), ExpectedCredits(821)),
|
||||
(Some(CommonResolution::FourK), Seconds(27), Batch(1), ExpectedCredits(853)),
|
||||
(Some(CommonResolution::FourK), Seconds(28), Batch(1), ExpectedCredits(884)),
|
||||
(Some(CommonResolution::FourK), Seconds(29), Batch(1), ExpectedCredits(916)),
|
||||
(Some(CommonResolution::FourK), Seconds(30), Batch(1), ExpectedCredits(947)),
|
||||
];
|
||||
|
||||
for (resolution, seconds, batch, expected) in cases {
|
||||
assert_successful_generation_charges(
|
||||
&harness, CommonVideoModel::Seedance2p5Ultra, *resolution, *seconds, *batch, *expected,
|
||||
).await;
|
||||
}
|
||||
}
|
||||
|
||||
/// Every batch size 1-10 at every resolution (5s).
|
||||
/// Seedance 2.5 generates a single video per request: every requested batch size 1-10 bills exactly one video.
|
||||
/// Seedance 2.5 offers 480p and 720p; 1080p and 4K downgrade to 720p (and price accordingly).
|
||||
#[tokio::test]
|
||||
#[cfg_attr(feature = "skip_database_tests", ignore)]
|
||||
async fn charges_every_batch_size_at_every_resolution() {
|
||||
let harness = TestHarness::create().await;
|
||||
|
||||
let cases: &[(Option<CommonResolution>, Seconds, Batch, ExpectedCredits)] = &[
|
||||
(Some(CommonResolution::FourEightyP), Seconds(5), Batch(1), ExpectedCredits(70)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(5), Batch(2), ExpectedCredits(70)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(5), Batch(3), ExpectedCredits(70)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(5), Batch(4), ExpectedCredits(70)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(5), Batch(5), ExpectedCredits(70)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(5), Batch(6), ExpectedCredits(70)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(5), Batch(7), ExpectedCredits(70)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(5), Batch(8), ExpectedCredits(70)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(5), Batch(9), ExpectedCredits(70)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(5), Batch(10), ExpectedCredits(70)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(5), Batch(1), ExpectedCredits(158)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(5), Batch(2), ExpectedCredits(158)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(5), Batch(3), ExpectedCredits(158)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(5), Batch(4), ExpectedCredits(158)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(5), Batch(5), ExpectedCredits(158)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(5), Batch(6), ExpectedCredits(158)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(5), Batch(7), ExpectedCredits(158)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(5), Batch(8), ExpectedCredits(158)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(5), Batch(9), ExpectedCredits(158)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(5), Batch(10), ExpectedCredits(158)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(5), Batch(1), ExpectedCredits(158)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(5), Batch(2), ExpectedCredits(158)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(5), Batch(3), ExpectedCredits(158)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(5), Batch(4), ExpectedCredits(158)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(5), Batch(5), ExpectedCredits(158)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(5), Batch(6), ExpectedCredits(158)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(5), Batch(7), ExpectedCredits(158)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(5), Batch(8), ExpectedCredits(158)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(5), Batch(9), ExpectedCredits(158)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(5), Batch(10), ExpectedCredits(158)),
|
||||
(Some(CommonResolution::FourK), Seconds(5), Batch(1), ExpectedCredits(158)),
|
||||
(Some(CommonResolution::FourK), Seconds(5), Batch(2), ExpectedCredits(158)),
|
||||
(Some(CommonResolution::FourK), Seconds(5), Batch(3), ExpectedCredits(158)),
|
||||
(Some(CommonResolution::FourK), Seconds(5), Batch(4), ExpectedCredits(158)),
|
||||
(Some(CommonResolution::FourK), Seconds(5), Batch(5), ExpectedCredits(158)),
|
||||
(Some(CommonResolution::FourK), Seconds(5), Batch(6), ExpectedCredits(158)),
|
||||
(Some(CommonResolution::FourK), Seconds(5), Batch(7), ExpectedCredits(158)),
|
||||
(Some(CommonResolution::FourK), Seconds(5), Batch(8), ExpectedCredits(158)),
|
||||
(Some(CommonResolution::FourK), Seconds(5), Batch(9), ExpectedCredits(158)),
|
||||
(Some(CommonResolution::FourK), Seconds(5), Batch(10), ExpectedCredits(158)),
|
||||
];
|
||||
|
||||
for (resolution, seconds, batch, expected) in cases {
|
||||
assert_successful_generation_charges(
|
||||
&harness, CommonVideoModel::Seedance2p5Ultra, *resolution, *seconds, *batch, *expected,
|
||||
).await;
|
||||
}
|
||||
}
|
||||
|
||||
/// Spot checks across duration x batch x resolution (batch always bills as one video).
|
||||
#[tokio::test]
|
||||
#[cfg_attr(feature = "skip_database_tests", ignore)]
|
||||
async fn charges_spot_checked_combinations() {
|
||||
let harness = TestHarness::create().await;
|
||||
|
||||
let cases: &[(Option<CommonResolution>, Seconds, Batch, ExpectedCredits)] = &[
|
||||
(Some(CommonResolution::FourEightyP), Seconds(6), Batch(2), ExpectedCredits(84)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(7), Batch(3), ExpectedCredits(98)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(9), Batch(4), ExpectedCredits(126)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(11), Batch(5), ExpectedCredits(154)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(13), Batch(8), ExpectedCredits(181)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(15), Batch(10), ExpectedCredits(209)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(6), Batch(2), ExpectedCredits(190)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(7), Batch(3), ExpectedCredits(221)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(9), Batch(4), ExpectedCredits(285)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(11), Batch(5), ExpectedCredits(348)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(13), Batch(8), ExpectedCredits(411)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(15), Batch(10), ExpectedCredits(474)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(6), Batch(2), ExpectedCredits(190)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(7), Batch(3), ExpectedCredits(221)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(9), Batch(4), ExpectedCredits(285)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(11), Batch(5), ExpectedCredits(348)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(13), Batch(8), ExpectedCredits(411)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(15), Batch(10), ExpectedCredits(474)),
|
||||
(Some(CommonResolution::FourK), Seconds(6), Batch(2), ExpectedCredits(190)),
|
||||
(Some(CommonResolution::FourK), Seconds(7), Batch(3), ExpectedCredits(221)),
|
||||
(Some(CommonResolution::FourK), Seconds(9), Batch(4), ExpectedCredits(285)),
|
||||
(Some(CommonResolution::FourK), Seconds(11), Batch(5), ExpectedCredits(348)),
|
||||
(Some(CommonResolution::FourK), Seconds(13), Batch(8), ExpectedCredits(411)),
|
||||
(Some(CommonResolution::FourK), Seconds(15), Batch(10), ExpectedCredits(474)),
|
||||
];
|
||||
|
||||
for (resolution, seconds, batch, expected) in cases {
|
||||
assert_successful_generation_charges(
|
||||
&harness, CommonVideoModel::Seedance2p5Ultra, *resolution, *seconds, *batch, *expected,
|
||||
).await;
|
||||
}
|
||||
}
|
||||
|
||||
/// With video references the per-second rate drops but billed seconds = output duration + probed input seconds. The fixture media is unreachable, so the probe fails open to the worst-case 30 input seconds, the upload then fails, and the exact charge is asserted on the refunded ledger entry.
|
||||
/// Every duration 4-30s at every resolution.
|
||||
#[tokio::test]
|
||||
#[cfg_attr(feature = "skip_database_tests", ignore)]
|
||||
async fn video_references_charge_every_duration_at_every_resolution() {
|
||||
let harness = TestHarness::create().await;
|
||||
|
||||
let cases: &[(Option<CommonResolution>, Seconds, Batch, ExpectedCredits)] = &[
|
||||
(Some(CommonResolution::FourEightyP), Seconds(4), Batch(1), ExpectedCredits(292)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(5), Batch(1), ExpectedCredits(300)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(6), Batch(1), ExpectedCredits(309)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(7), Batch(1), ExpectedCredits(317)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(8), Batch(1), ExpectedCredits(326)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(9), Batch(1), ExpectedCredits(334)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(10), Batch(1), ExpectedCredits(343)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(11), Batch(1), ExpectedCredits(351)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(12), Batch(1), ExpectedCredits(360)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(13), Batch(1), ExpectedCredits(369)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(14), Batch(1), ExpectedCredits(377)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(15), Batch(1), ExpectedCredits(386)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(16), Batch(1), ExpectedCredits(394)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(17), Batch(1), ExpectedCredits(403)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(18), Batch(1), ExpectedCredits(411)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(19), Batch(1), ExpectedCredits(420)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(20), Batch(1), ExpectedCredits(428)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(21), Batch(1), ExpectedCredits(437)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(22), Batch(1), ExpectedCredits(446)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(23), Batch(1), ExpectedCredits(454)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(24), Batch(1), ExpectedCredits(463)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(25), Batch(1), ExpectedCredits(471)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(26), Batch(1), ExpectedCredits(480)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(27), Batch(1), ExpectedCredits(488)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(28), Batch(1), ExpectedCredits(497)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(29), Batch(1), ExpectedCredits(506)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(30), Batch(1), ExpectedCredits(514)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(4), Batch(1), ExpectedCredits(637)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(5), Batch(1), ExpectedCredits(656)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(6), Batch(1), ExpectedCredits(675)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(7), Batch(1), ExpectedCredits(693)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(8), Batch(1), ExpectedCredits(712)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(9), Batch(1), ExpectedCredits(731)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(10), Batch(1), ExpectedCredits(749)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(11), Batch(1), ExpectedCredits(768)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(12), Batch(1), ExpectedCredits(787)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(13), Batch(1), ExpectedCredits(806)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(14), Batch(1), ExpectedCredits(824)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(15), Batch(1), ExpectedCredits(843)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(16), Batch(1), ExpectedCredits(862)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(17), Batch(1), ExpectedCredits(881)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(18), Batch(1), ExpectedCredits(899)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(19), Batch(1), ExpectedCredits(918)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(20), Batch(1), ExpectedCredits(937)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(21), Batch(1), ExpectedCredits(955)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(22), Batch(1), ExpectedCredits(974)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(23), Batch(1), ExpectedCredits(993)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(24), Batch(1), ExpectedCredits(1012)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(25), Batch(1), ExpectedCredits(1030)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(26), Batch(1), ExpectedCredits(1049)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(27), Batch(1), ExpectedCredits(1068)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(28), Batch(1), ExpectedCredits(1087)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(29), Batch(1), ExpectedCredits(1105)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(30), Batch(1), ExpectedCredits(1124)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(4), Batch(1), ExpectedCredits(637)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(5), Batch(1), ExpectedCredits(656)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(6), Batch(1), ExpectedCredits(675)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(7), Batch(1), ExpectedCredits(693)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(8), Batch(1), ExpectedCredits(712)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(9), Batch(1), ExpectedCredits(731)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(10), Batch(1), ExpectedCredits(749)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(11), Batch(1), ExpectedCredits(768)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(12), Batch(1), ExpectedCredits(787)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(13), Batch(1), ExpectedCredits(806)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(14), Batch(1), ExpectedCredits(824)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(15), Batch(1), ExpectedCredits(843)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(16), Batch(1), ExpectedCredits(862)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(17), Batch(1), ExpectedCredits(881)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(18), Batch(1), ExpectedCredits(899)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(19), Batch(1), ExpectedCredits(918)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(20), Batch(1), ExpectedCredits(937)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(21), Batch(1), ExpectedCredits(955)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(22), Batch(1), ExpectedCredits(974)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(23), Batch(1), ExpectedCredits(993)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(24), Batch(1), ExpectedCredits(1012)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(25), Batch(1), ExpectedCredits(1030)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(26), Batch(1), ExpectedCredits(1049)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(27), Batch(1), ExpectedCredits(1068)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(28), Batch(1), ExpectedCredits(1087)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(29), Batch(1), ExpectedCredits(1105)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(30), Batch(1), ExpectedCredits(1124)),
|
||||
(Some(CommonResolution::FourK), Seconds(4), Batch(1), ExpectedCredits(637)),
|
||||
(Some(CommonResolution::FourK), Seconds(5), Batch(1), ExpectedCredits(656)),
|
||||
(Some(CommonResolution::FourK), Seconds(6), Batch(1), ExpectedCredits(675)),
|
||||
(Some(CommonResolution::FourK), Seconds(7), Batch(1), ExpectedCredits(693)),
|
||||
(Some(CommonResolution::FourK), Seconds(8), Batch(1), ExpectedCredits(712)),
|
||||
(Some(CommonResolution::FourK), Seconds(9), Batch(1), ExpectedCredits(731)),
|
||||
(Some(CommonResolution::FourK), Seconds(10), Batch(1), ExpectedCredits(749)),
|
||||
(Some(CommonResolution::FourK), Seconds(11), Batch(1), ExpectedCredits(768)),
|
||||
(Some(CommonResolution::FourK), Seconds(12), Batch(1), ExpectedCredits(787)),
|
||||
(Some(CommonResolution::FourK), Seconds(13), Batch(1), ExpectedCredits(806)),
|
||||
(Some(CommonResolution::FourK), Seconds(14), Batch(1), ExpectedCredits(824)),
|
||||
(Some(CommonResolution::FourK), Seconds(15), Batch(1), ExpectedCredits(843)),
|
||||
(Some(CommonResolution::FourK), Seconds(16), Batch(1), ExpectedCredits(862)),
|
||||
(Some(CommonResolution::FourK), Seconds(17), Batch(1), ExpectedCredits(881)),
|
||||
(Some(CommonResolution::FourK), Seconds(18), Batch(1), ExpectedCredits(899)),
|
||||
(Some(CommonResolution::FourK), Seconds(19), Batch(1), ExpectedCredits(918)),
|
||||
(Some(CommonResolution::FourK), Seconds(20), Batch(1), ExpectedCredits(937)),
|
||||
(Some(CommonResolution::FourK), Seconds(21), Batch(1), ExpectedCredits(955)),
|
||||
(Some(CommonResolution::FourK), Seconds(22), Batch(1), ExpectedCredits(974)),
|
||||
(Some(CommonResolution::FourK), Seconds(23), Batch(1), ExpectedCredits(993)),
|
||||
(Some(CommonResolution::FourK), Seconds(24), Batch(1), ExpectedCredits(1012)),
|
||||
(Some(CommonResolution::FourK), Seconds(25), Batch(1), ExpectedCredits(1030)),
|
||||
(Some(CommonResolution::FourK), Seconds(26), Batch(1), ExpectedCredits(1049)),
|
||||
(Some(CommonResolution::FourK), Seconds(27), Batch(1), ExpectedCredits(1068)),
|
||||
(Some(CommonResolution::FourK), Seconds(28), Batch(1), ExpectedCredits(1087)),
|
||||
(Some(CommonResolution::FourK), Seconds(29), Batch(1), ExpectedCredits(1105)),
|
||||
(Some(CommonResolution::FourK), Seconds(30), Batch(1), ExpectedCredits(1124)),
|
||||
];
|
||||
|
||||
for (resolution, seconds, batch, expected) in cases {
|
||||
assert_reference_video_charge_then_refund(
|
||||
&harness, CommonVideoModel::Seedance2p5Ultra, *resolution, *seconds, *batch, *expected,
|
||||
).await;
|
||||
}
|
||||
}
|
||||
|
||||
/// With video references the per-second rate drops but billed seconds = output duration + probed input seconds. The fixture media is unreachable, so the probe fails open to the worst-case 30 input seconds, the upload then fails, and the exact charge is asserted on the refunded ledger entry.
|
||||
/// Every batch size 1-10 at every resolution (5s).
|
||||
/// Seedance 2.5 generates a single video per request: every requested batch size 1-10 bills exactly one video.
|
||||
#[tokio::test]
|
||||
#[cfg_attr(feature = "skip_database_tests", ignore)]
|
||||
async fn video_references_charge_every_batch_size_at_every_resolution() {
|
||||
let harness = TestHarness::create().await;
|
||||
|
||||
let cases: &[(Option<CommonResolution>, Seconds, Batch, ExpectedCredits)] = &[
|
||||
(Some(CommonResolution::FourEightyP), Seconds(5), Batch(1), ExpectedCredits(300)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(5), Batch(2), ExpectedCredits(300)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(5), Batch(3), ExpectedCredits(300)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(5), Batch(4), ExpectedCredits(300)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(5), Batch(5), ExpectedCredits(300)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(5), Batch(6), ExpectedCredits(300)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(5), Batch(7), ExpectedCredits(300)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(5), Batch(8), ExpectedCredits(300)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(5), Batch(9), ExpectedCredits(300)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(5), Batch(10), ExpectedCredits(300)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(5), Batch(1), ExpectedCredits(656)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(5), Batch(2), ExpectedCredits(656)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(5), Batch(3), ExpectedCredits(656)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(5), Batch(4), ExpectedCredits(656)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(5), Batch(5), ExpectedCredits(656)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(5), Batch(6), ExpectedCredits(656)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(5), Batch(7), ExpectedCredits(656)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(5), Batch(8), ExpectedCredits(656)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(5), Batch(9), ExpectedCredits(656)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(5), Batch(10), ExpectedCredits(656)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(5), Batch(1), ExpectedCredits(656)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(5), Batch(2), ExpectedCredits(656)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(5), Batch(3), ExpectedCredits(656)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(5), Batch(4), ExpectedCredits(656)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(5), Batch(5), ExpectedCredits(656)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(5), Batch(6), ExpectedCredits(656)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(5), Batch(7), ExpectedCredits(656)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(5), Batch(8), ExpectedCredits(656)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(5), Batch(9), ExpectedCredits(656)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(5), Batch(10), ExpectedCredits(656)),
|
||||
(Some(CommonResolution::FourK), Seconds(5), Batch(1), ExpectedCredits(656)),
|
||||
(Some(CommonResolution::FourK), Seconds(5), Batch(2), ExpectedCredits(656)),
|
||||
(Some(CommonResolution::FourK), Seconds(5), Batch(3), ExpectedCredits(656)),
|
||||
(Some(CommonResolution::FourK), Seconds(5), Batch(4), ExpectedCredits(656)),
|
||||
(Some(CommonResolution::FourK), Seconds(5), Batch(5), ExpectedCredits(656)),
|
||||
(Some(CommonResolution::FourK), Seconds(5), Batch(6), ExpectedCredits(656)),
|
||||
(Some(CommonResolution::FourK), Seconds(5), Batch(7), ExpectedCredits(656)),
|
||||
(Some(CommonResolution::FourK), Seconds(5), Batch(8), ExpectedCredits(656)),
|
||||
(Some(CommonResolution::FourK), Seconds(5), Batch(9), ExpectedCredits(656)),
|
||||
(Some(CommonResolution::FourK), Seconds(5), Batch(10), ExpectedCredits(656)),
|
||||
];
|
||||
|
||||
for (resolution, seconds, batch, expected) in cases {
|
||||
assert_reference_video_charge_then_refund(
|
||||
&harness, CommonVideoModel::Seedance2p5Ultra, *resolution, *seconds, *batch, *expected,
|
||||
).await;
|
||||
}
|
||||
}
|
||||
|
||||
/// With video references the per-second rate drops but billed seconds = output duration + probed input seconds. The fixture media is unreachable, so the probe fails open to the worst-case 30 input seconds, the upload then fails, and the exact charge is asserted on the refunded ledger entry.
|
||||
/// Spot checks across duration x batch x resolution.
|
||||
#[tokio::test]
|
||||
#[cfg_attr(feature = "skip_database_tests", ignore)]
|
||||
async fn video_references_charge_spot_checked_combinations() {
|
||||
let harness = TestHarness::create().await;
|
||||
|
||||
let cases: &[(Option<CommonResolution>, Seconds, Batch, ExpectedCredits)] = &[
|
||||
(Some(CommonResolution::FourEightyP), Seconds(6), Batch(2), ExpectedCredits(309)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(7), Batch(3), ExpectedCredits(317)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(9), Batch(4), ExpectedCredits(334)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(11), Batch(5), ExpectedCredits(351)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(13), Batch(8), ExpectedCredits(369)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(15), Batch(10), ExpectedCredits(386)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(6), Batch(2), ExpectedCredits(675)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(7), Batch(3), ExpectedCredits(693)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(9), Batch(4), ExpectedCredits(731)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(11), Batch(5), ExpectedCredits(768)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(13), Batch(8), ExpectedCredits(806)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(15), Batch(10), ExpectedCredits(843)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(6), Batch(2), ExpectedCredits(675)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(7), Batch(3), ExpectedCredits(693)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(9), Batch(4), ExpectedCredits(731)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(11), Batch(5), ExpectedCredits(768)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(13), Batch(8), ExpectedCredits(806)),
|
||||
(Some(CommonResolution::TenEightyP), Seconds(15), Batch(10), ExpectedCredits(843)),
|
||||
(Some(CommonResolution::FourK), Seconds(6), Batch(2), ExpectedCredits(675)),
|
||||
(Some(CommonResolution::FourK), Seconds(7), Batch(3), ExpectedCredits(693)),
|
||||
(Some(CommonResolution::FourK), Seconds(9), Batch(4), ExpectedCredits(731)),
|
||||
(Some(CommonResolution::FourK), Seconds(11), Batch(5), ExpectedCredits(768)),
|
||||
(Some(CommonResolution::FourK), Seconds(13), Batch(8), ExpectedCredits(806)),
|
||||
(Some(CommonResolution::FourK), Seconds(15), Batch(10), ExpectedCredits(843)),
|
||||
];
|
||||
|
||||
for (resolution, seconds, batch, expected) in cases {
|
||||
assert_reference_video_charge_then_refund(
|
||||
&harness, CommonVideoModel::Seedance2p5Ultra, *resolution, *seconds, *batch, *expected,
|
||||
).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ── Revenue premium: Ultra over the base model ──
|
||||
// Both prices and the delta are encoded so a change to EITHER rate card
|
||||
// shows up here, not just a flipped ordering.
|
||||
mod premium {
|
||||
use super::*;
|
||||
|
||||
/// Seedance 2.5 Ultra is fulfilled by Seedance 2.5 but has its own (higher)
|
||||
/// price. Same shape as the 2.0 collapse-bug pins: if the pipeline ever
|
||||
/// collapses Ultra before billing, these fail with the regular 2.5 numbers.
|
||||
#[tokio::test]
|
||||
#[cfg_attr(feature = "skip_database_tests", ignore)]
|
||||
async fn seedance_2p5_ultra_charges_a_premium_over_the_base_model() {
|
||||
let harness = TestHarness::create().await;
|
||||
|
||||
let cases: &[(Option<CommonResolution>, Seconds, Batch, ExpectedCredits, ExpectedCredits, CreditsDelta)] = &[
|
||||
(Some(CommonResolution::FourEightyP), Seconds(5), Batch(1), ExpectedCredits(59), ExpectedCredits(70), CreditsDelta(11)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(30), Batch(1), ExpectedCredits(354), ExpectedCredits(418), CreditsDelta(64)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(5), Batch(1), ExpectedCredits(134), ExpectedCredits(158), CreditsDelta(24)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(10), Batch(1), ExpectedCredits(268), ExpectedCredits(316), CreditsDelta(48)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(15), Batch(1), ExpectedCredits(401), ExpectedCredits(474), CreditsDelta(73)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(30), Batch(1), ExpectedCredits(802), ExpectedCredits(947), CreditsDelta(145)),
|
||||
// 1080p and 4K downgrade to 720p, so the premium matches 720p.
|
||||
(Some(CommonResolution::TenEightyP), Seconds(5), Batch(1), ExpectedCredits(134), ExpectedCredits(158), CreditsDelta(24)),
|
||||
(Some(CommonResolution::FourK), Seconds(5), Batch(1), ExpectedCredits(134), ExpectedCredits(158), CreditsDelta(24)),
|
||||
];
|
||||
|
||||
for (resolution, seconds, batch, base, variant, delta) in cases {
|
||||
assert_variant_charges_premium(
|
||||
&harness,
|
||||
CommonVideoModel::Seedance2p5,
|
||||
CommonVideoModel::Seedance2p5Ultra,
|
||||
*resolution, *seconds, *batch, *base, *variant, *delta,
|
||||
).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
-117
@@ -1,117 +0,0 @@
|
||||
//! Seedance 2.5 family pricing tests: 2.5 and 2.5 Ultra through the real
|
||||
//! generate endpoint against the test database, asserting exact wallet
|
||||
//! debits — including the reference-video input-seconds dimension.
|
||||
//!
|
||||
//! Reference-video note: the fixture media files point at unreachable CDN
|
||||
//! URLs, so the duration probe fails open and bills the worst-case 30 input
|
||||
//! seconds (pinned here), and the provider upload then fails, triggering a
|
||||
//! refund. The ledger entry keeps its original debit amount with
|
||||
//! `is_refunded = true`, which lets these tests assert the exact charge for
|
||||
//! reference-video requests without any real media.
|
||||
|
||||
use enums::common::generation::common_resolution::CommonResolution;
|
||||
use enums::common::generation::common_video_model::CommonVideoModel;
|
||||
|
||||
use super::support::{
|
||||
assert_reference_video_charge_then_refund, assert_successful_generation_charges, Batch,
|
||||
ExpectedCredits, Seconds, TestHarness,
|
||||
};
|
||||
|
||||
// ── Text-to-video pricing (successful generation via the stub provider) ──
|
||||
|
||||
#[tokio::test]
|
||||
#[cfg_attr(feature = "skip_database_tests", ignore)]
|
||||
async fn seedance_2p5_charges_by_resolution_and_duration() {
|
||||
let harness = TestHarness::create().await;
|
||||
|
||||
// 2.5 rates: 480p 11.76954733 ¢/s, 720p 26.70781893 ¢/s, ceil-rounded.
|
||||
// Only 480p/720p exist; 1080p downgrades to 720p pricing. No batching.
|
||||
let cases: &[(Option<CommonResolution>, Seconds, ExpectedCredits)] = &[
|
||||
(Some(CommonResolution::FourEightyP), Seconds(4), ExpectedCredits(48)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(5), ExpectedCredits(59)),
|
||||
(Some(CommonResolution::FourEightyP), Seconds(30), ExpectedCredits(354)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(4), ExpectedCredits(107)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(5), ExpectedCredits(134)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(10), ExpectedCredits(268)),
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(30), ExpectedCredits(802)),
|
||||
// Default resolution is 720p.
|
||||
(None, Seconds(5), ExpectedCredits(134)),
|
||||
];
|
||||
|
||||
for (resolution, seconds, expected) in cases {
|
||||
assert_successful_generation_charges(
|
||||
&harness,
|
||||
CommonVideoModel::Seedance2p5,
|
||||
*resolution,
|
||||
*seconds,
|
||||
Batch(1),
|
||||
*expected,
|
||||
)
|
||||
.await;
|
||||
}
|
||||
}
|
||||
|
||||
/// Seedance 2.5 Ultra is fulfilled by Seedance 2.5 but has its own (higher)
|
||||
/// price. Same shape as the 2.0 collapse-bug pins: if the pipeline ever
|
||||
/// collapses Ultra before billing, these fail with the regular 2.5 numbers.
|
||||
#[tokio::test]
|
||||
#[cfg_attr(feature = "skip_database_tests", ignore)]
|
||||
async fn seedance_2p5_ultra_charges_its_own_higher_rates() {
|
||||
let harness = TestHarness::create().await;
|
||||
|
||||
// Ultra rates: 480p 13.90946502 ¢/s, 720p 31.56378601 ¢/s, ceil-rounded.
|
||||
let cases: &[(Option<CommonResolution>, Seconds, ExpectedCredits)] = &[
|
||||
(Some(CommonResolution::FourEightyP), Seconds(5), ExpectedCredits(70)), // regular would be 59
|
||||
(Some(CommonResolution::FourEightyP), Seconds(30), ExpectedCredits(418)), // regular would be 354
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(5), ExpectedCredits(158)), // regular would be 134
|
||||
(Some(CommonResolution::SevenTwentyP), Seconds(30), ExpectedCredits(947)), // regular would be 802
|
||||
(None, Seconds(5), ExpectedCredits(158)),
|
||||
];
|
||||
|
||||
for (resolution, seconds, expected) in cases {
|
||||
assert_successful_generation_charges(
|
||||
&harness,
|
||||
CommonVideoModel::Seedance2p5Ultra,
|
||||
*resolution,
|
||||
*seconds,
|
||||
Batch(1),
|
||||
*expected,
|
||||
)
|
||||
.await;
|
||||
}
|
||||
}
|
||||
|
||||
// ── Reference-video input-seconds billing ──
|
||||
//
|
||||
// With video references the per-second rate drops but billed seconds =
|
||||
// output duration + probed input seconds. Unreachable fixture media probes
|
||||
// fail open to the 30-second worst case:
|
||||
// 2.5: 480p with refs = 7.24279835 ¢/s → 30s out + 30s in = 60 × rate = 435
|
||||
// 2.5: 720p with refs = 15.84362140 ¢/s → 60 × rate = 951
|
||||
// Ultra: 480p with refs = 8.55967078 ¢/s → 60 × rate = 514
|
||||
// Ultra: 720p with refs = 18.72427984 ¢/s → 60 × rate = 1124
|
||||
|
||||
#[tokio::test]
|
||||
#[cfg_attr(feature = "skip_database_tests", ignore)]
|
||||
async fn seedance_2p5_bills_reference_video_input_seconds_at_worst_case_when_unprobeable() {
|
||||
let harness = TestHarness::create().await;
|
||||
|
||||
let cases: &[(CommonVideoModel, Option<CommonResolution>, Seconds, ExpectedCredits)] = &[
|
||||
(CommonVideoModel::Seedance2p5, Some(CommonResolution::FourEightyP), Seconds(30), ExpectedCredits(435)),
|
||||
(CommonVideoModel::Seedance2p5, Some(CommonResolution::SevenTwentyP), Seconds(30), ExpectedCredits(951)),
|
||||
(CommonVideoModel::Seedance2p5Ultra, Some(CommonResolution::FourEightyP), Seconds(30), ExpectedCredits(514)),
|
||||
(CommonVideoModel::Seedance2p5Ultra, Some(CommonResolution::SevenTwentyP), Seconds(30), ExpectedCredits(1124)),
|
||||
];
|
||||
|
||||
for (model, resolution, seconds, expected) in cases {
|
||||
assert_reference_video_charge_then_refund(
|
||||
&harness,
|
||||
*model,
|
||||
*resolution,
|
||||
*seconds,
|
||||
Batch(1),
|
||||
*expected,
|
||||
)
|
||||
.await;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user