domain_encode_non_serde.rs (44077B)
1 #[path = "../src/test_fixtures.rs"] 2 mod test_fixtures; 3 4 use std::str::FromStr; 5 6 use radroots_core::{ 7 RadrootsCoreCurrency, RadrootsCoreDecimal, RadrootsCoreMoney, RadrootsCoreQuantity, 8 RadrootsCoreQuantityPrice, RadrootsCoreUnit, 9 }; 10 use radroots_events::{ 11 coop::{RadrootsCoop, RadrootsCoopLocation, RadrootsCoopRef}, 12 document::{RadrootsDocument, RadrootsDocumentSubject}, 13 farm::{ 14 RadrootsFarm, RadrootsFarmLocation, RadrootsFarmRef, RadrootsGcsLocation, 15 RadrootsGeoJsonPoint, RadrootsGeoJsonPolygon, 16 }, 17 ids::{RadrootsDTag, RadrootsInventoryBinId}, 18 listing::{ 19 RadrootsListing, RadrootsListingAvailability, RadrootsListingBin, 20 RadrootsListingDeliveryMethod, RadrootsListingLocation, RadrootsListingProduct, 21 }, 22 plot::{RadrootsPlot, RadrootsPlotLocation, RadrootsPlotRef}, 23 resource_area::{RadrootsResourceArea, RadrootsResourceAreaLocation, RadrootsResourceAreaRef}, 24 resource_cap::{RadrootsResourceHarvestCap, RadrootsResourceHarvestProduct}, 25 }; 26 use radroots_events_codec::coop::encode::{coop_build_tags, coop_ref_tags}; 27 use radroots_events_codec::coop::list_sets::{coop_members_farms_list_set, coop_members_list_set}; 28 use radroots_events_codec::document::encode::document_build_tags; 29 use radroots_events_codec::error::EventEncodeError; 30 use radroots_events_codec::farm::encode::{farm_build_tags, farm_ref_tags}; 31 use radroots_events_codec::farm::list_sets::{farm_listings_list_set, farm_members_list_set}; 32 use radroots_events_codec::listing::encode::listing_build_tags; 33 use radroots_events_codec::listing::tags::{ 34 ListingTagOptions, listing_tags_full, listing_tags_with_options, 35 }; 36 use radroots_events_codec::plot::encode::{plot_address, plot_build_tags}; 37 use radroots_events_codec::resource_area::encode::{ 38 resource_area_build_tags, resource_area_ref_tags, 39 }; 40 use radroots_events_codec::resource_area::list_sets::{ 41 resource_area_members_farms_list_set, resource_area_members_plots_list_set, 42 resource_area_stewards_list_set, 43 }; 44 use radroots_events_codec::resource_cap::encode::resource_harvest_cap_build_tags; 45 use test_fixtures::FIXTURE_ALICE_PUBLIC_KEY_HEX; 46 47 const VALID_PUBKEY: &str = FIXTURE_ALICE_PUBLIC_KEY_HEX; 48 const VALID_FARM_D_TAG: &str = "AAAAAAAAAAAAAAAAAAAAAA"; 49 const VALID_PLOT_D_TAG: &str = "AAAAAAAAAAAAAAAAAAAAAQ"; 50 const VALID_COOP_D_TAG: &str = "BAAAAAAAAAAAAAAAAAAAAA"; 51 const VALID_AREA_D_TAG: &str = "AAAAAAAAAAAAAAAAAAAAAw"; 52 const VALID_CAP_D_TAG: &str = "AAAAAAAAAAAAAAAAAAAABA"; 53 const VALID_DOC_D_TAG: &str = "AAAAAAAAAAAAAAAAAAAAAg"; 54 55 fn decimal(value: &str) -> RadrootsCoreDecimal { 56 RadrootsCoreDecimal::from_str(value).expect("valid decimal") 57 } 58 59 fn listing_d_tag(raw: &str) -> RadrootsDTag { 60 raw.parse().unwrap() 61 } 62 63 fn bin_id(raw: &str) -> RadrootsInventoryBinId { 64 raw.parse().unwrap() 65 } 66 67 fn sample_gcs(geohash: &str) -> RadrootsGcsLocation { 68 RadrootsGcsLocation { 69 lat: 37.0, 70 lng: -122.0, 71 geohash: geohash.to_string(), 72 point: RadrootsGeoJsonPoint { 73 r#type: "Point".to_string(), 74 coordinates: [-122.0, 37.0], 75 }, 76 polygon: RadrootsGeoJsonPolygon { 77 r#type: "Polygon".to_string(), 78 coordinates: vec![vec![ 79 [-122.0, 37.0], 80 [-122.0, 37.0001], 81 [-122.0001, 37.0001], 82 [-122.0, 37.0], 83 ]], 84 }, 85 accuracy: None, 86 altitude: None, 87 tag_0: None, 88 label: None, 89 area: None, 90 elevation: None, 91 soil: None, 92 climate: None, 93 gc_id: None, 94 gc_name: None, 95 gc_admin1_id: None, 96 gc_admin1_name: None, 97 gc_country_id: None, 98 gc_country_name: None, 99 } 100 } 101 102 fn sample_coop() -> RadrootsCoop { 103 RadrootsCoop { 104 d_tag: VALID_COOP_D_TAG.to_string(), 105 name: "Test Coop".to_string(), 106 about: None, 107 website: None, 108 picture: None, 109 banner: None, 110 location: Some(RadrootsCoopLocation { 111 primary: None, 112 city: None, 113 region: None, 114 country: None, 115 gcs: sample_gcs("9q8yy"), 116 }), 117 tags: Some(vec!["regional".to_string()]), 118 } 119 } 120 121 fn sample_farm() -> RadrootsFarm { 122 RadrootsFarm { 123 d_tag: VALID_FARM_D_TAG.to_string(), 124 name: "Test Farm".to_string(), 125 about: None, 126 website: None, 127 picture: None, 128 banner: None, 129 location: Some(RadrootsFarmLocation { 130 primary: None, 131 city: None, 132 region: None, 133 country: None, 134 gcs: Some(sample_gcs("9q8yy")), 135 }), 136 tags: Some(vec!["orchard".to_string()]), 137 } 138 } 139 140 fn sample_plot() -> RadrootsPlot { 141 RadrootsPlot { 142 d_tag: VALID_PLOT_D_TAG.to_string(), 143 farm: RadrootsFarmRef { 144 pubkey: VALID_PUBKEY.to_string(), 145 d_tag: VALID_FARM_D_TAG.to_string(), 146 }, 147 name: "Plot 1".to_string(), 148 about: None, 149 location: Some(RadrootsPlotLocation { 150 primary: None, 151 city: None, 152 region: None, 153 country: None, 154 gcs: sample_gcs("9q8yy"), 155 }), 156 tags: Some(vec!["orchard".to_string()]), 157 } 158 } 159 160 fn sample_listing() -> RadrootsListing { 161 let quantity = 162 RadrootsCoreQuantity::new(RadrootsCoreDecimal::from(1u32), RadrootsCoreUnit::Each); 163 let price_per_canonical_unit = RadrootsCoreQuantityPrice::new( 164 RadrootsCoreMoney::new(RadrootsCoreDecimal::from(10u32), RadrootsCoreCurrency::USD), 165 quantity.clone(), 166 ); 167 168 RadrootsListing { 169 d_tag: listing_d_tag(VALID_DOC_D_TAG), 170 published_at: None, 171 farm: RadrootsFarmRef { 172 pubkey: VALID_PUBKEY.to_string(), 173 d_tag: VALID_FARM_D_TAG.to_string(), 174 }, 175 product: RadrootsListingProduct { 176 key: "nutmeg".to_string(), 177 title: "Nutmeg".to_string(), 178 category: "spice".to_string(), 179 summary: None, 180 process: None, 181 lot: None, 182 location: None, 183 profile: None, 184 year: None, 185 }, 186 primary_bin_id: bin_id("bin-1"), 187 bins: vec![RadrootsListingBin { 188 bin_id: bin_id("bin-1"), 189 quantity, 190 price_per_canonical_unit, 191 display_amount: None, 192 display_unit: None, 193 display_label: None, 194 display_price: None, 195 display_price_unit: None, 196 }], 197 resource_area: None, 198 plot: None, 199 discounts: None, 200 inventory_available: Some(decimal("12")), 201 availability: Some(RadrootsListingAvailability::Window { 202 start: Some(1), 203 end: Some(2), 204 }), 205 delivery_method: Some(RadrootsListingDeliveryMethod::Shipping), 206 location: None, 207 images: None, 208 } 209 } 210 211 fn sample_resource_area() -> RadrootsResourceArea { 212 RadrootsResourceArea { 213 d_tag: VALID_AREA_D_TAG.to_string(), 214 name: "Banda Grove".to_string(), 215 about: None, 216 location: RadrootsResourceAreaLocation { 217 primary: None, 218 city: None, 219 region: None, 220 country: None, 221 gcs: sample_gcs("pmb5v"), 222 }, 223 tags: Some(vec!["nutmeg".to_string()]), 224 } 225 } 226 227 fn sample_resource_cap() -> RadrootsResourceHarvestCap { 228 RadrootsResourceHarvestCap { 229 d_tag: VALID_CAP_D_TAG.to_string(), 230 resource_area: RadrootsResourceAreaRef { 231 pubkey: VALID_PUBKEY.to_string(), 232 d_tag: VALID_AREA_D_TAG.to_string(), 233 }, 234 product: RadrootsResourceHarvestProduct { 235 key: "nutmeg".to_string(), 236 category: Some("spice".to_string()), 237 }, 238 start: 1, 239 end: 2, 240 cap_quantity: RadrootsCoreQuantity::new(decimal("1000"), RadrootsCoreUnit::MassG), 241 display_amount: None, 242 display_unit: None, 243 display_label: None, 244 tags: None, 245 } 246 } 247 248 fn sample_document() -> RadrootsDocument { 249 RadrootsDocument { 250 d_tag: VALID_DOC_D_TAG.to_string(), 251 doc_type: "charter".to_string(), 252 title: "Charter".to_string(), 253 version: "1.0.0".to_string(), 254 summary: None, 255 effective_at: None, 256 body_markdown: None, 257 subject: RadrootsDocumentSubject { 258 pubkey: VALID_PUBKEY.to_string(), 259 address: Some(format!("30340:{VALID_PUBKEY}:{VALID_FARM_D_TAG}")), 260 }, 261 tags: Some(vec!["policy".to_string()]), 262 } 263 } 264 265 #[test] 266 fn coop_encode_and_list_set_paths() { 267 let tags = coop_build_tags(&sample_coop()).expect("coop tags"); 268 assert!( 269 tags.iter() 270 .any(|tag| tag.first().map(|v| v.as_str()) == Some("d")) 271 ); 272 assert!( 273 tags.iter() 274 .any(|tag| tag.first().map(|v| v.as_str()) == Some("t")) 275 ); 276 assert!( 277 tags.iter() 278 .any(|tag| tag.first().map(|v| v.as_str()) == Some("g")) 279 ); 280 281 let mut coop = sample_coop(); 282 coop.tags = None; 283 coop.location = None; 284 let tags = coop_build_tags(&coop).expect("coop tags without optional fields"); 285 assert!( 286 !tags 287 .iter() 288 .any(|tag| tag.first().map(|v| v.as_str()) == Some("t")) 289 ); 290 assert!( 291 !tags 292 .iter() 293 .any(|tag| tag.first().map(|v| v.as_str()) == Some("g")) 294 ); 295 296 let mut coop = sample_coop(); 297 coop.d_tag = " ".to_string(); 298 let err = coop_build_tags(&coop).expect_err("empty d_tag"); 299 assert!(matches!(err, EventEncodeError::EmptyRequiredField("d_tag"))); 300 301 let mut coop = sample_coop(); 302 coop.name = " ".to_string(); 303 let err = coop_build_tags(&coop).expect_err("empty name"); 304 assert!(matches!(err, EventEncodeError::EmptyRequiredField("name"))); 305 306 let mut coop = sample_coop(); 307 coop.location.as_mut().expect("location").gcs.geohash = " ".to_string(); 308 let err = coop_build_tags(&coop).expect_err("empty geohash"); 309 assert!(matches!( 310 err, 311 EventEncodeError::EmptyRequiredField("location.gcs.geohash") 312 )); 313 314 let mut coop = sample_coop(); 315 coop.d_tag = "invalid".to_string(); 316 let err = coop_build_tags(&coop).expect_err("invalid d_tag"); 317 assert!(matches!(err, EventEncodeError::InvalidField("d_tag"))); 318 319 let tags = coop_ref_tags(&RadrootsCoopRef { 320 pubkey: VALID_PUBKEY.to_string(), 321 d_tag: VALID_COOP_D_TAG.to_string(), 322 }) 323 .expect("coop ref tags"); 324 assert_eq!(tags.len(), 2); 325 326 let err = coop_ref_tags(&RadrootsCoopRef { 327 pubkey: " ".to_string(), 328 d_tag: VALID_COOP_D_TAG.to_string(), 329 }) 330 .expect_err("empty coop pubkey"); 331 assert!(matches!( 332 err, 333 EventEncodeError::EmptyRequiredField("coop.pubkey") 334 )); 335 336 let err = coop_ref_tags(&RadrootsCoopRef { 337 pubkey: VALID_PUBKEY.to_string(), 338 d_tag: " ".to_string(), 339 }) 340 .expect_err("empty coop d_tag"); 341 assert!(matches!( 342 err, 343 EventEncodeError::EmptyRequiredField("coop.d_tag") 344 )); 345 346 let err = coop_ref_tags(&RadrootsCoopRef { 347 pubkey: VALID_PUBKEY.to_string(), 348 d_tag: "invalid".to_string(), 349 }) 350 .expect_err("invalid coop d_tag"); 351 assert!(matches!(err, EventEncodeError::InvalidField("coop.d_tag"))); 352 353 let err = coop_members_list_set("invalid", ["member"]).expect_err("invalid coop id"); 354 assert!(matches!(err, EventEncodeError::InvalidField("coop_id"))); 355 356 let err = coop_members_list_set(" ", ["member"]).expect_err("empty coop id"); 357 assert!(matches!( 358 err, 359 EventEncodeError::EmptyRequiredField("coop_id") 360 )); 361 362 let members = coop_members_list_set(VALID_COOP_D_TAG, ["member"]).expect("members list set"); 363 assert_eq!(members.entries.len(), 1); 364 assert_eq!(members.entries[0].tag, "p"); 365 366 let err = coop_members_list_set(VALID_COOP_D_TAG, [" "]).expect_err("empty member entry"); 367 assert!(matches!( 368 err, 369 EventEncodeError::EmptyRequiredField("entry.values") 370 )); 371 372 let member_farms = coop_members_farms_list_set( 373 VALID_COOP_D_TAG, 374 vec![RadrootsFarmRef { 375 pubkey: VALID_PUBKEY.to_string(), 376 d_tag: VALID_FARM_D_TAG.to_string(), 377 }], 378 ) 379 .expect("member farms list set"); 380 assert_eq!(member_farms.entries.len(), 2); 381 assert_eq!(member_farms.entries[0].tag, "a"); 382 assert_eq!(member_farms.entries[1].tag, "p"); 383 384 let member_farms_from_array = coop_members_farms_list_set( 385 VALID_COOP_D_TAG, 386 [RadrootsFarmRef { 387 pubkey: VALID_PUBKEY.to_string(), 388 d_tag: VALID_FARM_D_TAG.to_string(), 389 }], 390 ) 391 .expect("member farms list set array"); 392 assert_eq!(member_farms_from_array.entries.len(), 2); 393 assert_eq!(member_farms_from_array.entries[0].tag, "a"); 394 assert_eq!(member_farms_from_array.entries[1].tag, "p"); 395 396 let err = coop_members_farms_list_set( 397 VALID_COOP_D_TAG, 398 vec![RadrootsFarmRef { 399 pubkey: " ".to_string(), 400 d_tag: VALID_FARM_D_TAG.to_string(), 401 }], 402 ) 403 .expect_err("empty farm pubkey"); 404 assert!(matches!( 405 err, 406 EventEncodeError::EmptyRequiredField("farm.pubkey") 407 )); 408 409 let err = coop_members_farms_list_set( 410 VALID_COOP_D_TAG, 411 vec![RadrootsFarmRef { 412 pubkey: VALID_PUBKEY.to_string(), 413 d_tag: " ".to_string(), 414 }], 415 ) 416 .expect_err("empty farm d_tag"); 417 assert!(matches!( 418 err, 419 EventEncodeError::EmptyRequiredField("farm.d_tag") 420 )); 421 422 let err = coop_members_farms_list_set( 423 VALID_COOP_D_TAG, 424 vec![RadrootsFarmRef { 425 pubkey: VALID_PUBKEY.to_string(), 426 d_tag: "invalid".to_string(), 427 }], 428 ) 429 .expect_err("invalid farm d_tag"); 430 assert!(matches!(err, EventEncodeError::InvalidField("farm.d_tag"))); 431 } 432 433 #[test] 434 fn farm_encode_and_list_set_paths() { 435 let tags = farm_build_tags(&sample_farm()).expect("farm tags"); 436 assert!( 437 tags.iter() 438 .any(|tag| tag.first().map(|v| v.as_str()) == Some("d")) 439 ); 440 assert!( 441 tags.iter() 442 .any(|tag| tag.first().map(|v| v.as_str()) == Some("t")) 443 ); 444 assert!( 445 tags.iter() 446 .any(|tag| tag.first().map(|v| v.as_str()) == Some("g")) 447 ); 448 449 let mut farm = sample_farm(); 450 farm.tags = None; 451 farm.location = None; 452 let tags = farm_build_tags(&farm).expect("farm tags without optional fields"); 453 assert!( 454 !tags 455 .iter() 456 .any(|tag| tag.first().map(|v| v.as_str()) == Some("t")) 457 ); 458 assert!( 459 !tags 460 .iter() 461 .any(|tag| tag.first().map(|v| v.as_str()) == Some("g")) 462 ); 463 464 let mut farm = sample_farm(); 465 farm.d_tag = " ".to_string(); 466 let err = farm_build_tags(&farm).expect_err("empty d_tag"); 467 assert!(matches!(err, EventEncodeError::EmptyRequiredField("d_tag"))); 468 469 let mut farm = sample_farm(); 470 farm.name = " ".to_string(); 471 let err = farm_build_tags(&farm).expect_err("empty name"); 472 assert!(matches!(err, EventEncodeError::EmptyRequiredField("name"))); 473 474 let mut farm = sample_farm(); 475 farm.location 476 .as_mut() 477 .expect("location") 478 .gcs 479 .as_mut() 480 .expect("gcs") 481 .geohash = " ".to_string(); 482 let err = farm_build_tags(&farm).expect_err("empty geohash"); 483 assert!(matches!( 484 err, 485 EventEncodeError::EmptyRequiredField("location.gcs.geohash") 486 )); 487 488 let mut farm = sample_farm(); 489 farm.location.as_mut().expect("location").gcs = None; 490 let tags = farm_build_tags(&farm).expect("farm location without geo"); 491 assert!( 492 !tags 493 .iter() 494 .any(|tag| tag.first().map(|v| v.as_str()) == Some("g")) 495 ); 496 497 let tags = farm_ref_tags(&RadrootsFarmRef { 498 pubkey: VALID_PUBKEY.to_string(), 499 d_tag: VALID_FARM_D_TAG.to_string(), 500 }) 501 .expect("farm ref tags"); 502 assert_eq!(tags.len(), 2); 503 504 let err = farm_ref_tags(&RadrootsFarmRef { 505 pubkey: " ".to_string(), 506 d_tag: VALID_FARM_D_TAG.to_string(), 507 }) 508 .expect_err("empty farm pubkey"); 509 assert!(matches!( 510 err, 511 EventEncodeError::EmptyRequiredField("farm.pubkey") 512 )); 513 514 let err = farm_ref_tags(&RadrootsFarmRef { 515 pubkey: VALID_PUBKEY.to_string(), 516 d_tag: " ".to_string(), 517 }) 518 .expect_err("empty farm d_tag"); 519 assert!(matches!( 520 err, 521 EventEncodeError::EmptyRequiredField("farm.d_tag") 522 )); 523 524 let err = farm_ref_tags(&RadrootsFarmRef { 525 pubkey: VALID_PUBKEY.to_string(), 526 d_tag: "invalid".to_string(), 527 }) 528 .expect_err("invalid farm d_tag"); 529 assert!(matches!(err, EventEncodeError::InvalidField("farm.d_tag"))); 530 531 let err = farm_members_list_set("invalid", ["member"]).expect_err("invalid farm id"); 532 assert!(matches!(err, EventEncodeError::InvalidField("farm_id"))); 533 534 let err = farm_members_list_set(VALID_FARM_D_TAG, [" "]).expect_err("empty member entry"); 535 assert!(matches!( 536 err, 537 EventEncodeError::EmptyRequiredField("entry.values") 538 )); 539 540 let err = farm_listings_list_set(VALID_FARM_D_TAG, VALID_PUBKEY, [" "]) 541 .expect_err("empty listing id"); 542 assert!(matches!( 543 err, 544 EventEncodeError::EmptyRequiredField("listing_id") 545 )); 546 547 let err = farm_listings_list_set(VALID_FARM_D_TAG, VALID_PUBKEY, ["invalid"]) 548 .expect_err("invalid listing id"); 549 assert!(matches!(err, EventEncodeError::InvalidField("listing_id"))); 550 } 551 552 #[test] 553 fn plot_encode_paths() { 554 let tags = plot_build_tags(&sample_plot()).expect("plot tags"); 555 assert!( 556 tags.iter() 557 .any(|tag| tag.first().map(|v| v.as_str()) == Some("a")) 558 ); 559 assert!( 560 tags.iter() 561 .any(|tag| tag.first().map(|v| v.as_str()) == Some("p")) 562 ); 563 assert!( 564 tags.iter() 565 .any(|tag| tag.first().map(|v| v.as_str()) == Some("t")) 566 ); 567 assert!( 568 tags.iter() 569 .any(|tag| tag.first().map(|v| v.as_str()) == Some("g")) 570 ); 571 572 let mut plot = sample_plot(); 573 plot.tags = None; 574 plot.location = None; 575 let tags = plot_build_tags(&plot).expect("plot tags without optional fields"); 576 assert!( 577 !tags 578 .iter() 579 .any(|tag| tag.first().map(|v| v.as_str()) == Some("t")) 580 ); 581 assert!( 582 !tags 583 .iter() 584 .any(|tag| tag.first().map(|v| v.as_str()) == Some("g")) 585 ); 586 587 let err = plot_address(" ", VALID_PLOT_D_TAG).expect_err("empty author pubkey"); 588 assert!(matches!( 589 err, 590 EventEncodeError::EmptyRequiredField("plot.author_pubkey") 591 )); 592 593 let err = plot_address(VALID_PUBKEY, " ").expect_err("empty plot d_tag"); 594 assert!(matches!( 595 err, 596 EventEncodeError::EmptyRequiredField("plot.d_tag") 597 )); 598 599 let err = plot_address(VALID_PUBKEY, "invalid").expect_err("invalid plot d_tag"); 600 assert!(matches!(err, EventEncodeError::InvalidField("plot.d_tag"))); 601 602 let mut plot = sample_plot(); 603 plot.d_tag = " ".to_string(); 604 let err = plot_build_tags(&plot).expect_err("empty plot d_tag"); 605 assert!(matches!(err, EventEncodeError::EmptyRequiredField("d_tag"))); 606 607 let mut plot = sample_plot(); 608 plot.name = " ".to_string(); 609 let err = plot_build_tags(&plot).expect_err("empty plot name"); 610 assert!(matches!(err, EventEncodeError::EmptyRequiredField("name"))); 611 612 let mut plot = sample_plot(); 613 plot.farm.pubkey = " ".to_string(); 614 let err = plot_build_tags(&plot).expect_err("empty farm pubkey"); 615 assert!(matches!( 616 err, 617 EventEncodeError::EmptyRequiredField("farm.pubkey") 618 )); 619 620 let mut plot = sample_plot(); 621 plot.farm.d_tag = " ".to_string(); 622 let err = plot_build_tags(&plot).expect_err("empty farm d_tag"); 623 assert!(matches!( 624 err, 625 EventEncodeError::EmptyRequiredField("farm.d_tag") 626 )); 627 628 let mut plot = sample_plot(); 629 plot.farm.d_tag = "invalid".to_string(); 630 let err = plot_build_tags(&plot).expect_err("invalid farm d_tag"); 631 assert!(matches!(err, EventEncodeError::InvalidField("farm.d_tag"))); 632 633 let mut plot = sample_plot(); 634 plot.location.as_mut().expect("location").gcs.geohash = " ".to_string(); 635 let err = plot_build_tags(&plot).expect_err("empty geohash"); 636 assert!(matches!( 637 err, 638 EventEncodeError::EmptyRequiredField("location.gcs.geohash") 639 )); 640 } 641 642 #[test] 643 fn listing_encode_paths() { 644 let listing = sample_listing(); 645 let tags = listing_build_tags(&listing).expect("listing tags"); 646 assert!( 647 tags.iter() 648 .any(|tag| tag.first().map(|v| v.as_str()) == Some("d")) 649 ); 650 651 let full_tags = listing_tags_full(&listing).expect("listing full tags"); 652 assert!(full_tags.iter().any(|tag| { 653 tag.first().map(|v| v.as_str()) == Some("inventory") 654 && tag.get(1).map(|v| v.as_str()) == Some("12") 655 })); 656 assert!(full_tags.iter().any(|tag| { 657 tag.first().map(|v| v.as_str()) == Some("radroots:availability_start") 658 && tag.get(1).map(|v| v.as_str()) == Some("1") 659 })); 660 assert!(full_tags.iter().any(|tag| { 661 tag.first().map(|v| v.as_str()) == Some("expires_at") 662 && tag.get(1).map(|v| v.as_str()) == Some("2") 663 })); 664 assert!(full_tags.iter().any(|tag| { 665 tag.first().map(|v| v.as_str()) == Some("delivery") 666 && tag.get(1).map(|v| v.as_str()) == Some("shipping") 667 })); 668 669 let with_trade_fields: fn() -> ListingTagOptions = ListingTagOptions::with_trade_fields; 670 let option_tags = 671 listing_tags_with_options(&listing, with_trade_fields()).expect("listing option tags"); 672 assert!(option_tags.iter().any(|tag| { 673 tag.first().map(|v| v.as_str()) == Some("inventory") 674 && tag.get(1).map(|v| v.as_str()) == Some("12") 675 })); 676 677 let mut listing_with_display_fallback = sample_listing(); 678 listing_with_display_fallback.bins[0].quantity = listing_with_display_fallback.bins[0] 679 .quantity 680 .clone() 681 .with_label("fallback-label"); 682 listing_with_display_fallback.bins[0].display_amount = Some(decimal("1")); 683 listing_with_display_fallback.bins[0].display_unit = Some(RadrootsCoreUnit::Each); 684 listing_with_display_fallback.bins[0].display_label = None; 685 let display_tags = 686 listing_tags_with_options(&listing_with_display_fallback, ListingTagOptions::default()) 687 .expect("listing tags with display fallback"); 688 assert!(display_tags.iter().any(|tag| { 689 tag.first().map(|v| v.as_str()) == Some("radroots:bin") 690 && tag.last().map(|v| v.as_str()) == Some("fallback-label") 691 })); 692 693 let mut listing_with_geohash = sample_listing(); 694 listing_with_geohash.location = Some(RadrootsListingLocation { 695 primary: "Origin".to_string(), 696 city: None, 697 region: None, 698 country: None, 699 lat: None, 700 lng: None, 701 geohash: Some("6gkzwgjzn".to_string()), 702 }); 703 let decoded_tags = listing_tags_with_options( 704 &listing_with_geohash, 705 ListingTagOptions { 706 include_geohash: false, 707 include_gps: true, 708 ..ListingTagOptions::default() 709 }, 710 ) 711 .expect("listing tags with decoded geohash"); 712 assert!(decoded_tags.iter().any(|tag| { 713 tag.first().map(|v| v.as_str()) == Some("l") && tag.get(2).map(|v| v.as_str()) == Some("dd") 714 })); 715 716 let mut listing_with_shared_geohash = sample_listing(); 717 listing_with_shared_geohash.location = Some(RadrootsListingLocation { 718 primary: "Origin".to_string(), 719 city: None, 720 region: None, 721 country: None, 722 lat: None, 723 lng: None, 724 geohash: Some("6gkzwgjzn".to_string()), 725 }); 726 let shared_geohash_tags = 727 listing_tags_with_options(&listing_with_shared_geohash, ListingTagOptions::default()) 728 .expect("listing tags with shared geohash"); 729 assert!(shared_geohash_tags.iter().any(|tag| { 730 tag.first().map(|v| v.as_str()) == Some("g") 731 && tag.get(1).map(|v| v.as_str()) == Some("6gkzwgjzn") 732 })); 733 734 let mut listing_without_coordinates = sample_listing(); 735 listing_without_coordinates.location = Some(RadrootsListingLocation { 736 primary: "Origin".to_string(), 737 city: None, 738 region: None, 739 country: None, 740 lat: None, 741 lng: None, 742 geohash: None, 743 }); 744 let no_coordinates_tags = 745 listing_tags_with_options(&listing_without_coordinates, ListingTagOptions::default()) 746 .expect("listing tags without coordinates"); 747 assert!( 748 !no_coordinates_tags 749 .iter() 750 .any(|tag| tag.first().map(|v| v.as_str()) == Some("L")) 751 ); 752 assert!( 753 !no_coordinates_tags 754 .iter() 755 .any(|tag| tag.first().map(|v| v.as_str()) == Some("g")) 756 ); 757 758 let mut listing_with_blank_optionals = sample_listing(); 759 listing_with_blank_optionals.product.summary = Some(" ".to_string()); 760 listing_with_blank_optionals.product.process = Some("null".to_string()); 761 listing_with_blank_optionals.product.location = Some(" ".to_string()); 762 listing_with_blank_optionals.product.profile = Some("null".to_string()); 763 listing_with_blank_optionals.product.year = Some(" ".to_string()); 764 listing_with_blank_optionals.location = Some(RadrootsListingLocation { 765 primary: " ".to_string(), 766 city: Some(" ".to_string()), 767 region: Some("null".to_string()), 768 country: Some(" ".to_string()), 769 lat: None, 770 lng: None, 771 geohash: None, 772 }); 773 let blank_optional_tags = 774 listing_tags_with_options(&listing_with_blank_optionals, ListingTagOptions::default()) 775 .expect("listing tags with blank optional values"); 776 assert!( 777 !blank_optional_tags 778 .iter() 779 .any(|tag| tag.first().map(|v| v.as_str()) == Some("summary")) 780 ); 781 assert!( 782 !blank_optional_tags 783 .iter() 784 .any(|tag| tag.first().map(|v| v.as_str()) == Some("location")) 785 ); 786 787 let mut listing_no_gps = sample_listing(); 788 listing_no_gps.location = Some(RadrootsListingLocation { 789 primary: "Origin".to_string(), 790 city: None, 791 region: None, 792 country: None, 793 lat: Some(37.0), 794 lng: Some(-122.0), 795 geohash: None, 796 }); 797 let no_gps_tags = listing_tags_with_options( 798 &listing_no_gps, 799 ListingTagOptions { 800 include_gps: false, 801 ..ListingTagOptions::default() 802 }, 803 ) 804 .expect("listing tags without gps labels"); 805 assert!( 806 !no_gps_tags 807 .iter() 808 .any(|tag| tag.first().map(|v| v.as_str()) == Some("L")) 809 ); 810 811 let mut listing_without_availability = sample_listing(); 812 listing_without_availability.availability = None; 813 let no_availability_tags = 814 listing_tags_with_options(&listing_without_availability, with_trade_fields()) 815 .expect("listing tags without availability"); 816 assert!( 817 !no_availability_tags 818 .iter() 819 .any(|tag| { tag.first().map(|v| v.as_str()) == Some("radroots:availability_start") }) 820 ); 821 822 let mut listing_pickup = sample_listing(); 823 listing_pickup.delivery_method = Some(RadrootsListingDeliveryMethod::Pickup); 824 let pickup_tags = listing_tags_with_options(&listing_pickup, with_trade_fields()) 825 .expect("listing tags with pickup delivery"); 826 assert!(pickup_tags.iter().any(|tag| { 827 tag.first().map(|v| v.as_str()) == Some("delivery") 828 && tag.get(1).map(|v| v.as_str()) == Some("pickup") 829 })); 830 831 let mut listing_local = sample_listing(); 832 listing_local.delivery_method = Some(RadrootsListingDeliveryMethod::LocalDelivery); 833 let local_tags = listing_tags_with_options(&listing_local, with_trade_fields()) 834 .expect("listing tags with local delivery"); 835 assert!(local_tags.iter().any(|tag| { 836 tag.first().map(|v| v.as_str()) == Some("delivery") 837 && tag.get(1).map(|v| v.as_str()) == Some("local_delivery") 838 })); 839 840 let mut listing_other_delivery = sample_listing(); 841 listing_other_delivery.delivery_method = Some(RadrootsListingDeliveryMethod::Other { 842 method: "courier".to_string(), 843 }); 844 let other_delivery_tags = 845 listing_tags_with_options(&listing_other_delivery, with_trade_fields()) 846 .expect("listing tags with other delivery"); 847 assert!(other_delivery_tags.iter().any(|tag| { 848 tag.first().map(|v| v.as_str()) == Some("delivery") 849 && tag.get(1).map(|v| v.as_str()) == Some("other") 850 && tag.get(2).map(|v| v.as_str()) == Some("courier") 851 })); 852 853 let mut invalid = sample_listing(); 854 invalid.bins[0].display_price = None; 855 invalid.bins[0].display_price_unit = Some(RadrootsCoreUnit::Each); 856 let err = listing_tags_with_options(&invalid, ListingTagOptions::default()) 857 .expect_err("missing display price"); 858 assert!(matches!( 859 err, 860 EventEncodeError::EmptyRequiredField("bin.display_price") 861 )); 862 863 let mut invalid = sample_listing(); 864 invalid.bins[0].display_price = Some(RadrootsCoreMoney::new( 865 decimal("10"), 866 RadrootsCoreCurrency::USD, 867 )); 868 invalid.bins[0].display_price_unit = None; 869 let err = listing_tags_with_options(&invalid, ListingTagOptions::default()) 870 .expect_err("missing display price unit"); 871 assert!(matches!( 872 err, 873 EventEncodeError::EmptyRequiredField("bin.display_price_unit") 874 )); 875 876 let mut listing_with_display_price = sample_listing(); 877 listing_with_display_price.bins[0].display_price = Some(RadrootsCoreMoney::new( 878 decimal("10"), 879 RadrootsCoreCurrency::USD, 880 )); 881 listing_with_display_price.bins[0].display_price_unit = Some(RadrootsCoreUnit::Each); 882 let display_price_tags = 883 listing_tags_with_options(&listing_with_display_price, ListingTagOptions::default()) 884 .expect("listing tags with display price"); 885 assert!(display_price_tags.iter().any(|tag| { 886 tag.first().map(|v| v.as_str()) == Some("radroots:price") 887 && tag.get(6).map(|v| v.as_str()) == Some("10") 888 && tag.get(7).map(|v| v.as_str()) == Some("each") 889 })); 890 891 let mut invalid = listing_with_display_price.clone(); 892 invalid.bins[0].display_price = Some(RadrootsCoreMoney::new( 893 decimal("10"), 894 RadrootsCoreCurrency::EUR, 895 )); 896 let err = listing_tags_with_options(&invalid, ListingTagOptions::default()) 897 .expect_err("display price currency mismatch"); 898 assert!(matches!( 899 err, 900 EventEncodeError::EmptyRequiredField("bin.display_price") 901 )); 902 903 let mut invalid = sample_listing(); 904 invalid.bins[0].display_amount = None; 905 invalid.bins[0].display_unit = Some(RadrootsCoreUnit::Each); 906 let err = listing_tags_with_options(&invalid, ListingTagOptions::default()) 907 .expect_err("missing display amount"); 908 assert!(matches!( 909 err, 910 EventEncodeError::EmptyRequiredField("bin.display_amount") 911 )); 912 913 let mut invalid = sample_listing(); 914 invalid.bins[0].quantity = RadrootsCoreQuantity::new(decimal("1"), RadrootsCoreUnit::MassKg); 915 invalid.bins[0].price_per_canonical_unit = RadrootsCoreQuantityPrice::new( 916 RadrootsCoreMoney::new(decimal("10"), RadrootsCoreCurrency::USD), 917 RadrootsCoreQuantity::new(decimal("1"), RadrootsCoreUnit::MassG), 918 ); 919 let err = listing_tags_with_options(&invalid, ListingTagOptions::default()) 920 .expect_err("non-canonical bin quantity"); 921 assert!(matches!( 922 err, 923 EventEncodeError::EmptyRequiredField("bin.quantity") 924 )); 925 926 let mut invalid = sample_listing(); 927 invalid.bins[0].price_per_canonical_unit = RadrootsCoreQuantityPrice::new( 928 RadrootsCoreMoney::new(decimal("10"), RadrootsCoreCurrency::USD), 929 RadrootsCoreQuantity::new(decimal("2"), RadrootsCoreUnit::Each), 930 ); 931 let err = listing_tags_with_options(&invalid, ListingTagOptions::default()) 932 .expect_err("price must be per canonical unit"); 933 assert!(matches!( 934 err, 935 EventEncodeError::EmptyRequiredField("bin.price_per_canonical_unit") 936 )); 937 938 let mut invalid = sample_listing(); 939 invalid.bins[0].price_per_canonical_unit = RadrootsCoreQuantityPrice::new( 940 RadrootsCoreMoney::new(decimal("10"), RadrootsCoreCurrency::USD), 941 RadrootsCoreQuantity::new(decimal("1"), RadrootsCoreUnit::MassG), 942 ); 943 let err = listing_tags_with_options(&invalid, ListingTagOptions::default()) 944 .expect_err("non-convertible bin total price"); 945 assert!(matches!( 946 err, 947 EventEncodeError::EmptyRequiredField("bin.price_per_canonical_unit") 948 )); 949 950 let mut invalid = sample_listing(); 951 invalid.farm.d_tag = " ".to_string(); 952 let err = listing_build_tags(&invalid).expect_err("empty listing farm d_tag"); 953 assert!(matches!( 954 err, 955 EventEncodeError::EmptyRequiredField("farm.d_tag") 956 )); 957 958 let mut invalid = sample_listing(); 959 invalid.bins.clear(); 960 let err = 961 listing_tags_with_options(&invalid, ListingTagOptions::default()).expect_err("empty bins"); 962 assert!(matches!(err, EventEncodeError::EmptyRequiredField("bins"))); 963 } 964 965 #[test] 966 fn resource_area_encode_and_list_set_paths() { 967 let tags = resource_area_build_tags(&sample_resource_area()).expect("resource area tags"); 968 assert!( 969 tags.iter() 970 .any(|tag| tag.first().map(|v| v.as_str()) == Some("d")) 971 ); 972 assert!( 973 tags.iter() 974 .any(|tag| tag.first().map(|v| v.as_str()) == Some("g")) 975 ); 976 assert!( 977 tags.iter() 978 .any(|tag| tag.first().map(|v| v.as_str()) == Some("t")) 979 ); 980 981 let mut area = sample_resource_area(); 982 area.tags = None; 983 let tags = resource_area_build_tags(&area).expect("resource area tags without optional tags"); 984 assert!( 985 !tags 986 .iter() 987 .any(|tag| tag.first().map(|v| v.as_str()) == Some("t")) 988 ); 989 990 let mut area = sample_resource_area(); 991 area.d_tag = " ".to_string(); 992 let err = resource_area_build_tags(&area).expect_err("empty d_tag"); 993 assert!(matches!(err, EventEncodeError::EmptyRequiredField("d_tag"))); 994 995 let mut area = sample_resource_area(); 996 area.name = " ".to_string(); 997 let err = resource_area_build_tags(&area).expect_err("empty name"); 998 assert!(matches!(err, EventEncodeError::EmptyRequiredField("name"))); 999 1000 let mut area = sample_resource_area(); 1001 area.location.gcs.geohash = " ".to_string(); 1002 let err = resource_area_build_tags(&area).expect_err("empty geohash"); 1003 assert!(matches!( 1004 err, 1005 EventEncodeError::EmptyRequiredField("location.gcs.geohash") 1006 )); 1007 1008 let tags = resource_area_ref_tags(&RadrootsResourceAreaRef { 1009 pubkey: VALID_PUBKEY.to_string(), 1010 d_tag: VALID_AREA_D_TAG.to_string(), 1011 }) 1012 .expect("resource area ref tags"); 1013 assert_eq!(tags.len(), 2); 1014 1015 let err = resource_area_ref_tags(&RadrootsResourceAreaRef { 1016 pubkey: " ".to_string(), 1017 d_tag: VALID_AREA_D_TAG.to_string(), 1018 }) 1019 .expect_err("empty resource area pubkey"); 1020 assert!(matches!( 1021 err, 1022 EventEncodeError::EmptyRequiredField("resource_area.pubkey") 1023 )); 1024 1025 let err = resource_area_ref_tags(&RadrootsResourceAreaRef { 1026 pubkey: VALID_PUBKEY.to_string(), 1027 d_tag: " ".to_string(), 1028 }) 1029 .expect_err("empty resource area d_tag"); 1030 assert!(matches!( 1031 err, 1032 EventEncodeError::EmptyRequiredField("resource_area.d_tag") 1033 )); 1034 1035 let err = resource_area_ref_tags(&RadrootsResourceAreaRef { 1036 pubkey: VALID_PUBKEY.to_string(), 1037 d_tag: "invalid".to_string(), 1038 }) 1039 .expect_err("invalid resource area d_tag"); 1040 assert!(matches!( 1041 err, 1042 EventEncodeError::InvalidField("resource_area.d_tag") 1043 )); 1044 1045 let err = resource_area_members_farms_list_set( 1046 "invalid", 1047 vec![RadrootsFarmRef { 1048 pubkey: VALID_PUBKEY.to_string(), 1049 d_tag: VALID_FARM_D_TAG.to_string(), 1050 }], 1051 ) 1052 .expect_err("invalid area id"); 1053 assert!(matches!(err, EventEncodeError::InvalidField("area_id"))); 1054 1055 let err = 1056 resource_area_stewards_list_set(VALID_AREA_D_TAG, [" "]).expect_err("empty steward entry"); 1057 assert!(matches!( 1058 err, 1059 EventEncodeError::EmptyRequiredField("entry.values") 1060 )); 1061 1062 let stewards = 1063 resource_area_stewards_list_set(VALID_AREA_D_TAG, ["steward"]).expect("stewards list set"); 1064 assert_eq!(stewards.entries.len(), 1); 1065 assert_eq!(stewards.entries[0].tag, "p"); 1066 1067 let err = resource_area_members_farms_list_set( 1068 VALID_AREA_D_TAG, 1069 vec![RadrootsFarmRef { 1070 pubkey: " ".to_string(), 1071 d_tag: VALID_FARM_D_TAG.to_string(), 1072 }], 1073 ) 1074 .expect_err("empty farm pubkey"); 1075 assert!(matches!( 1076 err, 1077 EventEncodeError::EmptyRequiredField("farm.pubkey") 1078 )); 1079 1080 let err = resource_area_members_farms_list_set( 1081 VALID_AREA_D_TAG, 1082 vec![RadrootsFarmRef { 1083 pubkey: VALID_PUBKEY.to_string(), 1084 d_tag: " ".to_string(), 1085 }], 1086 ) 1087 .expect_err("empty farm d_tag"); 1088 assert!(matches!( 1089 err, 1090 EventEncodeError::EmptyRequiredField("farm.d_tag") 1091 )); 1092 1093 let err = resource_area_members_farms_list_set( 1094 VALID_AREA_D_TAG, 1095 vec![RadrootsFarmRef { 1096 pubkey: VALID_PUBKEY.to_string(), 1097 d_tag: "invalid".to_string(), 1098 }], 1099 ) 1100 .expect_err("invalid farm d_tag"); 1101 assert!(matches!(err, EventEncodeError::InvalidField("farm.d_tag"))); 1102 1103 let err = resource_area_members_plots_list_set( 1104 VALID_AREA_D_TAG, 1105 vec![RadrootsPlotRef { 1106 pubkey: " ".to_string(), 1107 d_tag: VALID_PLOT_D_TAG.to_string(), 1108 }], 1109 ) 1110 .expect_err("empty plot pubkey"); 1111 assert!(matches!( 1112 err, 1113 EventEncodeError::EmptyRequiredField("plot.pubkey") 1114 )); 1115 1116 let err = resource_area_members_plots_list_set( 1117 VALID_AREA_D_TAG, 1118 vec![RadrootsPlotRef { 1119 pubkey: VALID_PUBKEY.to_string(), 1120 d_tag: " ".to_string(), 1121 }], 1122 ) 1123 .expect_err("empty plot d_tag"); 1124 assert!(matches!( 1125 err, 1126 EventEncodeError::EmptyRequiredField("plot.d_tag") 1127 )); 1128 1129 let err = resource_area_members_plots_list_set( 1130 VALID_AREA_D_TAG, 1131 vec![RadrootsPlotRef { 1132 pubkey: VALID_PUBKEY.to_string(), 1133 d_tag: "invalid".to_string(), 1134 }], 1135 ) 1136 .expect_err("invalid plot d_tag"); 1137 assert!(matches!(err, EventEncodeError::InvalidField("plot.d_tag"))); 1138 } 1139 1140 #[test] 1141 fn resource_harvest_cap_encode_paths() { 1142 let tags = resource_harvest_cap_build_tags(&sample_resource_cap()).expect("resource cap tags"); 1143 assert!( 1144 tags.iter() 1145 .any(|tag| tag.first().map(|v| v.as_str()) == Some("category")) 1146 ); 1147 1148 let mut cap = sample_resource_cap(); 1149 cap.product.category = None; 1150 let tags = resource_harvest_cap_build_tags(&cap).expect("resource cap tags without category"); 1151 assert!( 1152 !tags 1153 .iter() 1154 .any(|tag| tag.first().map(|v| v.as_str()) == Some("category")) 1155 ); 1156 1157 let mut cap = sample_resource_cap(); 1158 cap.d_tag = " ".to_string(); 1159 let err = resource_harvest_cap_build_tags(&cap).expect_err("empty cap d_tag"); 1160 assert!(matches!(err, EventEncodeError::EmptyRequiredField("d_tag"))); 1161 1162 let mut cap = sample_resource_cap(); 1163 cap.d_tag = "invalid".to_string(); 1164 let err = resource_harvest_cap_build_tags(&cap).expect_err("invalid cap d_tag"); 1165 assert!(matches!(err, EventEncodeError::InvalidField("d_tag"))); 1166 1167 let mut cap = sample_resource_cap(); 1168 cap.product.key = " ".to_string(); 1169 let err = resource_harvest_cap_build_tags(&cap).expect_err("empty product key"); 1170 assert!(matches!( 1171 err, 1172 EventEncodeError::EmptyRequiredField("product.key") 1173 )); 1174 1175 let mut cap = sample_resource_cap(); 1176 cap.resource_area.pubkey = " ".to_string(); 1177 let err = resource_harvest_cap_build_tags(&cap).expect_err("empty resource_area pubkey"); 1178 assert!(matches!( 1179 err, 1180 EventEncodeError::EmptyRequiredField("resource_area.pubkey") 1181 )); 1182 1183 let mut cap = sample_resource_cap(); 1184 cap.resource_area.d_tag = " ".to_string(); 1185 let err = resource_harvest_cap_build_tags(&cap).expect_err("empty resource_area d_tag"); 1186 assert!(matches!( 1187 err, 1188 EventEncodeError::EmptyRequiredField("resource_area.d_tag") 1189 )); 1190 1191 let mut cap = sample_resource_cap(); 1192 cap.resource_area.d_tag = "invalid".to_string(); 1193 let err = resource_harvest_cap_build_tags(&cap).expect_err("invalid resource_area d_tag"); 1194 assert!(matches!( 1195 err, 1196 EventEncodeError::InvalidField("resource_area.d_tag") 1197 )); 1198 } 1199 1200 #[test] 1201 fn document_encode_paths() { 1202 let tags = document_build_tags(&sample_document()).expect("document tags"); 1203 assert!( 1204 tags.iter() 1205 .any(|tag| tag.first().map(|v| v.as_str()) == Some("d")) 1206 ); 1207 assert!( 1208 tags.iter() 1209 .any(|tag| tag.first().map(|v| v.as_str()) == Some("p")) 1210 ); 1211 assert!( 1212 tags.iter() 1213 .any(|tag| tag.first().map(|v| v.as_str()) == Some("a")) 1214 ); 1215 assert!( 1216 tags.iter() 1217 .any(|tag| tag.first().map(|v| v.as_str()) == Some("t")) 1218 ); 1219 1220 let mut document = sample_document(); 1221 document.subject.address = None; 1222 document.tags = None; 1223 let tags = document_build_tags(&document).expect("document without optional tags"); 1224 assert!( 1225 !tags 1226 .iter() 1227 .any(|tag| tag.first().map(|v| v.as_str()) == Some("a")) 1228 ); 1229 assert!( 1230 !tags 1231 .iter() 1232 .any(|tag| tag.first().map(|v| v.as_str()) == Some("t")) 1233 ); 1234 1235 let mut document = sample_document(); 1236 document.d_tag = " ".to_string(); 1237 let err = document_build_tags(&document).expect_err("empty d_tag"); 1238 assert!(matches!(err, EventEncodeError::EmptyRequiredField("d_tag"))); 1239 1240 let mut document = sample_document(); 1241 document.doc_type = " ".to_string(); 1242 let err = document_build_tags(&document).expect_err("empty doc_type"); 1243 assert!(matches!( 1244 err, 1245 EventEncodeError::EmptyRequiredField("doc_type") 1246 )); 1247 1248 let mut document = sample_document(); 1249 document.title = " ".to_string(); 1250 let err = document_build_tags(&document).expect_err("empty title"); 1251 assert!(matches!(err, EventEncodeError::EmptyRequiredField("title"))); 1252 1253 let mut document = sample_document(); 1254 document.version = " ".to_string(); 1255 let err = document_build_tags(&document).expect_err("empty version"); 1256 assert!(matches!( 1257 err, 1258 EventEncodeError::EmptyRequiredField("version") 1259 )); 1260 1261 let mut document = sample_document(); 1262 document.subject.pubkey = " ".to_string(); 1263 let err = document_build_tags(&document).expect_err("empty subject pubkey"); 1264 assert!(matches!( 1265 err, 1266 EventEncodeError::EmptyRequiredField("subject.pubkey") 1267 )); 1268 1269 let mut document = sample_document(); 1270 document.subject.address = Some(" ".to_string()); 1271 let err = document_build_tags(&document).expect_err("empty subject address"); 1272 assert!(matches!( 1273 err, 1274 EventEncodeError::EmptyRequiredField("subject.address") 1275 )); 1276 1277 let mut document = sample_document(); 1278 document.d_tag = "invalid".to_string(); 1279 let err = document_build_tags(&document).expect_err("invalid d_tag"); 1280 assert!(matches!(err, EventEncodeError::InvalidField("d_tag"))); 1281 } 1282 1283 #[test] 1284 fn resource_harvest_cap_money_type_sanity() { 1285 let money = RadrootsCoreMoney::new(decimal("1"), RadrootsCoreCurrency::USD); 1286 assert_eq!(money.amount.to_string(), "1"); 1287 }