// Copyright 2020 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package json import ( "bytes" "compress/gzip" "io/ioutil" "os" "path/filepath" "sort" "strings" "sync" "testing" "time" ) type jsonTestdataEntry struct { name string data []byte new func() any // nil if there is no concrete type for this } var ( jsonTestdataOnce sync.Once jsonTestdataLazy []jsonTestdataEntry ) func jsonTestdata() []jsonTestdataEntry { jsonTestdataOnce.Do(func() { fis, err := ioutil.ReadDir("testdata") if err != nil { panic(err) } sort.Slice(fis, func(i, j int) bool { return fis[i].Name() < fis[j].Name() }) for _, fi := range fis { if !strings.HasSuffix(fi.Name(), ".json.gz") { break } // Skip large files for a short test run. if testing.Short() { fi, err := os.Stat(filepath.Join("testdata", fi.Name())) if err == nil && fi.Size() > 1e3 { continue } } // Convert snake_case file name to CamelCase. words := strings.Split(strings.TrimSuffix(fi.Name(), ".json.gz"), "_") for i := range words { words[i] = strings.Title(words[i]) } name := strings.Join(words, "") // Read and decompress the test data. b, err := ioutil.ReadFile(filepath.Join("testdata", fi.Name())) if err != nil { panic(err) } zr, err := gzip.NewReader(bytes.NewReader(b)) if err != nil { panic(err) } data, err := ioutil.ReadAll(zr) if err != nil { panic(err) } // Check whether there is a concrete type for this data. var newFn func() any switch name { case "CanadaGeometry": newFn = func() any { return new(canadaRoot) } case "CitmCatalog": newFn = func() any { return new(citmRoot) } case "GolangSource": newFn = func() any { return new(golangRoot) } case "StringEscaped": newFn = func() any { return new(stringRoot) } case "StringUnicode": newFn = func() any { return new(stringRoot) } case "SyntheaFhir": newFn = func() any { return new(syntheaRoot) } case "TwitterStatus": newFn = func() any { return new(twitterRoot) } } jsonTestdataLazy = append(jsonTestdataLazy, jsonTestdataEntry{name, data, newFn}) } }) return jsonTestdataLazy } type ( canadaRoot struct { Type string `json:"type"` Features []struct { Type string `json:"type"` Properties struct { Name string `json:"name"` } `json:"properties"` Geometry struct { Type string `json:"type"` Coordinates [][][2]float64 `json:"coordinates"` } `json:"geometry"` } `json:"features"` } ) type ( citmRoot struct { AreaNames map[int64]string `json:"areaNames"` AudienceSubCategoryNames map[int64]string `json:"audienceSubCategoryNames"` BlockNames map[int64]string `json:"blockNames"` Events map[int64]struct { Description string `json:"description"` ID int `json:"id"` Logo string `json:"logo"` Name string `json:"name"` SubTopicIds []int `json:"subTopicIds"` SubjectCode any `json:"subjectCode"` Subtitle any `json:"subtitle"` TopicIds []int `json:"topicIds"` } `json:"events"` Performances []struct { EventID int `json:"eventId"` ID int `json:"id"` Logo any `json:"logo"` Name any `json:"name"` Prices []struct { Amount int `json:"amount"` AudienceSubCategoryID int64 `json:"audienceSubCategoryId"` SeatCategoryID int64 `json:"seatCategoryId"` } `json:"prices"` SeatCategories []struct { Areas []struct { AreaID int `json:"areaId"` BlockIds []any `json:"blockIds"` } `json:"areas"` SeatCategoryID int `json:"seatCategoryId"` } `json:"seatCategories"` SeatMapImage any `json:"seatMapImage"` Start int64 `json:"start"` VenueCode string `json:"venueCode"` } `json:"performances"` SeatCategoryNames map[uint64]string `json:"seatCategoryNames"` SubTopicNames map[uint64]string `json:"subTopicNames"` SubjectNames map[uint64]string `json:"subjectNames"` TopicNames map[uint64]string `json:"topicNames"` TopicSubTopics map[uint64][]uint64 `json:"topicSubTopics"` VenueNames map[string]string `json:"venueNames"` } ) type ( golangRoot struct { Tree *golangNode `json:"tree"` Username string `json:"username"` } golangNode struct { Name string `json:"name"` Kids []golangNode `json:"kids"` CLWeight float64 `json:"cl_weight"` Touches int `json:"touches"` MinT uint64 `json:"min_t"` MaxT uint64 `json:"max_t"` MeanT uint64 `json:"mean_t"` } ) type ( stringRoot struct { Arabic string `json:"Arabic"` ArabicPresentationFormsA string `json:"Arabic Presentation Forms-A"` ArabicPresentationFormsB string `json:"Arabic Presentation Forms-B"` Armenian string `json:"Armenian"` Arrows string `json:"Arrows"` Bengali string `json:"Bengali"` Bopomofo string `json:"Bopomofo"` BoxDrawing string `json:"Box Drawing"` CJKCompatibility string `json:"CJK Compatibility"` CJKCompatibilityForms string `json:"CJK Compatibility Forms"` CJKCompatibilityIdeographs string `json:"CJK Compatibility Ideographs"` CJKSymbolsAndPunctuation string `json:"CJK Symbols and Punctuation"` CJKUnifiedIdeographs string `json:"CJK Unified Ideographs"` CJKUnifiedIdeographsExtensionA string `json:"CJK Unified Ideographs Extension A"` CJKUnifiedIdeographsExtensionB string `json:"CJK Unified Ideographs Extension B"` Cherokee string `json:"Cherokee"` CurrencySymbols string `json:"Currency Symbols"` Cyrillic string `json:"Cyrillic"` CyrillicSupplementary string `json:"Cyrillic Supplementary"` Devanagari string `json:"Devanagari"` EnclosedAlphanumerics string `json:"Enclosed Alphanumerics"` EnclosedCJKLettersAndMonths string `json:"Enclosed CJK Letters and Months"` Ethiopic string `json:"Ethiopic"` GeometricShapes string `json:"Geometric Shapes"` Georgian string `json:"Georgian"` GreekAndCoptic string `json:"Greek and Coptic"` Gujarati string `json:"Gujarati"` Gurmukhi string `json:"Gurmukhi"` HangulCompatibilityJamo string `json:"Hangul Compatibility Jamo"` HangulJamo string `json:"Hangul Jamo"` HangulSyllables string `json:"Hangul Syllables"` Hebrew string `json:"Hebrew"` Hiragana string `json:"Hiragana"` IPAExtentions string `json:"IPA Extentions"` KangxiRadicals string `json:"Kangxi Radicals"` Katakana string `json:"Katakana"` Khmer string `json:"Khmer"` KhmerSymbols string `json:"Khmer Symbols"` Latin string `json:"Latin"` LatinExtendedAdditional string `json:"Latin Extended Additional"` Latin1Supplement string `json:"Latin-1 Supplement"` LatinExtendedA string `json:"Latin-Extended A"` LatinExtendedB string `json:"Latin-Extended B"` LetterlikeSymbols string `json:"Letterlike Symbols"` Malayalam string `json:"Malayalam"` MathematicalAlphanumericSymbols string `json:"Mathematical Alphanumeric Symbols"` MathematicalOperators string `json:"Mathematical Operators"` MiscellaneousSymbols string `json:"Miscellaneous Symbols"` Mongolian string `json:"Mongolian"` NumberForms string `json:"Number Forms"` Oriya string `json:"Oriya"` PhoneticExtensions string `json:"Phonetic Extensions"` SupplementalArrowsB string `json:"Supplemental Arrows-B"` Syriac string `json:"Syriac"` Tamil string `json:"Tamil"` Thaana string `json:"Thaana"` Thai string `json:"Thai"` UnifiedCanadianAboriginalSyllabics string `json:"Unified Canadian Aboriginal Syllabics"` YiRadicals string `json:"Yi Radicals"` YiSyllables string `json:"Yi Syllables"` } ) type ( syntheaRoot struct { Entry []struct { FullURL string `json:"fullUrl"` Request *struct { Method string `json:"method"` URL string `json:"url"` } `json:"request"` Resource *struct { AbatementDateTime time.Time `json:"abatementDateTime"` AchievementStatus syntheaCode `json:"achievementStatus"` Active bool `json:"active"` Activity []struct { Detail *struct { Code syntheaCode `json:"code"` Location syntheaReference `json:"location"` Status string `json:"status"` } `json:"detail"` } `json:"activity"` Address []syntheaAddress `json:"address"` Addresses []syntheaReference `json:"addresses"` AuthoredOn time.Time `json:"authoredOn"` BillablePeriod syntheaRange `json:"billablePeriod"` BirthDate string `json:"birthDate"` CareTeam []struct { Provider syntheaReference `json:"provider"` Reference string `json:"reference"` Role syntheaCode `json:"role"` Sequence int64 `json:"sequence"` } `json:"careTeam"` Category []syntheaCode `json:"category"` Claim syntheaReference `json:"claim"` Class syntheaCoding `json:"class"` ClinicalStatus syntheaCode `json:"clinicalStatus"` Code syntheaCode `json:"code"` Communication []struct { Language syntheaCode `json:"language"` } `json:"communication"` Component []struct { Code syntheaCode `json:"code"` ValueQuantity syntheaCoding `json:"valueQuantity"` } `json:"component"` Contained []struct { Beneficiary syntheaReference `json:"beneficiary"` ID string `json:"id"` Intent string `json:"intent"` Payor []syntheaReference `json:"payor"` Performer []syntheaReference `json:"performer"` Requester syntheaReference `json:"requester"` ResourceType string `json:"resourceType"` Status string `json:"status"` Subject syntheaReference `json:"subject"` Type syntheaCode `json:"type"` } `json:"contained"` Created time.Time `json:"created"` DeceasedDateTime time.Time `json:"deceasedDateTime"` Description syntheaCode `json:"description"` Diagnosis []struct { DiagnosisReference syntheaReference `json:"diagnosisReference"` Sequence int64 `json:"sequence"` Type []syntheaCode `json:"type"` } `json:"diagnosis"` DosageInstruction []struct { AsNeededBoolean bool `json:"asNeededBoolean"` DoseAndRate []struct { DoseQuantity *struct { Value float64 `json:"value"` } `json:"doseQuantity"` Type syntheaCode `json:"type"` } `json:"doseAndRate"` Sequence int64 `json:"sequence"` Timing *struct { Repeat *struct { Frequency int64 `json:"frequency"` Period float64 `json:"period"` PeriodUnit string `json:"periodUnit"` } `json:"repeat"` } `json:"timing"` } `json:"dosageInstruction"` EffectiveDateTime time.Time `json:"effectiveDateTime"` Encounter syntheaReference `json:"encounter"` Extension []syntheaExtension `json:"extension"` Gender string `json:"gender"` Goal []syntheaReference `json:"goal"` ID string `json:"id"` Identifier []struct { System string `json:"system"` Type syntheaCode `json:"type"` Use string `json:"use"` Value string `json:"value"` } `json:"identifier"` Insurance []struct { Coverage syntheaReference `json:"coverage"` Focal bool `json:"focal"` Sequence int64 `json:"sequence"` } `json:"insurance"` Insurer syntheaReference `json:"insurer"` Intent string `json:"intent"` Issued time.Time `json:"issued"` Item []struct { Adjudication []struct { Amount syntheaCurrency `json:"amount"` Category syntheaCode `json:"category"` } `json:"adjudication"` Category syntheaCode `json:"category"` DiagnosisSequence []int64 `json:"diagnosisSequence"` Encounter []syntheaReference `json:"encounter"` InformationSequence []int64 `json:"informationSequence"` LocationCodeableConcept syntheaCode `json:"locationCodeableConcept"` Net syntheaCurrency `json:"net"` ProcedureSequence []int64 `json:"procedureSequence"` ProductOrService syntheaCode `json:"productOrService"` Sequence int64 `json:"sequence"` ServicedPeriod syntheaRange `json:"servicedPeriod"` } `json:"item"` LifecycleStatus string `json:"lifecycleStatus"` ManagingOrganization []syntheaReference `json:"managingOrganization"` MaritalStatus syntheaCode `json:"maritalStatus"` MedicationCodeableConcept syntheaCode `json:"medicationCodeableConcept"` MultipleBirthBoolean bool `json:"multipleBirthBoolean"` Name RawValue `json:"name"` NumberOfInstances int64 `json:"numberOfInstances"` NumberOfSeries int64 `json:"numberOfSeries"` OccurrenceDateTime time.Time `json:"occurrenceDateTime"` OnsetDateTime time.Time `json:"onsetDateTime"` Outcome string `json:"outcome"` Participant []struct { Individual syntheaReference `json:"individual"` Member syntheaReference `json:"member"` Role []syntheaCode `json:"role"` } `json:"participant"` Patient syntheaReference `json:"patient"` Payment *struct { Amount syntheaCurrency `json:"amount"` } `json:"payment"` PerformedPeriod syntheaRange `json:"performedPeriod"` Period syntheaRange `json:"period"` Prescription syntheaReference `json:"prescription"` PrimarySource bool `json:"primarySource"` Priority syntheaCode `json:"priority"` Procedure []struct { ProcedureReference syntheaReference `json:"procedureReference"` Sequence int64 `json:"sequence"` } `json:"procedure"` Provider syntheaReference `json:"provider"` ReasonCode []syntheaCode `json:"reasonCode"` ReasonReference []syntheaReference `json:"reasonReference"` RecordedDate time.Time `json:"recordedDate"` Referral syntheaReference `json:"referral"` Requester syntheaReference `json:"requester"` ResourceType string `json:"resourceType"` Result []syntheaReference `json:"result"` Series []struct { BodySite syntheaCoding `json:"bodySite"` Instance []struct { Number int64 `json:"number"` SopClass syntheaCoding `json:"sopClass"` Title string `json:"title"` UID string `json:"uid"` } `json:"instance"` Modality syntheaCoding `json:"modality"` Number int64 `json:"number"` NumberOfInstances int64 `json:"numberOfInstances"` Started string `json:"started"` UID string `json:"uid"` } `json:"series"` ServiceProvider syntheaReference `json:"serviceProvider"` Started time.Time `json:"started"` Status string `json:"status"` Subject syntheaReference `json:"subject"` SupportingInfo []struct { Category syntheaCode `json:"category"` Sequence int64 `json:"sequence"` ValueReference syntheaReference `json:"valueReference"` } `json:"supportingInfo"` Telecom []map[string]string `json:"telecom"` Text map[string]string `json:"text"` Total RawValue `json:"total"` Type RawValue `json:"type"` Use string `json:"use"` VaccineCode syntheaCode `json:"vaccineCode"` ValueCodeableConcept syntheaCode `json:"valueCodeableConcept"` ValueQuantity syntheaCoding `json:"valueQuantity"` VerificationStatus syntheaCode `json:"verificationStatus"` } `json:"resource"` } `json:"entry"` ResourceType string `json:"resourceType"` Type string `json:"type"` } syntheaCode struct { Coding []syntheaCoding `json:"coding"` Text string `json:"text"` } syntheaCoding struct { Code string `json:"code"` Display string `json:"display"` System string `json:"system"` Unit string `json:"unit"` Value float64 `json:"value"` } syntheaReference struct { Display string `json:"display"` Reference string `json:"reference"` } syntheaAddress struct { City string `json:"city"` Country string `json:"country"` Extension []syntheaExtension `json:"extension"` Line []string `json:"line"` PostalCode string `json:"postalCode"` State string `json:"state"` } syntheaExtension struct { URL string `json:"url"` ValueAddress syntheaAddress `json:"valueAddress"` ValueCode string `json:"valueCode"` ValueDecimal float64 `json:"valueDecimal"` ValueString string `json:"valueString"` Extension []syntheaExtension `json:"extension"` } syntheaRange struct { End time.Time `json:"end"` Start time.Time `json:"start"` } syntheaCurrency struct { Currency string `json:"currency"` Value float64 `json:"value"` } ) type ( twitterRoot struct { Statuses []twitterStatus `json:"statuses"` SearchMetadata struct { CompletedIn float64 `json:"completed_in"` MaxID int64 `json:"max_id"` MaxIDStr int64 `json:"max_id_str,string"` NextResults string `json:"next_results"` Query string `json:"query"` RefreshURL string `json:"refresh_url"` Count int `json:"count"` SinceID int `json:"since_id"` SinceIDStr int `json:"since_id_str,string"` } `json:"search_metadata"` } twitterStatus struct { Metadata struct { ResultType string `json:"result_type"` IsoLanguageCode string `json:"iso_language_code"` } `json:"metadata"` CreatedAt string `json:"created_at"` ID int64 `json:"id"` IDStr int64 `json:"id_str,string"` Text string `json:"text"` Source string `json:"source"` Truncated bool `json:"truncated"` InReplyToStatusID int64 `json:"in_reply_to_status_id"` InReplyToStatusIDStr int64 `json:"in_reply_to_status_id_str,string"` InReplyToUserID int64 `json:"in_reply_to_user_id"` InReplyToUserIDStr int64 `json:"in_reply_to_user_id_str,string"` InReplyToScreenName string `json:"in_reply_to_screen_name"` User twitterUser `json:"user,omitempty"` Geo any `json:"geo"` Coordinates any `json:"coordinates"` Place any `json:"place"` Contributors any `json:"contributors"` RetweeetedStatus *twitterStatus `json:"retweeted_status"` RetweetCount int `json:"retweet_count"` FavoriteCount int `json:"favorite_count"` Entities twitterEntities `json:"entities,omitempty"` Favorited bool `json:"favorited"` Retweeted bool `json:"retweeted"` PossiblySensitive bool `json:"possibly_sensitive"` Lang string `json:"lang"` } twitterUser struct { ID int64 `json:"id"` IDStr string `json:"id_str"` Name string `json:"name"` ScreenName string `json:"screen_name"` Location string `json:"location"` Description string `json:"description"` URL any `json:"url"` Entities twitterEntities `json:"entities"` Protected bool `json:"protected"` FollowersCount int `json:"followers_count"` FriendsCount int `json:"friends_count"` ListedCount int `json:"listed_count"` CreatedAt string `json:"created_at"` FavouritesCount int `json:"favourites_count"` UtcOffset int `json:"utc_offset"` TimeZone string `json:"time_zone"` GeoEnabled bool `json:"geo_enabled"` Verified bool `json:"verified"` StatusesCount int `json:"statuses_count"` Lang string `json:"lang"` ContributorsEnabled bool `json:"contributors_enabled"` IsTranslator bool `json:"is_translator"` IsTranslationEnabled bool `json:"is_translation_enabled"` ProfileBackgroundColor string `json:"profile_background_color"` ProfileBackgroundImageURL string `json:"profile_background_image_url"` ProfileBackgroundImageURLHTTPS string `json:"profile_background_image_url_https"` ProfileBackgroundTile bool `json:"profile_background_tile"` ProfileImageURL string `json:"profile_image_url"` ProfileImageURLHTTPS string `json:"profile_image_url_https"` ProfileBannerURL string `json:"profile_banner_url"` ProfileLinkColor string `json:"profile_link_color"` ProfileSidebarBorderColor string `json:"profile_sidebar_border_color"` ProfileSidebarFillColor string `json:"profile_sidebar_fill_color"` ProfileTextColor string `json:"profile_text_color"` ProfileUseBackgroundImage bool `json:"profile_use_background_image"` DefaultProfile bool `json:"default_profile"` DefaultProfileImage bool `json:"default_profile_image"` Following bool `json:"following"` FollowRequestSent bool `json:"follow_request_sent"` Notifications bool `json:"notifications"` } twitterEntities struct { Hashtags []any `json:"hashtags"` Symbols []any `json:"symbols"` URL *twitterURL `json:"url"` URLs []twitterURL `json:"urls"` UserMentions []struct { ScreenName string `json:"screen_name"` Name string `json:"name"` ID int64 `json:"id"` IDStr int64 `json:"id_str,string"` Indices []int `json:"indices"` } `json:"user_mentions"` Description struct { URLs []twitterURL `json:"urls"` } `json:"description"` Media []struct { ID int64 `json:"id"` IDStr string `json:"id_str"` Indices []int `json:"indices"` MediaURL string `json:"media_url"` MediaURLHTTPS string `json:"media_url_https"` URL string `json:"url"` DisplayURL string `json:"display_url"` ExpandedURL string `json:"expanded_url"` Type string `json:"type"` Sizes map[string]struct { W int `json:"w"` H int `json:"h"` Resize string `json:"resize"` } `json:"sizes"` SourceStatusID int64 `json:"source_status_id"` SourceStatusIDStr int64 `json:"source_status_id_str,string"` } `json:"media"` } twitterURL struct { URL string `json:"url"` URLs []twitterURL `json:"urls"` ExpandedURL string `json:"expanded_url"` DisplayURL string `json:"display_url"` Indices []int `json:"indices"` } )