@@ -6,7 +6,12 @@ package azcosmos
66import (
77 "context"
88 "encoding/json"
9+ "errors"
10+ "net/http"
11+ "strings"
912 "testing"
13+
14+ "github.com/Azure/azure-sdk-for-go/sdk/azcore"
1015)
1116
1217func TestItemCRUD (t * testing.T ) {
@@ -136,3 +141,79 @@ func TestItemCRUD(t *testing.T) {
136141 t .Fatalf ("Expected empty response, got %v" , itemResponse .Value )
137142 }
138143}
144+
145+ func TestItemIdEncoding (t * testing.T ) {
146+ emulatorTests := newEmulatorTests (t )
147+ client := emulatorTests .getClient (t )
148+
149+ database := emulatorTests .createDatabase (t , context .TODO (), client , "itemCRUD" )
150+ defer emulatorTests .deleteDatabase (t , context .TODO (), database )
151+ properties := ContainerProperties {
152+ ID : "aContainer" ,
153+ PartitionKeyDefinition : PartitionKeyDefinition {
154+ Paths : []string {"/pk" },
155+ },
156+ }
157+
158+ _ , err := database .CreateContainer (context .TODO (), properties , nil )
159+ if err != nil {
160+ t .Fatalf ("Failed to create container: %v" , err )
161+ }
162+
163+ container , _ := database .NewContainer ("aContainer" )
164+
165+ verifyEncodingScenario (t , container , "PlainVanillaId" , "Test" , http .StatusCreated , http .StatusOK , http .StatusOK , http .StatusNoContent )
166+ verifyEncodingScenario (t , container , "IdWithWhitespaces" , "This is a test" , http .StatusCreated , http .StatusOK , http .StatusOK , http .StatusNoContent )
167+ verifyEncodingScenario (t , container , "IdStartingWithWhitespaces" , " Test" , http .StatusCreated , http .StatusOK , http .StatusOK , http .StatusNoContent )
168+ verifyEncodingScenario (t , container , "IdEndingWithWhitespace" , "Test " , http .StatusCreated , http .StatusUnauthorized , http .StatusUnauthorized , http .StatusUnauthorized )
169+ verifyEncodingScenario (t , container , "IdEndingWithWhitespaces" , "Test " , http .StatusCreated , http .StatusUnauthorized , http .StatusUnauthorized , http .StatusUnauthorized )
170+ verifyEncodingScenario (t , container , "IdWithAllowedSpecialCharacters" , "WithAllowedSpecial,=.:~+-@()^${}[]!_Chars" , http .StatusCreated , http .StatusOK , http .StatusOK , http .StatusNoContent )
171+ verifyEncodingScenario (t , container , "IdWithBase64EncodedIdCharacters" , strings .Replace ("BQE1D3PdG4N4bzU9TKaCIM3qc0TVcZ2/Y3jnsRfwdHC1ombkX3F1dot/SG0/UTq9AbgdX3kOWoP6qL6lJqWeKgV3zwWWPZO/t5X0ehJzv9LGkWld07LID2rhWhGT6huBM6Q=" , "/" , "-" , - 1 ), http .StatusCreated , http .StatusOK , http .StatusOK , http .StatusNoContent )
172+ verifyEncodingScenario (t , container , "IdEndingWithPercentEncodedWhitespace" , "IdEndingWithPercentEncodedWhitespace%20" , http .StatusCreated , http .StatusUnauthorized , http .StatusUnauthorized , http .StatusUnauthorized )
173+ verifyEncodingScenario (t , container , "IdWithPercentEncodedSpecialChar" , "WithPercentEncodedSpecialChar%E9%B1%80" , http .StatusCreated , http .StatusUnauthorized , http .StatusUnauthorized , http .StatusUnauthorized )
174+ verifyEncodingScenario (t , container , "IdWithDisallowedCharQuestionMark" , "Disallowed?Chars" , http .StatusCreated , http .StatusOK , http .StatusOK , http .StatusNoContent )
175+ verifyEncodingScenario (t , container , "IdWithDisallowedCharForwardSlash" , "Disallowed/Chars" , http .StatusCreated , http .StatusBadRequest , http .StatusBadRequest , http .StatusBadRequest )
176+ verifyEncodingScenario (t , container , "IdWithDisallowedCharBackSlash" , "Disallowed\\ Chars" , http .StatusCreated , http .StatusBadRequest , http .StatusBadRequest , http .StatusBadRequest )
177+ verifyEncodingScenario (t , container , "IdWithDisallowedCharPoundSign" , "Disallowed#Chars" , http .StatusCreated , http .StatusUnauthorized , http .StatusUnauthorized , http .StatusUnauthorized )
178+ verifyEncodingScenario (t , container , "IdWithCarriageReturn" , "With\r CarriageReturn" , http .StatusCreated , http .StatusBadRequest , http .StatusBadRequest , http .StatusBadRequest )
179+ verifyEncodingScenario (t , container , "IdWithTab" , "With\t Tab" , http .StatusCreated , http .StatusBadRequest , http .StatusBadRequest , http .StatusBadRequest )
180+ verifyEncodingScenario (t , container , "IdWithLineFeed" , "With\n LineFeed" , http .StatusCreated , http .StatusBadRequest , http .StatusBadRequest , http .StatusBadRequest )
181+ verifyEncodingScenario (t , container , "IdWithUnicodeCharacters" , "WithUnicode鱀" , http .StatusCreated , http .StatusOK , http .StatusOK , http .StatusNoContent )
182+ }
183+
184+ func verifyEncodingScenario (t * testing.T , container * ContainerClient , name string , id string , expectedCreate int , expectedRead int , expectedReplace int , expectedDelete int ) {
185+ item := map [string ]interface {}{
186+ "id" : id ,
187+ "pk" : id ,
188+ }
189+
190+ pk := NewPartitionKeyString (id )
191+
192+ marshalled , err := json .Marshal (item )
193+ if err != nil {
194+ t .Fatal (err )
195+ }
196+
197+ itemResponse , err := container .CreateItem (context .TODO (), pk , marshalled , nil )
198+ verifyEncodingScenarioResponse (t , name + "Create" , itemResponse , err , expectedCreate )
199+ itemResponse , err = container .ReadItem (context .TODO (), pk , id , nil )
200+ verifyEncodingScenarioResponse (t , name + "Read" , itemResponse , err , expectedRead )
201+ itemResponse , err = container .ReplaceItem (context .TODO (), pk , id , marshalled , nil )
202+ verifyEncodingScenarioResponse (t , name + "Replace" , itemResponse , err , expectedReplace )
203+ itemResponse , err = container .DeleteItem (context .TODO (), pk , id , nil )
204+ verifyEncodingScenarioResponse (t , name + "Delete" , itemResponse , err , expectedDelete )
205+ }
206+
207+ func verifyEncodingScenarioResponse (t * testing.T , name string , itemResponse ItemResponse , err error , expectedStatus int ) {
208+ if err != nil {
209+ var responseErr * azcore.ResponseError
210+ errors .As (err , & responseErr )
211+ if responseErr .StatusCode != expectedStatus {
212+ t .Fatalf ("[%s] Expected status code %d, got %d, %s" , name , expectedStatus , responseErr .StatusCode , err )
213+ }
214+ } else {
215+ if itemResponse .RawResponse .StatusCode != expectedStatus {
216+ t .Fatalf ("[%s] Expected status code %d, got %d" , name , expectedStatus , itemResponse .RawResponse .StatusCode )
217+ }
218+ }
219+ }
0 commit comments