usage_test.go 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  1. package model_test
  2. import (
  3. "testing"
  4. "github.com/labring/aiproxy/core/model"
  5. )
  6. func TestPrice_ValidateConditionalPrices(t *testing.T) {
  7. tests := []struct {
  8. name string
  9. price model.Price
  10. wantErr bool
  11. }{
  12. {
  13. name: "Empty conditional prices",
  14. price: model.Price{
  15. ConditionalPrices: []model.ConditionalPrice{},
  16. },
  17. wantErr: false,
  18. },
  19. {
  20. name: "Nil conditional prices",
  21. price: model.Price{
  22. ConditionalPrices: nil,
  23. },
  24. wantErr: false,
  25. },
  26. {
  27. name: "Valid single condition",
  28. price: model.Price{
  29. ConditionalPrices: []model.ConditionalPrice{
  30. {
  31. Condition: model.PriceCondition{
  32. InputTokenMin: 0,
  33. InputTokenMax: 32000,
  34. OutputTokenMin: 0,
  35. OutputTokenMax: 200,
  36. },
  37. Price: model.Price{
  38. InputPrice: 0.0008,
  39. OutputPrice: 0.002,
  40. },
  41. },
  42. },
  43. },
  44. wantErr: false,
  45. },
  46. {
  47. name: "Valid multiple conditions - doubao-seed-1.6 example",
  48. price: model.Price{
  49. ConditionalPrices: []model.ConditionalPrice{
  50. {
  51. Condition: model.PriceCondition{
  52. InputTokenMin: 0,
  53. InputTokenMax: 32000,
  54. OutputTokenMin: 0,
  55. OutputTokenMax: 200,
  56. },
  57. Price: model.Price{
  58. InputPrice: 0.0008,
  59. OutputPrice: 0.002,
  60. },
  61. },
  62. {
  63. Condition: model.PriceCondition{
  64. InputTokenMin: 0,
  65. InputTokenMax: 32000,
  66. OutputTokenMin: 201,
  67. OutputTokenMax: 16000,
  68. },
  69. Price: model.Price{
  70. InputPrice: 0.0008,
  71. OutputPrice: 0.008,
  72. },
  73. },
  74. {
  75. Condition: model.PriceCondition{
  76. InputTokenMin: 32001,
  77. InputTokenMax: 128000,
  78. },
  79. Price: model.Price{
  80. InputPrice: 0.0012,
  81. OutputPrice: 0.016,
  82. },
  83. },
  84. {
  85. Condition: model.PriceCondition{
  86. InputTokenMin: 128001,
  87. InputTokenMax: 256000,
  88. },
  89. Price: model.Price{
  90. InputPrice: 0.0024,
  91. OutputPrice: 0.024,
  92. },
  93. },
  94. },
  95. },
  96. wantErr: false,
  97. },
  98. {
  99. name: "Invalid input token range - min > max",
  100. price: model.Price{
  101. ConditionalPrices: []model.ConditionalPrice{
  102. {
  103. Condition: model.PriceCondition{
  104. InputTokenMin: 32000,
  105. InputTokenMax: 1000, // min > max
  106. },
  107. Price: model.Price{
  108. InputPrice: 0.0008,
  109. OutputPrice: 0.002,
  110. },
  111. },
  112. },
  113. },
  114. wantErr: true,
  115. },
  116. {
  117. name: "Invalid output token range - min > max",
  118. price: model.Price{
  119. ConditionalPrices: []model.ConditionalPrice{
  120. {
  121. Condition: model.PriceCondition{
  122. InputTokenMin: 0,
  123. InputTokenMax: 32000,
  124. OutputTokenMin: 1000,
  125. OutputTokenMax: 500, // min > max
  126. },
  127. Price: model.Price{
  128. InputPrice: 0.0008,
  129. OutputPrice: 0.002,
  130. },
  131. },
  132. },
  133. },
  134. wantErr: true,
  135. },
  136. {
  137. name: "Overlapping input ranges with overlapping output ranges",
  138. price: model.Price{
  139. ConditionalPrices: []model.ConditionalPrice{
  140. {
  141. Condition: model.PriceCondition{
  142. InputTokenMin: 0,
  143. InputTokenMax: 32000,
  144. OutputTokenMin: 0,
  145. OutputTokenMax: 500,
  146. },
  147. Price: model.Price{
  148. InputPrice: 0.0008,
  149. OutputPrice: 0.002,
  150. },
  151. },
  152. {
  153. Condition: model.PriceCondition{
  154. InputTokenMin: 20000, // overlaps with previous
  155. InputTokenMax: 50000,
  156. OutputTokenMin: 200, // overlaps with previous
  157. OutputTokenMax: 1000,
  158. },
  159. Price: model.Price{
  160. InputPrice: 0.0012,
  161. OutputPrice: 0.008,
  162. },
  163. },
  164. },
  165. },
  166. wantErr: true,
  167. },
  168. {
  169. name: "Overlapping input ranges but non-overlapping output ranges (valid)",
  170. price: model.Price{
  171. ConditionalPrices: []model.ConditionalPrice{
  172. {
  173. Condition: model.PriceCondition{
  174. InputTokenMin: 0,
  175. InputTokenMax: 32000,
  176. OutputTokenMin: 0,
  177. OutputTokenMax: 200,
  178. },
  179. Price: model.Price{
  180. InputPrice: 0.0008,
  181. OutputPrice: 0.002,
  182. },
  183. },
  184. {
  185. Condition: model.PriceCondition{
  186. InputTokenMin: 0, // same input range
  187. InputTokenMax: 32000, // same input range
  188. OutputTokenMin: 201, // non-overlapping output range
  189. OutputTokenMax: 16000,
  190. },
  191. Price: model.Price{
  192. InputPrice: 0.0008,
  193. OutputPrice: 0.008,
  194. },
  195. },
  196. },
  197. },
  198. wantErr: false,
  199. },
  200. {
  201. name: "Improperly ordered conditions",
  202. price: model.Price{
  203. ConditionalPrices: []model.ConditionalPrice{
  204. {
  205. Condition: model.PriceCondition{
  206. InputTokenMin: 32001,
  207. InputTokenMax: 128000,
  208. },
  209. Price: model.Price{
  210. InputPrice: 0.0012,
  211. OutputPrice: 0.016,
  212. },
  213. },
  214. {
  215. Condition: model.PriceCondition{
  216. InputTokenMin: 0,
  217. InputTokenMax: 32000, // should come before the previous one
  218. },
  219. Price: model.Price{
  220. InputPrice: 0.0008,
  221. OutputPrice: 0.002,
  222. },
  223. },
  224. },
  225. },
  226. wantErr: true,
  227. },
  228. {
  229. name: "Valid consecutive ranges",
  230. price: model.Price{
  231. ConditionalPrices: []model.ConditionalPrice{
  232. {
  233. Condition: model.PriceCondition{
  234. InputTokenMin: 0,
  235. InputTokenMax: 32000,
  236. },
  237. Price: model.Price{
  238. InputPrice: 0.0008,
  239. OutputPrice: 0.002,
  240. },
  241. },
  242. {
  243. Condition: model.PriceCondition{
  244. InputTokenMin: 32001, // consecutive with previous
  245. InputTokenMax: 128000,
  246. },
  247. Price: model.Price{
  248. InputPrice: 0.0012,
  249. OutputPrice: 0.016,
  250. },
  251. },
  252. },
  253. },
  254. wantErr: false,
  255. },
  256. {
  257. name: "Gap between ranges (valid)",
  258. price: model.Price{
  259. ConditionalPrices: []model.ConditionalPrice{
  260. {
  261. Condition: model.PriceCondition{
  262. InputTokenMin: 0,
  263. InputTokenMax: 32000,
  264. },
  265. Price: model.Price{
  266. InputPrice: 0.0008,
  267. OutputPrice: 0.002,
  268. },
  269. },
  270. {
  271. Condition: model.PriceCondition{
  272. InputTokenMin: 50000, // gap between 32000 and 50000
  273. InputTokenMax: 128000,
  274. },
  275. Price: model.Price{
  276. InputPrice: 0.0012,
  277. OutputPrice: 0.016,
  278. },
  279. },
  280. },
  281. },
  282. wantErr: false,
  283. },
  284. {
  285. name: "Unbounded ranges (zero values)",
  286. price: model.Price{
  287. ConditionalPrices: []model.ConditionalPrice{
  288. {
  289. Condition: model.PriceCondition{
  290. InputTokenMin: 0, // unbounded min
  291. InputTokenMax: 0, // unbounded max
  292. },
  293. Price: model.Price{
  294. InputPrice: 0.001,
  295. OutputPrice: 0.002,
  296. },
  297. },
  298. },
  299. },
  300. wantErr: false,
  301. },
  302. {
  303. name: "Mixed bounded and unbounded ranges",
  304. price: model.Price{
  305. ConditionalPrices: []model.ConditionalPrice{
  306. {
  307. Condition: model.PriceCondition{
  308. InputTokenMin: 0,
  309. InputTokenMax: 32000,
  310. },
  311. Price: model.Price{
  312. InputPrice: 0.0008,
  313. OutputPrice: 0.002,
  314. },
  315. },
  316. {
  317. Condition: model.PriceCondition{
  318. InputTokenMin: 32001,
  319. InputTokenMax: 0, // unbounded max
  320. },
  321. Price: model.Price{
  322. InputPrice: 0.0012,
  323. OutputPrice: 0.016,
  324. },
  325. },
  326. },
  327. },
  328. wantErr: false,
  329. },
  330. }
  331. for _, tt := range tests {
  332. t.Run(tt.name, func(t *testing.T) {
  333. err := tt.price.ValidateConditionalPrices()
  334. if tt.wantErr {
  335. if err == nil {
  336. t.Errorf("%s: ValidateConditionalPrices() expected error but got nil", tt.name)
  337. }
  338. return
  339. }
  340. if err != nil {
  341. t.Errorf("%s: ValidateConditionalPrices() unexpected error = %v", tt.name, err)
  342. }
  343. })
  344. }
  345. }