From 2fda3e0a04d6cdd0436f7c4a283b051d2d6f07ce Mon Sep 17 00:00:00 2001 From: gkokolatos Date: Fri, 24 Nov 2023 11:18:32 +0100 Subject: [PATCH] Prepare for release 2.1 (#1017) * Add CHANGELOG entry for the release * Update version number throughout * Update vendored source dependency for parson * Update vendored Postgres sources snprintf, strerror * Update version related tests --- CHANGELOG.md | 26 +++ docs/conf.py | 4 +- src/bin/lib/parson/.gitignore | 9 +- src/bin/lib/parson/CMakeLists.txt | 29 ++++ src/bin/lib/parson/README.md | 149 ++++++++++++++++++ src/bin/lib/parson/meson.build | 36 +++++ src/bin/lib/parson/package.json | 12 ++ src/bin/lib/parson/parson.c | 104 ++++++++---- src/bin/lib/parson/parson.h | 20 ++- src/bin/lib/parson/tests.c | 80 ++++++++-- .../lib/parson/tests/test_2_serialized.txt | 1 - .../parson/tests/test_2_serialized_pretty.txt | 53 ------- src/bin/lib/pg/snprintf.h | 5 +- src/bin/lib/pg/strerror.c | 2 +- src/bin/pg_autoctl/azure.c | 4 +- src/bin/pg_autoctl/defaults.h | 2 +- src/monitor/Makefile | 2 +- src/monitor/expected/dummy_update.out | 2 +- src/monitor/metadata.h | 2 +- ...mmy.sql => pgautofailover--2.1--dummy.sql} | 0 src/monitor/pgautofailover.control | 2 +- 21 files changed, 423 insertions(+), 121 deletions(-) create mode 100644 src/bin/lib/parson/CMakeLists.txt create mode 100644 src/bin/lib/parson/README.md create mode 100644 src/bin/lib/parson/meson.build create mode 100644 src/bin/lib/parson/package.json delete mode 100644 src/bin/lib/parson/tests/test_2_serialized.txt delete mode 100644 src/bin/lib/parson/tests/test_2_serialized_pretty.txt rename src/monitor/{pgautofailover--2.0--dummy.sql => pgautofailover--2.1--dummy.sql} (100%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 65470c106..dc5dbde57 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,29 @@ +### pg_auto_failover v2.1 (November 24, 2022) ### + +This release incorporates support for Postgres major version 16, some bug fixes, +documentation updates, and usual code maintenance work. + +### Added +* Support for Postgres major version 16. (#1013, #1006, ) +* Improve on documentation, Docker images, and tutorials. (#964, #954, #947) +* PGDATABASE as default create node --dbname. (#956) +* Add chapters to the documentation navigation. (#954) + +### Fixed +* Makefile .PHONY target is defined throughout where needed. (#1008) +* History file parsing allowing for files longer than 1024 lines. (#995) +* A mistake in setup description (#984) +* Typo in pg_autoctl_do_pgsetup.rst (#961) +* pg_autoctl version Postgres compatibility string. (#951) +* Creating the PGUSER at pg_autoctl create postgres time. (#950) +* Dockerfile compatibility for Citus before 11. (#946) +* Punctuation in README.md. (#945) + +### Changed +* Main Makefile is reorganized to split out citus and azure specifics. (#1008) +* Citus version matrix with new Citus releases. (#990) +* Update Citus from 11.1.2 to 11.1.3 in the build system. (#957) + ### pg_auto_failover v2.0 (October 7, 2022) ### This new release includes support for Citus in pg_auto_failover, the usual diff --git a/docs/conf.py b/docs/conf.py index e477b5bb2..2b58e9582 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -71,9 +71,9 @@ def __init__(self, **options): # built documents. # # The short X.Y version. -version = "2.0" +version = "2.1" # The full version, including alpha/beta/rc tags. -release = "2.0" +release = "2.1" # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/src/bin/lib/parson/.gitignore b/src/bin/lib/parson/.gitignore index 3472ac144..ea09d4897 100644 --- a/src/bin/lib/parson/.gitignore +++ b/src/bin/lib/parson/.gitignore @@ -1,3 +1,8 @@ +.DS_Store +test +*.o testcpp -testcpp.* -test.dSYM +tests/test_2_serialized.txt +tests/test_2_serialized_pretty.txt +test_hash_collisions +build/** diff --git a/src/bin/lib/parson/CMakeLists.txt b/src/bin/lib/parson/CMakeLists.txt new file mode 100644 index 000000000..e2f443487 --- /dev/null +++ b/src/bin/lib/parson/CMakeLists.txt @@ -0,0 +1,29 @@ +cmake_minimum_required(VERSION 3.5) +project(parson C) + +include (GNUInstallDirs) + +set(PARSON_VERSION 1.5.3) +add_library(parson parson.c) +target_include_directories(parson PUBLIC $) + +set_target_properties(parson PROPERTIES PUBLIC_HEADER "parson.h") +set_target_properties(parson PROPERTIES VERSION ${PARSON_VERSION}) +set_target_properties(parson PROPERTIES SOVERSION ${PARSON_VERSION}) + +install( + TARGETS parson + EXPORT parsonTargets + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT shlib + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} +) + +install( + EXPORT parsonTargets + FILE parsonConfig.cmake + NAMESPACE parson:: + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME} +) + diff --git a/src/bin/lib/parson/README.md b/src/bin/lib/parson/README.md new file mode 100644 index 000000000..011e05199 --- /dev/null +++ b/src/bin/lib/parson/README.md @@ -0,0 +1,149 @@ +## About +Parson is a lightweight [json](http://json.org) library written in C. + +## Features +* Lightweight (only 2 files) +* Simple API +* Addressing json values with dot notation (similar to C structs or objects in most OO languages, e.g. "objectA.objectB.value") +* C89 compatible +* Test suites + +## Installation +Run: +``` +git clone https://github.com/kgabis/parson.git +``` +and copy parson.h and parson.c to you source code tree. + +Run ```make test``` to compile and run tests. + +## Examples +### Parsing JSON +Here is a function, which prints basic commit info (date, sha and author) from a github repository. +```c +void print_commits_info(const char *username, const char *repo) { + JSON_Value *root_value; + JSON_Array *commits; + JSON_Object *commit; + size_t i; + + char curl_command[512]; + char cleanup_command[256]; + char output_filename[] = "commits.json"; + + /* it ain't pretty, but it's not a libcurl tutorial */ + sprintf(curl_command, + "curl -s \"https://api.github.com/repos/%s/%s/commits\" > %s", + username, repo, output_filename); + sprintf(cleanup_command, "rm -f %s", output_filename); + system(curl_command); + + /* parsing json and validating output */ + root_value = json_parse_file(output_filename); + if (json_value_get_type(root_value) != JSONArray) { + system(cleanup_command); + return; + } + + /* getting array from root value and printing commit info */ + commits = json_value_get_array(root_value); + printf("%-10.10s %-10.10s %s\n", "Date", "SHA", "Author"); + for (i = 0; i < json_array_get_count(commits); i++) { + commit = json_array_get_object(commits, i); + printf("%.10s %.10s %s\n", + json_object_dotget_string(commit, "commit.author.date"), + json_object_get_string(commit, "sha"), + json_object_dotget_string(commit, "commit.author.name")); + } + + /* cleanup code */ + json_value_free(root_value); + system(cleanup_command); +} + +``` +Calling ```print_commits_info("torvalds", "linux");``` prints: +``` +Date SHA Author +2012-10-15 dd8e8c4a2c David Rientjes +2012-10-15 3ce9e53e78 Michal Marek +2012-10-14 29bb4cc5e0 Randy Dunlap +2012-10-15 325adeb55e Ralf Baechle +2012-10-14 68687c842c Russell King +2012-10-14 ddffeb8c4d Linus Torvalds +... +``` + +### Persistence +In this example I'm using parson to save user information to a file and then load it and validate later. +```c +void persistence_example(void) { + JSON_Value *schema = json_parse_string("{\"name\":\"\"}"); + JSON_Value *user_data = json_parse_file("user_data.json"); + char buf[256]; + const char *name = NULL; + if (user_data == NULL || json_validate(schema, user_data) != JSONSuccess) { + puts("Enter your name:"); + scanf("%s", buf); + user_data = json_value_init_object(); + json_object_set_string(json_object(user_data), "name", buf); + json_serialize_to_file(user_data, "user_data.json"); + } + name = json_object_get_string(json_object(user_data), "name"); + printf("Hello, %s.", name); + json_value_free(schema); + json_value_free(user_data); + return; +} +``` + +### Serialization +Creating JSON values is very simple thanks to the dot notation. +Object hierarchy is automatically created when addressing specific fields. +In the following example I create a simple JSON value containing basic information about a person. +```c +void serialization_example(void) { + JSON_Value *root_value = json_value_init_object(); + JSON_Object *root_object = json_value_get_object(root_value); + char *serialized_string = NULL; + json_object_set_string(root_object, "name", "John Smith"); + json_object_set_number(root_object, "age", 25); + json_object_dotset_string(root_object, "address.city", "Cupertino"); + json_object_dotset_value(root_object, "contact.emails", json_parse_string("[\"email@example.com\",\"email2@example.com\"]")); + serialized_string = json_serialize_to_string_pretty(root_value); + puts(serialized_string); + json_free_serialized_string(serialized_string); + json_value_free(root_value); +} + +``` + +Output: +``` +{ + "name": "John Smith", + "age": 25, + "address": { + "city": "Cupertino" + }, + "contact": { + "emails": [ + "email@example.com", + "email2@example.com" + ] + } +} +``` + +## Contributing + +I will always merge *working* bug fixes. However, if you want to add something new to the API, please create an "issue" on github for this first so we can discuss if it should end up in the library before you start implementing it. +Remember to follow parson's code style and write appropriate tests. + +## My other projects +* [ape](https://github.com/kgabis/ape) - simple programming language implemented in C library +* [kgflags](https://github.com/kgabis/kgflags) - easy to use command-line flag parsing library +* [agnes](https://github.com/kgabis/agnes) - header-only NES emulation library + +## License +[The MIT License (MIT)](http://opensource.org/licenses/mit-license.php) diff --git a/src/bin/lib/parson/meson.build b/src/bin/lib/parson/meson.build new file mode 100644 index 000000000..ab6fb9307 --- /dev/null +++ b/src/bin/lib/parson/meson.build @@ -0,0 +1,36 @@ +project('parson', 'c', + version : '1.5.3', + license : 'MIT', + meson_version : '>=0.46.0', + default_options : [ + 'c_std=c89', 'optimization=2', + 'warning_level=2' + ] +) + +parson_sources = ['parson.c'] + +parson_inc = include_directories('.') + +parson_lib = library( + meson.project_name(), + sources: parson_sources, + install: true +) + +install_headers('parson.h') + +parson = declare_dependency( + include_directories : parson_inc, + link_with : parson_lib +) + +pkgconfig = import('pkgconfig') + +# will create a pkg config +pkgconfig.generate(parson_lib, + version: meson.project_version(), + filebase: meson.project_name(), + name: meson.project_name(), + description: 'Lightweight JSON library written in C.', +) diff --git a/src/bin/lib/parson/package.json b/src/bin/lib/parson/package.json new file mode 100644 index 000000000..8267dc753 --- /dev/null +++ b/src/bin/lib/parson/package.json @@ -0,0 +1,12 @@ +{ + "name": "parson", + "version": "1.5.3", + "repo": "kgabis/parson", + "description": "Small json parser and reader", + "keywords": [ "json", "parser" ], + "license": "MIT", + "src": [ + "parson.c", + "parson.h" + ] +} diff --git a/src/bin/lib/parson/parson.c b/src/bin/lib/parson/parson.c index 6f7e94fb3..2c8630d92 100644 --- a/src/bin/lib/parson/parson.c +++ b/src/bin/lib/parson/parson.c @@ -1,8 +1,8 @@ /* SPDX-License-Identifier: MIT - Parson 1.4.0 (https://github.com/kgabis/parson) - Copyright (c) 2012 - 2022 Krzysztof Gabis + Parson 1.5.3 (https://github.com/kgabis/parson) + Copyright (c) 2012 - 2023 Krzysztof Gabis Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -31,8 +31,8 @@ #include "parson.h" #define PARSON_IMPL_VERSION_MAJOR 1 -#define PARSON_IMPL_VERSION_MINOR 4 -#define PARSON_IMPL_VERSION_PATCH 0 +#define PARSON_IMPL_VERSION_MINOR 5 +#define PARSON_IMPL_VERSION_PATCH 3 #if (PARSON_VERSION_MAJOR != PARSON_IMPL_VERSION_MAJOR)\ || (PARSON_VERSION_MINOR != PARSON_IMPL_VERSION_MINOR)\ @@ -40,6 +40,7 @@ #error "parson version mismatch between parson.c and parson.h" #endif +#include #include #include #include @@ -71,6 +72,10 @@ #define PARSON_NUM_BUF_SIZE 64 /* double printed with "%1.17g" shouldn't be longer than 25 bytes so let's be paranoid and use 64 */ #endif +#ifndef PARSON_INDENT_STR +#define PARSON_INDENT_STR " " +#endif + #define SIZEOF_TOKEN(a) (sizeof(a) - 1) #define SKIP_CHAR(str) ((*str)++) #define SKIP_WHITESPACES(str) while (isspace((unsigned char)(**str))) { SKIP_CHAR(str); } @@ -94,6 +99,8 @@ static int parson_escape_slashes = 1; static char *parson_float_format = NULL; +static JSON_Number_Serialization_Function parson_number_serialization_function = NULL; + #define IS_CONT(b) (((unsigned char)(b) & 0xC0) == 0x80) /* is utf-8 continuation byte */ typedef int parson_bool_t; @@ -146,6 +153,8 @@ static char * read_file(const char *filename); static void remove_comments(char *string, const char *start_token, const char *end_token); static char * parson_strndup(const char *string, size_t n); static char * parson_strdup(const char *string); +static int parson_sprintf(char * s, const char * format, ...); + static int hex_char_to_int(char c); static JSON_Status parse_utf16_hex(const char *string, unsigned int *result); static int num_bytes_in_utf8_sequence(unsigned char c); @@ -192,8 +201,6 @@ static JSON_Value * parse_value(const char **string, size_t nesting); /* Serialization */ static int json_serialize_to_buffer_r(const JSON_Value *value, char *buf, int level, parson_bool_t is_pretty, char *num_buf); static int json_serialize_string(const char *string, size_t len, char *buf); -static int append_indent(char *buf, int level); -static int append_string(char *buf, const char *string); /* Various */ static char * read_file(const char * filename) { @@ -279,6 +286,27 @@ static char * parson_strdup(const char *string) { return parson_strndup(string, strlen(string)); } +static int parson_sprintf(char * s, const char * format, ...) + __attribute__((format(printf, 2, 3))); +static int parson_sprintf(char * s, const char * format, ...) { + int result; + va_list args; + va_start(args, format); + + #if defined(__APPLE__) && defined(__clang__) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wdeprecated-declarations" + #endif + result = vsprintf(s, format, args); + #if defined(__APPLE__) && defined(__clang__) + #pragma clang diagnostic pop + #endif + + va_end(args); + return result; + +} + static int hex_char_to_int(char c) { if (c >= '0' && c <= '9') { return c - '0'; @@ -437,7 +465,7 @@ static JSON_Status json_object_init(JSON_Object *object, size_t capacity) { object->count = 0; object->cell_capacity = capacity; - object->item_capacity = (unsigned int)(capacity * 0.7f); + object->item_capacity = (unsigned int)(capacity * 7/10); if (capacity == 0) { return JSONSuccess; @@ -1095,15 +1123,27 @@ static JSON_Value * parse_null_value(const char **string) { } /* Serialization */ -#define APPEND_STRING(str) do { written = append_string(buf, (str));\ - if (written < 0) { return -1; }\ - if (buf != NULL) { buf += written; }\ - written_total += written; } while(0) -#define APPEND_INDENT(level) do { written = append_indent(buf, (level));\ - if (written < 0) { return -1; }\ - if (buf != NULL) { buf += written; }\ - written_total += written; } while(0) +/* APPEND_STRING() is only called on string literals. + It's a bit hacky because it makes plenty of assumptions about the external state + and should eventually be tidied up into a function (same goes for APPEND_INDENT) + */ +#define APPEND_STRING(str) do {\ + written = SIZEOF_TOKEN((str));\ + if (buf != NULL) {\ + memcpy(buf, (str), written);\ + buf[written] = '\0';\ + buf += written;\ + }\ + written_total += written;\ + } while (0) + +#define APPEND_INDENT(level) do {\ + int level_i = 0;\ + for (level_i = 0; level_i < (level); level_i++) {\ + APPEND_STRING(PARSON_INDENT_STR);\ + }\ + } while (0) static int json_serialize_to_buffer_r(const JSON_Value *value, char *buf, int level, parson_bool_t is_pretty, char *num_buf) { @@ -1225,10 +1265,11 @@ static int json_serialize_to_buffer_r(const JSON_Value *value, char *buf, int le if (buf != NULL) { num_buf = buf; } - if (parson_float_format) { - written = sprintf(num_buf, parson_float_format, num); + if (parson_number_serialization_function) { + written = parson_number_serialization_function(num, num_buf); } else { - written = sprintf(num_buf, PARSON_DEFAULT_FLOAT_FORMAT, num); + const char *float_format = parson_float_format ? parson_float_format : PARSON_DEFAULT_FLOAT_FORMAT; + written = parson_sprintf(num_buf, float_format, num); } if (written < 0) { return -1; @@ -1315,22 +1356,6 @@ static int json_serialize_string(const char *string, size_t len, char *buf) { return written_total; } -static int append_indent(char *buf, int level) { - int i; - int written = -1, written_total = 0; - for (i = 0; i < level; i++) { - APPEND_STRING(" "); - } - return written_total; -} - -static int append_string(char *buf, const char *string) { - if (buf == NULL) { - return (int)strlen(string); - } - return sprintf(buf, "%s", string); -} - #undef APPEND_STRING #undef APPEND_INDENT @@ -2272,9 +2297,15 @@ JSON_Status json_object_clear(JSON_Object *object) { } for (i = 0; i < json_object_get_count(object); i++) { parson_free(object->names[i]); + object->names[i] = NULL; + json_value_free(object->values[i]); + object->values[i] = NULL; } object->count = 0; + for (i = 0; i < object->cell_capacity; i++) { + object->cells[i] = OBJECT_INVALID_IX; + } return JSONSuccess; } @@ -2443,6 +2474,7 @@ void json_set_escape_slashes(int escape_slashes) { void json_set_float_serialization_format(const char *format) { if (parson_float_format) { parson_free(parson_float_format); + parson_float_format = NULL; } if (!format) { parson_float_format = NULL; @@ -2450,3 +2482,7 @@ void json_set_float_serialization_format(const char *format) { } parson_float_format = parson_strdup(format); } + +void json_set_number_serialization_function(JSON_Number_Serialization_Function func) { + parson_number_serialization_function = func; +} diff --git a/src/bin/lib/parson/parson.h b/src/bin/lib/parson/parson.h index fa431f9be..40be490bf 100644 --- a/src/bin/lib/parson/parson.h +++ b/src/bin/lib/parson/parson.h @@ -1,8 +1,8 @@ /* SPDX-License-Identifier: MIT - Parson 1.4.0 (https://github.com/kgabis/parson) - Copyright (c) 2012 - 2022 Krzysztof Gabis + Parson 1.5.3 (https://github.com/kgabis/parson) + Copyright (c) 2012 - 2023 Krzysztof Gabis Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -35,10 +35,10 @@ extern "C" #endif #define PARSON_VERSION_MAJOR 1 -#define PARSON_VERSION_MINOR 4 -#define PARSON_VERSION_PATCH 0 +#define PARSON_VERSION_MINOR 5 +#define PARSON_VERSION_PATCH 3 -#define PARSON_VERSION_STRING "1.4.0" +#define PARSON_VERSION_STRING "1.5.3" #include /* size_t */ @@ -67,6 +67,12 @@ typedef int JSON_Status; typedef void * (*JSON_Malloc_Function)(size_t); typedef void (*JSON_Free_Function)(void *); +/* A function used for serializing numbers (see json_set_number_serialization_function). + If 'buf' is null then it should return number of bytes that would've been written + (but not more than PARSON_NUM_BUF_SIZE). +*/ +typedef int (*JSON_Number_Serialization_Function)(double num, char *buf); + /* Call only once, before calling any other function from parson API. If not called, malloc and free from stdlib will be used for all allocations */ void json_set_allocation_functions(JSON_Malloc_Function malloc_fun, JSON_Free_Function free_fun); @@ -80,6 +86,10 @@ void json_set_escape_slashes(int escape_slashes); If format is null then the default format is used. */ void json_set_float_serialization_format(const char *format); +/* Sets a function that will be used for serialization of numbers. + If function is null then the default serialization function is used. */ +void json_set_number_serialization_function(JSON_Number_Serialization_Function fun); + /* Parses first JSON value in a file, returns NULL in case of error */ JSON_Value * json_parse_file(const char *filename); diff --git a/src/bin/lib/parson/tests.c b/src/bin/lib/parson/tests.c index 895986a1d..3cf97b5d0 100644 --- a/src/bin/lib/parson/tests.c +++ b/src/bin/lib/parson/tests.c @@ -2,7 +2,7 @@ SPDX-License-Identifier: MIT Parson (https://github.com/kgabis/parson) - Copyright (c) 2012 - 2022 Krzysztof Gabis + Copyright (c) 2012 - 2023 Krzysztof Gabis Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -26,6 +26,10 @@ #define _CRT_SECURE_NO_WARNINGS #endif +#if defined(__APPLE__) && defined(__clang__) + #pragma clang diagnostic ignored "-Wdeprecated-declarations" +#endif + #include "parson.h" #include @@ -63,6 +67,8 @@ void test_suite_11(void); /* Additional things that require testing */ void test_memory_leaks(void); void test_failing_allocations(void); void test_custom_number_format(void); +void test_custom_number_serialization_function(void); +void test_object_clear(void); void print_commits_info(const char *username, const char *repo); void persistence_example(void); @@ -132,6 +138,8 @@ int tests_main(int argc, char *argv[]) { test_memory_leaks(); test_failing_allocations(); test_custom_number_format(); + test_custom_number_serialization_function(); + test_object_clear(); printf("Tests failed: %d\n", g_tests_failed); printf("Tests passed: %d\n", g_tests_passed); @@ -365,7 +373,7 @@ void test_suite_3(void) { TEST(g_malloc_count == 0); } -void test_suite_4() { +void test_suite_4(void) { const char *filename = "test_2.txt"; JSON_Value *a = NULL, *a_copy = NULL; a = json_parse_file(get_file_path(filename)); @@ -599,7 +607,7 @@ void test_suite_10(void) { TEST(g_malloc_count == 0); } -void test_suite_11() { +void test_suite_11(void) { const char * array_with_slashes = "[\"a/b/c\"]"; const char * array_with_escaped_slashes = "[\"a\\/b\\/c\"]"; char *serialized = NULL; @@ -617,7 +625,7 @@ void test_suite_11() { TEST(STREQ(array_with_escaped_slashes, serialized)); } -void test_memory_leaks() { +void test_memory_leaks(void) { g_malloc_count = 0; TEST(json_object_set_string(NULL, "lorem", "ipsum") == JSONFailure); @@ -630,7 +638,7 @@ void test_memory_leaks() { TEST(g_malloc_count == 0); } -void test_failing_allocations() { +void test_failing_allocations(void) { const char *filename = "test_2.txt"; JSON_Value *root_value = NULL; JSON_Object *root_object = NULL; @@ -689,19 +697,63 @@ void test_failing_allocations() { } } - json_set_allocation_functions(malloc, free); + json_set_allocation_functions(counted_malloc, counted_free); printf("OK (tested %d failing allocations)\n", n - 1); g_tests_passed++; } -void test_custom_number_format() { - char *serialized = NULL; - JSON_Value *val = json_value_init_number(0.6); - json_set_float_serialization_format("%.1f"); - serialized = json_serialize_to_string(val); - TEST(STREQ(serialized, "0.6")); - json_free_serialized_string(serialized); - json_value_free(val); +void test_custom_number_format(void) { + g_malloc_count = 0; + { + char *serialized = NULL; + JSON_Value *val = json_value_init_number(0.6); + json_set_float_serialization_format("%.1f"); + serialized = json_serialize_to_string(val); + json_set_float_serialization_format(NULL); + TEST(STREQ(serialized, "0.6")); + json_free_serialized_string(serialized); + json_value_free(val); + } + TEST(g_malloc_count == 0); +} + +static int custom_serialization_func_called = 0; +static int custom_serialization_func(double num, char *buf) { + char num_buf[32]; + custom_serialization_func_called = 1; + if (buf == NULL) + buf = num_buf; + return sprintf(buf, "%.1f", num); +} + +void test_custom_number_serialization_function(void) { + g_malloc_count = 0; + { + /* We just test that custom_serialization_func() gets called, not it's performance */ + char *serialized = NULL; + JSON_Value *val = json_value_init_number(0.6); + json_set_number_serialization_function(custom_serialization_func); + serialized = json_serialize_to_string(val); + TEST(STREQ(serialized, "0.6")); + TEST(custom_serialization_func_called); + json_set_number_serialization_function(NULL); + json_free_serialized_string(serialized); + json_value_free(val); + } + TEST(g_malloc_count == 0); +} + +void test_object_clear(void) { + g_malloc_count = 0; + { + JSON_Value *val = json_value_init_object(); + JSON_Object *obj = json_value_get_object(val); + json_object_set_string(obj, "foo", "bar"); + json_object_clear(obj); + TEST(json_object_get_value(obj, "foo") == NULL); + json_value_free(val); + } + TEST(g_malloc_count == 0); } void print_commits_info(const char *username, const char *repo) { diff --git a/src/bin/lib/parson/tests/test_2_serialized.txt b/src/bin/lib/parson/tests/test_2_serialized.txt deleted file mode 100644 index 0088b198d..000000000 --- a/src/bin/lib/parson/tests/test_2_serialized.txt +++ /dev/null @@ -1 +0,0 @@ -{"string":"lorem ipsum","utf string":"lorem ipsum","utf-8 string":"あいうえお","surrogate string":"lorem𝄞ipsum𝍧lorem","string with null":"abc\u0000def","positive one":1,"negative one":-1,"pi":3.1400000000000001,"hard to parse number":-0.00031399999999999999,"big int":2147483647,"big uint":4294967295,"double underflow":6.9041432094973937e-310,"boolean true":true,"boolean false":false,"null":null,"string array":["lorem","ipsum"],"x^2 array":[0,1,4,9,16,25,36,49,64,81,100],"\/*":null,"object":{"nested string":"str","nested true":true,"nested false":false,"nested null":null,"nested number":123,"nested array":["lorem","ipsum"],"nested object":{"lorem":"ipsum"}},"*\/":null,"\/**\/":"comment","\/\/":"comment","url":"https:\/\/www.example.com\/search?q=12345","escaped chars":"\" \\ \/","empty object":{},"empty array":[]} \ No newline at end of file diff --git a/src/bin/lib/parson/tests/test_2_serialized_pretty.txt b/src/bin/lib/parson/tests/test_2_serialized_pretty.txt deleted file mode 100644 index 176cd1416..000000000 --- a/src/bin/lib/parson/tests/test_2_serialized_pretty.txt +++ /dev/null @@ -1,53 +0,0 @@ -{ - "string": "lorem ipsum", - "utf string": "lorem ipsum", - "utf-8 string": "あいうえお", - "surrogate string": "lorem𝄞ipsum𝍧lorem", - "string with null": "abc\u0000def", - "positive one": 1, - "negative one": -1, - "pi": 3.1400000000000001, - "hard to parse number": -0.00031399999999999999, - "big int": 2147483647, - "big uint": 4294967295, - "double underflow": 6.9041432094973937e-310, - "boolean true": true, - "boolean false": false, - "null": null, - "string array": [ - "lorem", - "ipsum" - ], - "x^2 array": [ - 0, - 1, - 4, - 9, - 16, - 25, - 36, - 49, - 64, - 81, - 100 - ], - "\/*": null, - "object": { - "nested string": "str", - "nested true": true, - "nested false": false, - "nested null": null, - "nested number": 123, - "nested array": [ - "lorem", - "ipsum" - ] - }, - "*\/": null, - "\/**\/": "comment", - "\/\/": "comment", - "url": "https:\/\/www.example.com\/search?q=12345", - "escaped chars": "\" \\ \/", - "empty object": {}, - "empty array": [] -} \ No newline at end of file diff --git a/src/bin/lib/pg/snprintf.h b/src/bin/lib/pg/snprintf.h index ed2309125..b8f225031 100644 --- a/src/bin/lib/pg/snprintf.h +++ b/src/bin/lib/pg/snprintf.h @@ -3,7 +3,7 @@ * port.h * Header for src/port/ compatibility functions. * - * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/port.h @@ -17,7 +17,8 @@ #ifndef USE_REPL_SNPRINTF -int pg_vsnprintf(char *str, size_t count, const char *fmt, va_list args); +int pg_vsnprintf(char *str, size_t count, const char *fmt, va_list args) + __attribute__((format(printf, 3, 0))); int pg_snprintf(char *str, size_t count, const char *fmt,...) __attribute__((format(printf, 3, 4))); int pg_vsprintf(char *str, const char *fmt, va_list args); diff --git a/src/bin/lib/pg/strerror.c b/src/bin/lib/pg/strerror.c index 1990cc8a6..cd3ce7ad0 100644 --- a/src/bin/lib/pg/strerror.c +++ b/src/bin/lib/pg/strerror.c @@ -3,7 +3,7 @@ * strerror.c * Replacements for standard strerror() and strerror_r() functions * - * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/bin/pg_autoctl/azure.c b/src/bin/pg_autoctl/azure.c index 7182896ca..4561d71e1 100644 --- a/src/bin/pg_autoctl/azure.c +++ b/src/bin/pg_autoctl/azure.c @@ -1141,8 +1141,8 @@ azure_prepare_target_versions(KeyVal *env) /* default values */ sformat(env->values[0], MAXCONNINFO, "13"); /* AZ_PG_VERSION */ - sformat(env->values[1], MAXCONNINFO, "2.0"); /* AZ_PGAF_DEB_VERSION */ - sformat(env->values[2], MAXCONNINFO, "2.0-1"); /* AZ_PGAF_DEB_REVISION */ + sformat(env->values[1], MAXCONNINFO, "2.1"); /* AZ_PGAF_DEB_VERSION */ + sformat(env->values[2], MAXCONNINFO, "2.1-1"); /* AZ_PGAF_DEB_REVISION */ for (int i = 0; i < 3; i++) { diff --git a/src/bin/pg_autoctl/defaults.h b/src/bin/pg_autoctl/defaults.h index 7ed389ec4..378dae060 100644 --- a/src/bin/pg_autoctl/defaults.h +++ b/src/bin/pg_autoctl/defaults.h @@ -19,7 +19,7 @@ #define PG_AUTOCTL_VERSION GIT_VERSION /* version of the extension that we requite to talk to on the monitor */ -#define PG_AUTOCTL_EXTENSION_VERSION "2.0" +#define PG_AUTOCTL_EXTENSION_VERSION "2.1" /* environment variable to use to make DEBUG facilities available */ #define PG_AUTOCTL_DEBUG "PG_AUTOCTL_DEBUG" diff --git a/src/monitor/Makefile b/src/monitor/Makefile index b91469a7e..88241f516 100644 --- a/src/monitor/Makefile +++ b/src/monitor/Makefile @@ -2,7 +2,7 @@ # Licensed under the PostgreSQL License. EXTENSION = pgautofailover -EXTVERSION = 2.0 +EXTVERSION = 2.1 SRC_DIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) diff --git a/src/monitor/expected/dummy_update.out b/src/monitor/expected/dummy_update.out index cb7009451..33b4c4782 100644 --- a/src/monitor/expected/dummy_update.out +++ b/src/monitor/expected/dummy_update.out @@ -19,5 +19,5 @@ select installed_version -- should error because installed extension isn't compatible with .so select * from pgautofailover.get_primary('unknown formation'); ERROR: loaded "pgautofailover" library version differs from installed extension version -DETAIL: Loaded library requires 2.0, but the installed extension version is dummy. +DETAIL: Loaded library requires 2.1, but the installed extension version is dummy. HINT: Run ALTER EXTENSION pgautofailover UPDATE and try again. diff --git a/src/monitor/metadata.h b/src/monitor/metadata.h index 2a6d27486..98f077923 100644 --- a/src/monitor/metadata.h +++ b/src/monitor/metadata.h @@ -15,7 +15,7 @@ #include "storage/lockdefs.h" -#define AUTO_FAILOVER_EXTENSION_VERSION "2.0" +#define AUTO_FAILOVER_EXTENSION_VERSION "2.1" #define AUTO_FAILOVER_EXTENSION_NAME "pgautofailover" #define AUTO_FAILOVER_SCHEMA_NAME "pgautofailover" #define AUTO_FAILOVER_FORMATION_TABLE "pgautofailover.formation" diff --git a/src/monitor/pgautofailover--2.0--dummy.sql b/src/monitor/pgautofailover--2.1--dummy.sql similarity index 100% rename from src/monitor/pgautofailover--2.0--dummy.sql rename to src/monitor/pgautofailover--2.1--dummy.sql diff --git a/src/monitor/pgautofailover.control b/src/monitor/pgautofailover.control index 307709842..4bf0840f7 100644 --- a/src/monitor/pgautofailover.control +++ b/src/monitor/pgautofailover.control @@ -1,5 +1,5 @@ comment = 'pg_auto_failover' -default_version = '2.0' +default_version = '2.1' module_pathname = '$libdir/pgautofailover' relocatable = false requires = 'btree_gist'