Get methods fail when stored value is null or empty


#1

Tried searching the forums for a similar issue/topic and browsed the Github commits but was unable to find anything related. Apologies if this is a duplicate.

The following IBucket methods fail if the stored value was inserted/replaced/upserted (insertion method does not seem to change outcome) as null or empty when using v2.0.3.1 of the .NET SDK:

IDocumentResult<T> GetDocument<T>(string id);

Task<IDocumentResult<T>> GetDocumentAsync<T>(string id);

IOperationResult<T> Get<T>(string key);

Task<IOperationResult<T>> GetAsync<T>(string key);

I haven’t tested any of the ranged get methods (e.g. Get(keys)) or any of the get and touch methods (e.g. GetAndTouch(key, expiration)), but I would imagine they would be affected just the same seeing as the issue stems from reading/consumption of the buffer.

Issue is presented in either Couchbase or Memcached buckets but here is my client configuration:

<couchbaseClients>
  <couchbase useSsl="false">
    <buckets>
      <add name="default" password="" useSsl="false" />
    </buckets>
    <servers>
      <add uri="http://localhost:8091/pools" />
    </servers>
  </couchbase>
</couchbaseClients>

and is present in the latest master branch revision on GitHub (https://github.com/couchbase/couchbase-net-client) so I’ve added the following tests to demonstrate the issue. The type doesn’t seem to change the outcome but I’ve demonstrated using object (null) and string (null & empty/"") types.

namespace Couchbase.Tests.Core.Buckets
{
    #region Usings

    using System;
    using Couchbase.Core;
    using NUnit.Framework;

    #endregion

    [TestFixture]
    public class AgnosticBucketTypeTests
    {
        private ICluster _cluster;

        [TestFixtureSetUp]
        public void TestFixtureSetUp()
        {
            _cluster = new Cluster("couchbaseClients/couchbase");
        }

        [TestFixtureTearDown]
        public void TestFixtureTearDown()
        {
            _cluster.Dispose();
        }

        #region IDocumentResult<T> GetDocument<T>(string id)

        [Test]
        public void Test_GetDocument_When_Document_Content_Is_Empty_String()
        {
            const string id = "AgnosticBucketTypeTests.Test_GetDocument_When_Document_Content_Is_Empty_String";

            using (var bucket = _cluster.OpenBucket())
            {
                bucket.Upsert(new Document<string>
                              {
                                  Id = id,
                                  Content = String.Empty
                              });

                var result = bucket.GetDocument<string>(id);

                Assert.IsTrue(result.Success);
            }
        }

        [Test]
        public void Test_GetDocument_When_Document_Content_Is_Null_Object()
        {
            const string id = "AgnosticBucketTypeTests.Test_GetDocument_When_Document_Content_Is_Null_Object";

            using (var bucket = _cluster.OpenBucket())
            {
                bucket.Upsert(new Document<object>
                              {
                                  Id = id,
                                  Content = null
                              });

                var result = bucket.GetDocument<object>(id);

                Assert.IsTrue(result.Success);
            }
        }

        [Test]
        public void Test_GetDocument_When_Document_Content_Is_Null_String()
        {
            const string id = "AgnosticBucketTypeTests.Test_GetDocument_When_Document_Content_Is_Null_String";

            using (var bucket = _cluster.OpenBucket())
            {
                bucket.Upsert(new Document<string>
                              {
                                  Id = id,
                                  Content = null
                              });

                var result = bucket.GetDocument<string>(id);

                Assert.IsTrue(result.Success);
            }
        }

        [Test]
        public void Test_GetDocument_When_Value_Is_Empty_String()
        {
            const string key = "AgnosticBucketTypeTests.Test_GetDocument_When_Value_Is_Empty_String";

            const string value = "";

            using (var bucket = _cluster.OpenBucket())
            {
                bucket.Upsert(key, value);

                var result = bucket.GetDocument<string>(key);

                Assert.IsTrue(result.Success);
            }
        }

        [Test]
        public void Test_GetDocument_When_Value_Is_Null_Object()
        {
            const string key = "AgnosticBucketTypeTests.Test_GetDocument_When_Value_Is_Null_Object";

            const object value = null;

            using (var bucket = _cluster.OpenBucket())
            {
                bucket.Upsert(key, value);

                var result = bucket.GetDocument<object>(key);

                Assert.IsTrue(result.Success);
            }
        }

        [Test]
        public void Test_GetDocument_When_Value_Is_Null_String()
        {
            const string key = "AgnosticBucketTypeTests.Test_GetDocument_When_Value_Is_Null_String";

            const string value = null;

            using (var bucket = _cluster.OpenBucket())
            {
                bucket.Upsert(key, value);

                var result = bucket.GetDocument<string>(key);

                Assert.IsTrue(result.Success);
            }
        }

        #endregion

        #region Task<IDocumentResult<T>> GetDocumentAsync<T>(string id)

        [Test]
        public void Test_GetDocumentAsync_When_Document_Content_Is_Empty_String()
        {
            const string id = "AgnosticBucketTypeTests.Test_GetDocumentAsync_When_Document_Content_Is_Empty_String";

            using (var bucket = _cluster.OpenBucket())
            {
                bucket.Upsert(new Document<string>
                              {
                                  Id = id,
                                  Content = String.Empty
                              });

                var result = bucket.GetDocumentAsync<string>(id).Result;

                Assert.IsTrue(result.Success);
            }
        }

        [Test]
        public void Test_GetDocumentAsync_When_Document_Content_Is_Null_Object()
        {
            const string id = "AgnosticBucketTypeTests.Test_GetDocumentAsync_When_Document_Content_Is_Null_Object";

            using (var bucket = _cluster.OpenBucket())
            {
                bucket.Upsert(new Document<object>
                              {
                                  Id = id,
                                  Content = null
                              });

                var result = bucket.GetDocumentAsync<object>(id).Result;

                Assert.IsTrue(result.Success);
            }
        }

        [Test]
        public void Test_GetDocumentAsync_When_Document_Content_Is_Null_String()
        {
            const string id = "AgnosticBucketTypeTests.Test_GetDocumentAsync_When_Document_Content_Is_Null_String";

            using (var bucket = _cluster.OpenBucket())
            {
                bucket.Upsert(new Document<string>
                              {
                                  Id = id,
                                  Content = null
                              });

                var result = bucket.GetDocumentAsync<string>(id).Result;

                Assert.IsTrue(result.Success);
            }
        }

        [Test]
        public void Test_GetDocumentAsync_When_Value_Is_Empty_String()
        {
            const string key = "AgnosticBucketTypeTests.Test_GetDocumentAsync_When_Value_Is_Empty_String";

            const string value = "";

            using (var bucket = _cluster.OpenBucket())
            {
                bucket.Upsert(key, value);

                var result = bucket.GetDocumentAsync<string>(key).Result;

                Assert.IsTrue(result.Success);
            }
        }

        [Test]
        public void Test_GetDocumentAsync_When_Value_Is_Null_Object()
        {
            const string key = "AgnosticBucketTypeTests.Test_GetDocumentAsync_When_Value_Is_Null_Object";

            const object value = null;

            using (var bucket = _cluster.OpenBucket())
            {
                bucket.Upsert(key, value);

                var result = bucket.GetDocumentAsync<object>(key).Result;

                Assert.IsTrue(result.Success);
            }
        }

        [Test]
        public void Test_GetDocumentAsync_When_Value_Is_Null_String()
        {
            const string key = "AgnosticBucketTypeTests.Test_GetDocumentAsync_When_Value_Is_Null_String";

            const string value = null;

            using (var bucket = _cluster.OpenBucket())
            {
                bucket.Upsert(key, value);

                var result = bucket.GetDocumentAsync<string>(key).Result;

                Assert.IsTrue(result.Success);
            }
        }

        #endregion

        #region IOperationResult<T> Get<T>(string key)

        [Test]
        public void Test_Get_When_Document_Content_Is_Empty_String()
        {
            const string id = "AgnosticBucketTypeTests.Test_Get_When_Document_Content_Is_Empty_String";

            using (var bucket = _cluster.OpenBucket())
            {
                bucket.Upsert(new Document<string>
                              {
                                  Id = id,
                                  Content = String.Empty
                              });

                var result = bucket.Get<string>(id);

                Assert.IsTrue(result.Success);
            }
        }

        [Test]
        public void Test_Get_When_Document_Content_Is_Null_Object()
        {
            const string id = "AgnosticBucketTypeTests.Test_Get_When_Document_Content_Is_Null_Object";

            using (var bucket = _cluster.OpenBucket())
            {
                bucket.Upsert(new Document<object>
                              {
                                  Id = id,
                                  Content = null
                              });

                var result = bucket.Get<object>(id);

                Assert.IsTrue(result.Success);
            }
        }

        [Test]
        public void Test_Get_When_Document_Content_Is_Null_String()
        {
            const string id = "AgnosticBucketTypeTests.Test_Get_When_Document_Content_Is_Null_String";

            using (var bucket = _cluster.OpenBucket())
            {
                bucket.Upsert(new Document<string>
                              {
                                  Id = id,
                                  Content = null
                              });

                var result = bucket.Get<string>(id);

                Assert.IsTrue(result.Success);
            }
        }

        [Test]
        public void Test_Get_When_Value_Is_Empty_String()
        {
            const string key = "AgnosticBucketTypeTests.Test_Get_When_Value_Is_Empty_String";

            const string value = "";

            using (var bucket = _cluster.OpenBucket())
            {
                bucket.Upsert(key, value);

                var result = bucket.Get<string>(key);

                Assert.IsTrue(result.Success);
            }
        }

        [Test]
        public void Test_Get_When_Value_Is_Null_Object()
        {
            const string key = "AgnosticBucketTypeTests.Test_Get_When_Value_Is_Null_Object";

            const object value = null;

            using (var bucket = _cluster.OpenBucket())
            {
                bucket.Upsert(key, value);

                var result = bucket.Get<object>(key);

                Assert.IsTrue(result.Success);
            }
        }

        [Test]
        public void Test_Get_When_Value_Is_Null_String()
        {
            const string key = "AgnosticBucketTypeTests.Test_Get_When_Value_Is_Null_String";

            const string value = null;

            using (var bucket = _cluster.OpenBucket())
            {
                bucket.Upsert(key, value);

                var result = bucket.Get<string>(key);

                Assert.IsTrue(result.Success);
            }
        }

        #endregion

        #region Task<IOperationResult<T>> GetAsync<T>(string key)

        [Test]
        public void Test_GetAsync_When_Document_Content_Is_Empty_String()
        {
            const string id = "AgnosticBucketTypeTests.Test_GetAsync_When_Document_Content_Is_Empty_String";

            using (var bucket = _cluster.OpenBucket())
            {
                bucket.Upsert(new Document<string>
                              {
                                  Id = id,
                                  Content = String.Empty
                              });

                var result = bucket.GetAsync<string>(id).Result;

                Assert.IsTrue(result.Success);
            }
        }

        [Test]
        public void Test_GetAsync_When_Document_Content_Is_Null_Object()
        {
            const string id = "AgnosticBucketTypeTests.Test_GetAsync_When_Document_Content_Is_Null_Object";

            using (var bucket = _cluster.OpenBucket())
            {
                bucket.Upsert(new Document<object>
                              {
                                  Id = id,
                                  Content = null
                              });

                var result = bucket.GetAsync<object>(id).Result;

                Assert.IsTrue(result.Success);
            }
        }

        [Test]
        public void Test_GetAsync_When_Document_Content_Is_Null_String()
        {
            const string id = "AgnosticBucketTypeTests.Test_GetAsync_When_Document_Content_Is_Null_String";

            using (var bucket = _cluster.OpenBucket())
            {
                bucket.Upsert(new Document<string>
                              {
                                  Id = id,
                                  Content = null
                              });

                var result = bucket.GetAsync<string>(id).Result;

                Assert.IsTrue(result.Success);
            }
        }

        [Test]
        public void Test_GetAsync_When_Value_Is_Empty_String()
        {
            const string key = "AgnosticBucketTypeTests.Test_GetAsync_When_Value_Is_Empty_String";

            const string value = "";

            using (var bucket = _cluster.OpenBucket())
            {
                bucket.Upsert(key, value);

                var result = bucket.GetAsync<string>(key).Result;

                Assert.IsTrue(result.Success);
            }
        }

        [Test]
        public void Test_GetAsync_When_Value_Is_Null_Object()
        {
            const string key = "AgnosticBucketTypeTests.Test_GetAsync_When_Value_Is_Null_Object";

            const object value = null;

            using (var bucket = _cluster.OpenBucket())
            {
                bucket.Upsert(key, value);

                var result = bucket.GetAsync<object>(key).Result;

                Assert.IsTrue(result.Success);
            }
        }

        [Test]
        public void Test_GetAsync_When_Value_Is_Null_String()
        {
            const string key = "AgnosticBucketTypeTests.Test_GetAsync_When_Value_Is_Null_String";

            const string value = null;

            using (var bucket = _cluster.OpenBucket())
            {
                bucket.Upsert(key, value);

                var result = bucket.GetAsync<string>(key).Result;

                Assert.IsTrue(result.Success);
            }
        }

        #endregion
    }
}

#region [ License information          ]

/* ************************************************************
 *
 *    @author Couchbase <info@couchbase.com>
 *    @copyright 2014 Couchbase, Inc.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 *
 * ************************************************************/

#endregion

Will update topic (post reply) if more details are presented.

Thanks,

Eric


#2

@ericberens -

Hi Eric, thanks for the detailed post; it sounds like a bug. Can you create a Jira ticket? https://issues.couchbase.com/browse/NCBC

If you create the Jira ticket, you’ll get updates on the progress.

Thanks!

-Jeff


#3

@jmorris -

Done!

https://issues.couchbase.com/browse/NCBC-862