Skip to content

Commit fc162ef

Browse files
author
Mikhail Samin's Claude
committed
Release v1.5.11
Make response parsing lenient: never throw because a field is missing or a different type than expected. The enterprise endpoint can return songs with no score (also missing isrc/upc/label, and some fields on YouTube-sourced entries). Those fields are now optional/nullable and degrade instead of raising. Kept legitimate failures: API status=error, undecodable JSON, transport errors, and caller-input errors (unknown provider, missing token).
1 parent 40bc69c commit fc162ef

3 files changed

Lines changed: 46 additions & 2 deletions

File tree

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
cmake_minimum_required(VERSION 3.16)
2-
project(audd-cpp VERSION 1.5.10 LANGUAGES CXX)
2+
project(audd-cpp VERSION 1.5.11 LANGUAGES CXX)
33

44
# ---------- options ----------
55
option(AUDD_CXX20 "Build with C++20 instead of C++17" OFF)

include/audd/version.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
#ifndef AUDD_VERSION_HPP
99
#define AUDD_VERSION_HPP
1010

11-
#define AUDD_VERSION "1.5.10"
11+
#define AUDD_VERSION "1.5.11"
1212

1313
namespace audd {
1414

tests/test_enterprise_parse.cpp

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,50 @@ TEST_CASE("enterprise chunk extras capture unknown song-level keys") {
5353
CHECK(c.songs[0].extras.at("future_field").get<std::string>() == "future_value");
5454
}
5555

56+
TEST_CASE("enterprise song omitting score/isrc/upc/label parses without throwing") {
57+
// The enterprise endpoint legitimately returns songs with no score and no
58+
// isrc/upc/label. Parsing must never throw on these absent fields; the
59+
// corresponding members default (score 0, strings empty).
60+
auto j = nlohmann::json::parse(R"({
61+
"offset": "00:01:00",
62+
"songs": [{
63+
"timecode": "00:01:00",
64+
"artist": "Unknown Artist",
65+
"title": "Untitled",
66+
"start_offset": 60,
67+
"end_offset": 90
68+
}]
69+
})");
70+
audd::EnterpriseChunkResult c;
71+
CHECK_NOTHROW(c = parse_enterprise_chunk(j));
72+
REQUIRE(c.songs.size() == 1);
73+
CHECK(c.songs[0].artist == "Unknown Artist");
74+
CHECK(c.songs[0].title == "Untitled");
75+
CHECK(c.songs[0].score == 0); // absent -> default
76+
CHECK(c.songs[0].isrc.empty()); // absent -> default
77+
CHECK(c.songs[0].upc.empty()); // absent -> default
78+
CHECK(c.songs[0].label.empty()); // absent -> default
79+
CHECK(c.songs[0].start_offset == 60);
80+
CHECK(c.songs[0].end_offset == 90);
81+
}
82+
83+
TEST_CASE("enterprise song with wrong-typed score does not throw") {
84+
// Defensive: even if score arrives as an unexpected JSON type, parsing
85+
// must not throw; the field simply defaults.
86+
auto j = nlohmann::json::parse(R"({
87+
"songs": [{
88+
"score": {"unexpected": "object"},
89+
"artist": "a",
90+
"title": "b"
91+
}]
92+
})");
93+
audd::EnterpriseChunkResult c;
94+
CHECK_NOTHROW(c = parse_enterprise_chunk(j));
95+
REQUIRE(c.songs.size() == 1);
96+
CHECK(c.songs[0].score == 0);
97+
CHECK(c.songs[0].artist == "a");
98+
}
99+
56100
TEST_CASE("enterprise match thumbnail_url") {
57101
audd::EnterpriseMatch m;
58102
m.song_link = "https://lis.tn/abcd";

0 commit comments

Comments
 (0)