You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

802 lines
26 KiB
C#

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using StackExchange.Redis;
using Xunit;
using Xunit.Extensions;
using Xunit.Serialization;
using Xunit.Abstractions;
using Xunit.Sdk;
using RedisStudyModel;
using RedisStuy;
namespace RedisStudyTest
{
/// <summary>
/// Redis Hash 类型测试
/// </summary>
[Trait("RedisHash", "All")]
public class RedisHashStudyTest : IDisposable
{
#region 初始化
private readonly ITestOutputHelper testOutput;
private IDatabase redisDatabase = null;
private RedisHashStudy redisHashStudy = null;
private List<Student> defaultStudentList;
private Student defaultStudent = null;
private string preStudentHashKey = "RedisStudy:Student:";
private string defaultStudentHashKey = "";
private int defaultExpireSeconds = 20;
/// <summary>
/// 构造
/// </summary>
public RedisHashStudyTest(ITestOutputHelper output)
{
this.testOutput = output;
redisDatabase = RedisHelper.GetRedisDatabase();
redisHashStudy = new RedisHashStudy();
defaultStudent = new Student()
{
Id = 1,
Name = "王高峰",
Age = 18
};
defaultStudentHashKey = preStudentHashKey + defaultStudent.Id;
defaultStudentList = new List<Student>()
{
new Student()
{
Id = 1001,
Name = "王高峰",
Age = 11
},
new Student()
{
Id = 1002,
Name = "王高峰2",
Age = 22
},
new Student()
{
Id = 1003,
Name = "王高峰3",
Age = 33
},
new Student()
{
Id = 1004,
Name = "王高峰4",
Age = 44
},
new Student()
{
Id = 1005,
Name = "王高峰5",
Age = 55
},
};
//删理默认学生
DeleteExitsStudents();
}
#endregion
#region HashSet
/// <summary>
/// xUnit输出信息 测试
/// </summary>
[Trait("RedisHash", "HashSet")]
[Fact(DisplayName = "HashSet 输出信息测试")]
public void HashSetOutputTest()
{
Assert.True(true);
testOutput.WriteLine("我是xUnit测试输出信息");
}
/// <summary>
/// 参数异常 测试
/// </summary>
[Trait("RedisHash", "HashSet")]
[Fact(DisplayName = "HashSet 异常测试")]
public void HashSetExceptionTest()
{
string redisKey = preStudentHashKey + defaultStudent.Id;
//参数异常测试
Assert.Throws<ArgumentNullException>(() => redisHashStudy.HashSet(string.Empty, null));
Assert.Throws<ArgumentNullException>(() => redisHashStudy.HashSet("", null));
Assert.Throws<ArgumentNullException>(() => redisHashStudy.HashSet(preStudentHashKey + "-1", null));
Assert.Throws<ArgumentNullException>(() => redisHashStudy.HashSet(preStudentHashKey + "-1", new HashEntry[] { }));
}
/// <summary>
/// 参数 When 测试
/// </summary>
[Trait("RedisHash", "HashSet")]
[Fact(DisplayName = "HashSet When参数测试")]
public void HashSetWhenTest()
{
string redisKey = preStudentHashKey + defaultStudent.Id;
//当前上下文不能使用: When.Exists
var id_When_NotExists_No = redisHashStudy.HashSet(redisKey, "Id", defaultStudent.Id + 1, When.NotExists);
Assert.True(id_When_NotExists_No);
var id_When_NotExists_Yes = redisHashStudy.HashSet(redisKey, "Id", defaultStudent.Id + 1, When.NotExists);
Assert.False(id_When_NotExists_Yes);
var id_When_Always_Exists = redisHashStudy.HashSet(redisKey, "Id", defaultStudent.Id + 1, When.Always);
Assert.False(id_When_Always_Exists);
var id_When_Always_NotExists = redisHashStudy.HashSet(redisKey, "Id4", defaultStudent.Id + 1, When.Always);
Assert.True(id_When_Always_NotExists);
}
/// <summary>
/// 添加一个默认学生 测试
/// </summary>
[Trait("RedisHash", "HashSet")]
[Fact]
public void HashSetAddStudentTest()
{
var studentEntries = new HashEntry[]
{
new HashEntry("Id",defaultStudent.Id),
new HashEntry("Name",defaultStudent.Name),
new HashEntry("Age",defaultStudent.Age),
};
//插入Sudent
var addHash = redisHashStudy.HashSet(defaultStudentHashKey, studentEntries, CommandFlags.None);
Assert.True(addHash);
//设置过期
redisDatabase.KeyExpire(defaultStudentHashKey, TimeSpan.FromSeconds(defaultExpireSeconds));
}
/// <summary>
/// 添加一组初始化设置的学生 测试
/// </summary>
[Trait("RedisHash", "HashSet")]
[Fact]
public void HashSetAddGroupStudentTest()
{
foreach (var temp in defaultStudentList)
{
string redisKey = preStudentHashKey + temp.Id;
var studentEntries = new HashEntry[]
{
new HashEntry("Id", temp.Id),
new HashEntry("Name", temp.Name),
new HashEntry("Age", temp.Age),
};
//插入Sudent
var addStudent = redisHashStudy.HashSet(redisKey, studentEntries);
Assert.True(addStudent);
//设置过期
redisDatabase.KeyExpire(redisKey, TimeSpan.FromSeconds(defaultExpireSeconds));
}
//清理删除
foreach (var temp in defaultStudentList)
{
redisDatabase.KeyDelete(preStudentHashKey + temp.Id);
}
}
/// <summary>
/// 设置一个哈希字段 测试
/// </summary>
[Trait("RedisHash", "HashSet")]
[Fact]
public void HashSetHashfieldTest()
{
Assert.True(redisHashStudy.HashSet(defaultStudentHashKey, "Id", defaultStudent.Id));
Assert.False(redisHashStudy.HashSet(defaultStudentHashKey, "Id", defaultStudent.Id));
Assert.True(redisHashStudy.HashSet(defaultStudentHashKey, "Name", defaultStudent.Name));
Assert.False(redisHashStudy.HashSet(defaultStudentHashKey, "Name", defaultStudent.Name));
Assert.True(redisHashStudy.HashSet(defaultStudentHashKey, "Age", defaultStudent.Age));
Assert.False(redisHashStudy.HashSet(defaultStudentHashKey, "Age", defaultStudent.Age));
}
/// <summary>
/// 设置一组哈希字段 测试
/// </summary>
[Fact]
public void HashSetGroupHashfieldTest()
{
Assert.True(redisHashStudy.HashSet(defaultStudentHashKey, "Id", defaultStudent.Id));
Assert.False(redisHashStudy.HashSet(defaultStudentHashKey, "Id", defaultStudent.Id + 1));
var entrys = new HashEntry[]
{
new HashEntry("Name", defaultStudent.Name),
new HashEntry("Age", defaultStudent.Age),
};
var entrys2 = new HashEntry[]
{
new HashEntry("Name", defaultStudent.Name+"2"),
new HashEntry("Age", defaultStudent.Age+1),
};
Assert.True(redisHashStudy.HashSet(defaultStudentHashKey, entrys));
Assert.True(redisHashStudy.HashSet(defaultStudentHashKey, entrys2));
}
/// <summary>
/// 特例测试给key为空的哈希 设置字段
/// 结 果:添加或更新操作能成功,但是字段值插入不进去。
/// </summary>
[Trait("RedisHash", "HashSet")]
[Fact]
public void HashSetForEmptyKeyTest()
{
Assert.True(redisHashStudy.HashSet(string.Empty, "Name", "wanggaofeng"));
redisDatabase.KeyDelete(string.Empty);
}
/// <summary>
/// 特例测试:给字段名为空串的哈希 设置字段
/// 结 果:添加或更新操作正常,只是字段键名为""
/// </summary>
[Trait("RedisHash", "HashSet")]
[Fact]
public void HashSetForEmptyFieldTest()
{
Assert.True(redisHashStudy.HashSet(defaultStudentHashKey, "", defaultStudent.Id));
Assert.False(redisHashStudy.HashSet(defaultStudentHashKey, "", defaultStudent.Id + 1));
redisDatabase.KeyDelete(defaultStudentHashKey);
}
#endregion
#region HashDecrement
/// <summary>
/// 字段值不是数字时,异常
/// 原注释:字段不为数据字,则改为数字
/// 实际执行:抛出异常,不知道是原注释错误,还是其它原因
/// </summary>
[Fact]
public void HashDecrementExceptionTest()
{
Assert.True(redisHashStudy.HashSet(defaultStudentHashKey, "Name", "wanggaofeng"));
Assert.Throws<RedisServerException>(() => redisHashStudy.HashDecrement(defaultStudentHashKey, "Name", 1));
}
/// <summary>
/// 哈希表不存在
/// 则先创建哈希表再添加值为0的字段然后执行自减操作
/// </summary>
[Fact]
public void HashDecrementHashKeyTest()
{
//Key不存在先创建哈希表再添加值为0的字段然后执行自减操作
Assert.Equal(-1, redisHashStudy.HashDecrement(defaultStudentHashKey, "Id", 1));
//存在,直接自减
Assert.Equal(-1, redisHashStudy.HashGet(defaultStudentHashKey, "Id"));
}
/// <summary>
/// 自减字段不存在
/// 先添加字段值设为0然后执行自减操作
/// </summary>
[Fact]
public void HashDecrementHashFieldTest()
{
//字段不存在,则创建之
Assert.Equal(-1, redisHashStudy.HashDecrement(defaultStudentHashKey, "Age", 1));
Assert.Equal(-1, redisHashStudy.HashGet(defaultStudentHashKey, "Age"));
}
/// <summary>
/// 自减负数,则自增
/// </summary>
[Fact]
public void HashDecrementMinusTest()
{
//自减负数时,则自增
Assert.Equal(2, redisHashStudy.HashDecrement(defaultStudentHashKey, "Age", -2));
}
/// <summary>
/// 自减整数
/// </summary>
[Fact]
public void HashDecrementByIntTest()
{
//字段减少1
Assert.Equal(-1, redisHashStudy.HashDecrement(defaultStudentHashKey, "Age", 1));
//字段减少2
Assert.Equal(-3, redisHashStudy.HashDecrement(defaultStudentHashKey, "Age", 2));
}
/// <summary>
/// 自减浮点数
/// 断言应该用精度值在一个小范围内
/// </summary>
[Fact]
public void HashDecrementByDoubleTest()
{
//新字段时,可以用相等比较
var dec = redisHashStudy.HashDecrement(defaultStudentHashKey, "Age", 2.1);
var absDec = Math.Abs(-2.1 - dec);
Assert.Equal(0, absDec);
//已经存在的,浮点数,不使用相等比较,而改用两值相差一定的小范围
dec = redisHashStudy.HashDecrement(defaultStudentHashKey, "Age", 2.5);
absDec = Math.Abs(-4.6 - dec);
Assert.True(absDec < 0.01);
}
#endregion HashIncrement
#region HashIncrement
/// <summary>
/// 字段值不是数字时,异常
/// 原注释:字段不为数据字,则改为数字
/// 实际执行:抛出异常,不知道是原注释错误,还是其它原因
/// </summary>
[Fact]
public void HashIncrementExceptionTest()
{
Assert.True(redisHashStudy.HashSet(defaultStudentHashKey, "Name", "wanggaofeng"));
Assert.Throws<RedisServerException>(() => redisHashStudy.HashIncrement(defaultStudentHashKey, "Name", 1));
}
/// <summary>
/// 哈希表不存在
/// 则先创建哈希表再添加值为0的字段然后执行自增操作
/// </summary>
[Fact]
public void HashIncrementHashKeyTest()
{
//Key不存在先创建哈希表再添加值为0的字段然后执行自减操作
Assert.Equal(1, redisHashStudy.HashIncrement(defaultStudentHashKey, "Id", 1));
Assert.Equal(1, redisHashStudy.HashGet(defaultStudentHashKey, "Id"));
}
/// <summary>
/// 自增字段不存在
/// 先添加字段值设为0然后执行自增操作
/// </summary>
[Fact]
public void HashIncrementHashFieldTest()
{
//字段不存在,则创建之
Assert.Equal(1, redisHashStudy.HashIncrement(defaultStudentHashKey, "Age", 1));
Assert.Equal(1, redisHashStudy.HashGet(defaultStudentHashKey, "Age"));
}
/// <summary>
/// 自增负数,则自减
/// </summary>
[Fact]
public void HashIncrementMinusTest()
{
//自增负数时,则自减
Assert.Equal(-2, redisHashStudy.HashIncrement(defaultStudentHashKey, "Age", -2));
}
/// <summary>
/// 自增整数
/// </summary>
[Fact]
public void HashIncrementByIntTest()
{
//字段减少1
Assert.Equal(1, redisHashStudy.HashIncrement(defaultStudentHashKey, "Age", 1));
//字段减少2
Assert.Equal(3, redisHashStudy.HashIncrement(defaultStudentHashKey, "Age", 2));
}
/// <summary>
/// 自增浮点数
/// 断言应该用精度值在一个小范围内
/// </summary>
[Fact]
public void HashIncrementByDoubleTest()
{
//新字段时,可以用相等比较
var dec = redisHashStudy.HashIncrement(defaultStudentHashKey, "Age", 2.1);
var absDec = Math.Abs(2.1 - dec);
Assert.Equal(0, absDec);
//已经存在的,浮点数,不使用相等比较,而改用两值相差一定的小范围
dec = redisHashStudy.HashIncrement(defaultStudentHashKey, "Age", 2.5);
absDec = Math.Abs(4.6 - dec);
Assert.True(absDec < 0.01);
}
#endregion
#region HashGetAll
/// <summary>
/// 获取一个学生
/// </summary>
[Fact]
public void HashGetAllTest()
{
var studentEntries = new HashEntry[]
{
new HashEntry("Id",defaultStudent.Id),
new HashEntry("Name",defaultStudent.Name),
new HashEntry("Age",defaultStudent.Age),
};
//插入Sudent
var addHash = redisHashStudy.HashSet(defaultStudentHashKey, studentEntries);
Assert.True(addHash);
var entries = redisHashStudy.HashGetAll(defaultStudentHashKey);
Assert.NotNull(entries);
Student myStudent = new Student()
{
Id = (int)entries.FirstOrDefault(e => e.Name == "Id").Value,
Name = entries.FirstOrDefault(e => e.Name == "Name").Value,
Age = (int)entries.FirstOrDefault(e => e.Name == "Age").Value,
};
Assert.True(myStudent.Id == defaultStudent.Id && myStudent.Name == defaultStudent.Name && myStudent.Age == defaultStudent.Age);
}
#endregion
#region HashGet
/// <summary>
/// 哈希表不存在时,获取字段值
/// </summary>
[Fact]
public void HashGetNotKkeyTest()
{
var result = redisHashStudy.HashGet(defaultStudentHashKey, "Id");
Assert.False(result.HasValue);
}
/// <summary>
/// 字段不存在时,获取字段值
/// </summary>
[Fact]
public void HashGetNotHashfieldTest()
{
redisHashStudy.HashIncrement(defaultStudentHashKey, "Id", 1);
var result = redisHashStudy.HashGet(defaultStudentHashKey, "Name");
Assert.False(result.HasValue);
}
[Fact]
public void HashGetOneFieldTest()
{
AddDefaultStudent();
Assert.Equal(1, redisHashStudy.HashGet(defaultStudentHashKey, "Id"));
Assert.Equal(defaultStudent.Name, redisHashStudy.HashGet(defaultStudentHashKey, "Name", CommandFlags.None));
Assert.Equal(defaultStudent.Age, redisHashStudy.HashGet(defaultStudentHashKey, "Age", CommandFlags.None));
}
[Fact]
public void HashGetGroupFieldTest()
{
AddDefaultStudent();
RedisValue[] hashFields = new RedisValue[]
{
"Id",
"Name",
"Age",
};
RedisValue[] resultValues = redisHashStudy.HashGet(defaultStudentHashKey, hashFields, CommandFlags.None);
Assert.Contains(defaultStudent.Id, resultValues);
Assert.Contains(defaultStudent.Name, resultValues);
Assert.Contains(defaultStudent.Age, resultValues);
}
#endregion
#region HashKeys
/// <summary>
/// 哈希不存在时获取所有字段的Key
/// </summary>
[Fact]
public void HashKeysNotKeyTest()
{
RedisValue[] keys = redisHashStudy.HashKeys(defaultStudentHashKey);
Assert.NotNull(keys);
Assert.Empty(keys);
}
/// <summary>
/// 获取哈希所有字段的Key
/// </summary>
[Fact]
public void HashKeys()
{
AddDefaultStudent();
RedisValue[] keys = redisHashStudy.HashKeys(defaultStudentHashKey);
Assert.NotEmpty(keys);
Assert.Contains("Id", keys);
Assert.Contains("Name", keys);
Assert.Contains("Age", keys);
}
#endregion
#region HashValues
/// <summary>
/// 哈希不存在时获取所有字段的Key
/// </summary>
[Fact]
public void HashValuesNotKeyTest()
{
RedisValue[] keys = redisHashStudy.HashValues(defaultStudentHashKey);
Assert.NotNull(keys);
Assert.Empty(keys);
}
/// <summary>
/// 获取哈希所有字段的Key
/// </summary>
[Fact]
public void HashValues()
{
AddDefaultStudent();
RedisValue[] values = redisHashStudy.HashValues(defaultStudentHashKey);
Assert.NotEmpty(values);
Assert.Contains(defaultStudent.Id, values);
Assert.Contains(defaultStudent.Name, values);
Assert.Contains(defaultStudent.Age, values);
}
#endregion
#region HashLength
/// <summary>
/// 哈希不存在时,获取字段数
/// </summary>
[Fact]
public void HashLengthNotKeyTest()
{
var result = redisHashStudy.HashLength(defaultStudentHashKey);
Assert.Equal(0, result);
}
/// <summary>
/// 获取哈希字段数
/// </summary>
[Fact]
public void HashLengthTest()
{
AddDefaultStudent();
var result = redisHashStudy.HashLength(defaultStudentHashKey);
Assert.Equal(3, result);
}
#endregion
#region HashScan
/// <summary>
/// 哈希不存在时HashScan
/// </summary>
[Fact]
public void HashScanNotKeyTest()
{
var hashEntrys = redisHashStudy.HashScan(defaultStudentHashKey, "*", 20, CommandFlags.None);
var num = hashEntrys.Count();
Assert.Equal(0, num);
var entryList = hashEntrys.ToList();
Assert.Empty(entryList);
}
/// <summary>
/// 简单测试,有单独测试类详细测试
/// </summary>
[Fact]
public void HashScanTest()
{
//插入多列hash
List<HashEntry> hashEntries = new List<HashEntry>();
for (int i = 1; i <= 100; i++)
{
hashEntries.Add(new HashEntry("Field" + i, i));
}
redisHashStudy.HashSet(defaultStudentHashKey, hashEntries.ToArray());
var hashFieldScan = redisHashStudy.HashScan(defaultStudentHashKey);
Assert.Equal(100, hashFieldScan.Count());
var scanTake = hashFieldScan.Skip(10).Take(10).ToList();
Assert.Equal(10, scanTake.Count());
//删除hash
redisDatabase.KeyDelete(defaultStudentHashKey);
}
[Fact]
public void HashScan2Test()
{
//插入多列hash
List<HashEntry> hashEntries = new List<HashEntry>();
for (int i = 1; i <= 100; i++)
{
hashEntries.Add(new HashEntry("Field" + i, i));
}
redisHashStudy.HashSet(defaultStudentHashKey, hashEntries.ToArray());
var hashFieldScan = redisHashStudy.HashScan(defaultStudentHashKey, "*", 20, 0, 0, CommandFlags.None);
Assert.Equal(100, hashFieldScan.Count());
}
#endregion
#region HashExists
/// <summary>
/// 指定字段是否存在
/// </summary>
[Fact]
public void HashExists()
{
var studentEntries = new HashEntry[]
{
new HashEntry("Id",defaultStudent.Id),
new HashEntry("Name",defaultStudent.Name),
};
//插入Sudent
var addHash = redisHashStudy.HashSet(defaultStudentHashKey, studentEntries);
Assert.True(addHash);
Assert.True(redisHashStudy.HashExists(defaultStudentHashKey, "Id"));
Assert.True(redisHashStudy.HashExists(defaultStudentHashKey, "Name"));
Assert.False(redisHashStudy.HashExists(defaultStudentHashKey, "Age"));
}
#endregion
#region HashDelete
/// <summary>
/// 哈希不存在时,删除哈希字段
/// </summary>
[Fact]
public void HashDeleteNotKeyTest()
{
var hashDeleteResult = redisHashStudy.HashDelete(defaultStudentHashKey, "FieldFirst");
Assert.False(hashDeleteResult);
}
/// <summary>
/// 删除不存在的哈希字段
/// </summary>
[Fact]
public void HashDeleteNotFieldTest()
{
redisHashStudy.HashIncrement(defaultStudentHashKey, "Id", 1);
var hashDeleteResult = redisHashStudy.HashDelete(defaultStudentHashKey, "Name");
Assert.False(hashDeleteResult);
}
/// <summary>
/// 删除哈希一个字段
/// </summary>
[Fact]
public void HashDeleteTest()
{
AddDefaultStudent();
var hashDeleteResult = redisHashStudy.HashDelete(defaultStudentHashKey, "Id");
Assert.True(hashDeleteResult);
hashDeleteResult = redisHashStudy.HashDelete(defaultStudentHashKey, "Name", CommandFlags.None);
Assert.True(hashDeleteResult);
hashDeleteResult = redisHashStudy.HashDelete(defaultStudentHashKey, "Age", CommandFlags.None);
Assert.True(hashDeleteResult);
}
/// <summary>
/// 删除一组哈希字段
/// </summary>
[Fact]
public void HashDeleteGroupFieldTest()
{
AddDefaultStudent();
RedisValue[] delValues = new RedisValue[]
{
"Id",
"Name",
"Age",
};
var hashDeleteResult = redisHashStudy.HashDelete(defaultStudentHashKey, delValues, CommandFlags.None);
Assert.Equal(3, hashDeleteResult);
}
#endregion
#region HashKeyDelete
/// <summary>
/// 删除学生
/// </summary>
[Fact]
public void KeyDeleteTest()
{
Assert.False(redisDatabase.KeyDelete(preStudentHashKey + "-2000"));
}
#endregion
/// <summary>
/// 清理
/// </summary>
public void Dispose()
{
DeleteExitsStudents();
}
#region 辅助方法
/// <summary>
/// 删除Redis中的测试学生
/// </summary>
private void DeleteExitsStudents()
{
if (defaultStudent != null)
{
redisDatabase.KeyDelete(preStudentHashKey + defaultStudent.Id);
}
}
private void AddDefaultStudent()
{
var studentEntries = new HashEntry[]
{
new HashEntry("Id",defaultStudent.Id),
new HashEntry("Name",defaultStudent.Name),
new HashEntry("Age",defaultStudent.Age),
};
//插入Sudent
var addHash = redisHashStudy.HashSet(defaultStudentHashKey, studentEntries);
}
#endregion
}
}