* ObjectTest.cs: chore: 整理 AVUser 接口,并编写简单测试用例。

* UserTest.cs:
* AVUser.cs:
* AVQuery.cs:
* AVObject.cs:
* MD5.cs:
* AVCloudCodeController.cs:
oneRain 2019-08-23 16:16:18 +08:00
parent 3786595bf1
commit 6969884bd9
7 changed files with 166 additions and 106 deletions

View File

@ -3,7 +3,6 @@ using LeanCloud;
using System.Net.Http; using System.Net.Http;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Runtime.CompilerServices;
namespace LeanCloudTests { namespace LeanCloudTests {
public class ObjectTests { public class ObjectTests {
@ -12,6 +11,7 @@ namespace LeanCloudTests {
AVClient.Initialize(new AVClient.Configuration { AVClient.Initialize(new AVClient.Configuration {
ApplicationId = "BMYV4RKSTwo8WSqt8q9ezcWF-gzGzoHsz", ApplicationId = "BMYV4RKSTwo8WSqt8q9ezcWF-gzGzoHsz",
ApplicationKey = "pbf6Nk5seyjilexdpyrPwjSp", ApplicationKey = "pbf6Nk5seyjilexdpyrPwjSp",
ApiServer = "https://avoscloud.com",
RTMServer = "https://router-g0-push.avoscloud.com", RTMServer = "https://router-g0-push.avoscloud.com",
}); });
AVClient.HttpLog(TestContext.Out.WriteLine); AVClient.HttpLog(TestContext.Out.WriteLine);
@ -54,5 +54,19 @@ namespace LeanCloudTests {
Assert.Pass(); Assert.Pass();
} }
[Test]
public async Task TestMassiveRequest() {
await Task.Run(() => {
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 50; j++) {
AVObject obj = AVObject.Create("Foo");
obj.SaveAsync().ContinueWith(_ => {
TestContext.Out.WriteLine($"{obj.ObjectId} saved");
});
}
Thread.Sleep(1000);
}
});
}
} }
} }

View File

@ -70,5 +70,45 @@ namespace LeanCloudTests {
await user.UpdatePasswordAsync("111111", "222222"); await user.UpdatePasswordAsync("111111", "222222");
await user.UpdatePasswordAsync("222222", "111111"); await user.UpdatePasswordAsync("222222", "111111");
} }
[Test]
public async Task LoginWithAuthData() {
AVUser user = await AVUser.LogInWithAuthDataAsync(new Dictionary<string, object> {
{ "openid", "0395BA18A5CD6255E5BA185E7BEBA242" },
{ "access_token", "12345678-SaMpLeTuo3m2avZxh5cjJmIrAfx4ZYyamdofM7IjU" },
{ "expires_in", 1382686496 }
}, "qq");
Assert.NotNull(user.SessionToken);
TestContext.Out.WriteLine(user.SessionToken);
}
[Test]
public async Task AssociateAuthData() {
AVUser user = await AVUser.LogInAsync("111111", "111111");
Assert.NotNull(user.SessionToken);
await user.AssociateAuthDataAsync(new Dictionary<string, object> {
{ "openid", "0395BA18A5CD6255E5BA185E7BEBA243" },
{ "access_token", "12345678-SaMpLeTuo3m2avZxh5cjJmIrAfx4ZYyamdofM7IjU" },
{ "expires_in", 1382686496 }
}, "qq");
}
[Test]
public async Task Anonymously() {
AVUser user = await AVUser.LogInAnonymouslyAsync();
Assert.NotNull(user.SessionToken);
TestContext.Out.WriteLine(user.SessionToken);
}
[Test]
public async Task GetRoles() {
AVUser user = await AVUser.LogInAsync("111111", "111111");
Assert.NotNull(user.SessionToken);
IEnumerable<AVRole> roles = await user.GetRolesAsync();
Assert.Greater(roles.Count(), 0);
foreach (AVRole role in roles) {
TestContext.Out.WriteLine(role.Name);
}
}
} }
} }

View File

@ -7,7 +7,7 @@ using System.Net.Http;
namespace LeanCloud.Storage.Internal { namespace LeanCloud.Storage.Internal {
public class AVCloudCodeController { public class AVCloudCodeController {
public Task<T> CallFunctionAsync<T>(String name, public Task<T> CallFunctionAsync<T>(string name,
IDictionary<string, object> parameters, IDictionary<string, object> parameters,
string sessionToken, string sessionToken,
CancellationToken cancellationToken) { CancellationToken cancellationToken) {
@ -19,7 +19,7 @@ namespace LeanCloud.Storage.Internal {
return AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command, cancellationToken: cancellationToken).OnSuccess(t => { return AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command, cancellationToken: cancellationToken).OnSuccess(t => {
var decoded = AVDecoder.Instance.Decode(t.Result.Item2) as IDictionary<string, object>; var decoded = AVDecoder.Instance.Decode(t.Result.Item2) as IDictionary<string, object>;
if (!decoded.ContainsKey("result")) { if (!decoded.ContainsKey("result")) {
return default(T); return default;
} }
return Conversion.To<T>(decoded["result"]); return Conversion.To<T>(decoded["result"]);
}); });
@ -34,7 +34,7 @@ namespace LeanCloud.Storage.Internal {
return AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command, cancellationToken: cancellationToken).OnSuccess(t => { return AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command, cancellationToken: cancellationToken).OnSuccess(t => {
var decoded = AVDecoder.Instance.Decode(t.Result.Item2) as IDictionary<string, object>; var decoded = AVDecoder.Instance.Decode(t.Result.Item2) as IDictionary<string, object>;
if (!decoded.ContainsKey("result")) { if (!decoded.ContainsKey("result")) {
return default(T); return default;
} }
return Conversion.To<T>(decoded["result"]); return Conversion.To<T>(decoded["result"]);
}); });

View File

@ -75,11 +75,11 @@ namespace LeanCloud.Storage.Internal
private const byte S42 = 10; private const byte S42 = 10;
private const byte S43 = 15; private const byte S43 = 15;
private const byte S44 = 21; private const byte S44 = 21;
static private byte[] PADDING = new byte[] { private static readonly byte[] PADDING = {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}; };
#endregion #endregion
#region F, G, H and I are basic MD5 functions. #region F, G, H and I are basic MD5 functions.

View File

@ -570,7 +570,7 @@ string propertyName
// Get the JSON representation of the object. // Get the JSON representation of the object.
currentOperations = StartSave(); currentOperations = StartSave();
sessionToken = AVUser.CurrentUser.SessionToken; sessionToken = AVUser.CurrentUser?.SessionToken;
deepSaveTask = DeepSaveAsync(estimatedData, sessionToken, cancellationToken); deepSaveTask = DeepSaveAsync(estimatedData, sessionToken, cancellationToken);
} }

View File

@ -654,10 +654,13 @@ namespace LeanCloud
internal AVQuery<T> WhereRelatedTo(AVObject parent, string key) { internal AVQuery<T> WhereRelatedTo(AVObject parent, string key) {
MergeWhereClauses(new Dictionary<string, object> { MergeWhereClauses(new Dictionary<string, object> {
{ key, new Dictionary<string, object>{ { "$relatedTo", new Dictionary<string, object> { {
{ "object", parent}, "$relatedTo",
{ "key", key} new Dictionary<string, object> {
} } } } { "object", parent },
{ "key", key }
}
}
}); });
return this; return this;
} }

View File

@ -269,96 +269,6 @@ namespace LeanCloud {
#endregion #endregion
#region 第三方登录
/// <summary>
/// 使用第三方数据注册;如果已经存在相同的 Auth Data则执行登录
/// </summary>
/// <param name="authData">Auth Data</param>
/// <param name="platform">平台</param>
/// <param name="options"></param>
/// <returns></returns>
public static Task<AVUser> LogInWithAuthDataAsync(IDictionary<string, object> authData, string platform, AVUserAuthDataLogInOption options = null) {
if (options == null) {
options = new AVUserAuthDataLogInOption();
}
return LogInWithAsync(platform, authData, options.FailOnNotExist);
}
/// <summary>
/// 使用第三方数据注册;
/// </summary>
/// <param name="authData">Auth data</param>
/// <param name="platform">平台标识</param>
/// <param name="unionId"></param>
/// <param name="options"></param>
/// <returns></returns>
public static Task<AVUser> LogInWithAuthDataAndUnionIdAsync(IDictionary<string, object> authData, string platform, string unionId,
AVUserAuthDataLogInOption options = null) {
if (options == null) {
options = new AVUserAuthDataLogInOption();
}
MergeAuthData(authData, unionId, options);
return LogInWithAsync(platform, authData, options.FailOnNotExist);
}
/// <summary>
/// 绑定第三方登录
/// </summary>
/// <param name="authData">Auth data</param>
/// <param name="platform">平台标识</param>
/// <returns></returns>
public Task AssociateAuthDataAsync(IDictionary<string, object> authData, string platform) {
return LinkWithAsync(platform, authData);
}
/// <summary>
/// 绑定第三方登录
/// </summary>
/// <param name="authData">OAuth data</param>
/// <param name="platform">平台标识</param>
/// <param name="unionId"></param>
/// <param name="options"></param>
/// <returns></returns>
public Task AssociateAuthDataAndUnionIdAsync(IDictionary<string, object> authData, string platform, string unionId,
AVUserAuthDataLogInOption options = null) {
if (options == null) {
options = new AVUserAuthDataLogInOption();
}
MergeAuthData(authData, unionId, options);
return LinkWithAsync(platform, authData);
}
/// <summary>
/// 解绑第三方登录
/// </summary>
/// <param name="platform">平台标识</param>
/// <returns></returns>
public Task DisassociateWithAuthDataAsync(string platform) {
return LinkWithAsync(platform, null);
}
#endregion
public Task LinkWithAsync(string authType, IDictionary<string, object> data) {
AuthData = new Dictionary<string, IDictionary<string, object>> {
[authType] = data
};
return SaveAsync();
}
internal static async Task<AVUser> LogInWithAsync(string authType, IDictionary<string, object> data, bool failOnNotExist) {
var ret = await UserController.LogInAsync(authType, data, failOnNotExist);
AVUser user = FromState<AVUser>(ret, "_User");
user.AuthData = new Dictionary<string, IDictionary<string, object>> {
[authType] = data
};
CurrentUser = user;
return CurrentUser;
}
#region 手机号登录 #region 手机号登录
/// <summary> /// <summary>
@ -430,6 +340,77 @@ namespace LeanCloud {
#endregion #endregion
#region 第三方登录
/// <summary>
/// 使用第三方数据注册;如果已经存在相同的 Auth Data则执行登录
/// </summary>
/// <param name="authData">Auth Data</param>
/// <param name="platform">平台</param>
/// <param name="options"></param>
/// <returns></returns>
public static Task<AVUser> LogInWithAuthDataAsync(IDictionary<string, object> authData, string platform, AVUserAuthDataLogInOption options = null) {
if (options == null) {
options = new AVUserAuthDataLogInOption();
}
return LogInWithAsync(platform, authData, options.FailOnNotExist);
}
/// <summary>
/// 使用第三方数据注册;
/// </summary>
/// <param name="authData">Auth data</param>
/// <param name="platform">平台标识</param>
/// <param name="unionId"></param>
/// <param name="options"></param>
/// <returns></returns>
public static Task<AVUser> LogInWithAuthDataAndUnionIdAsync(IDictionary<string, object> authData, string platform, string unionId,
AVUserAuthDataLogInOption options = null) {
if (options == null) {
options = new AVUserAuthDataLogInOption();
}
MergeAuthData(authData, unionId, options);
return LogInWithAsync(platform, authData, options.FailOnNotExist);
}
/// <summary>
/// 绑定第三方登录
/// </summary>
/// <param name="authData">Auth data</param>
/// <param name="platform">平台标识</param>
/// <returns></returns>
public Task AssociateAuthDataAsync(IDictionary<string, object> authData, string platform) {
return LinkWithAuthDataAsync(platform, authData);
}
/// <summary>
/// 绑定第三方登录
/// </summary>
/// <param name="authData">Auth data</param>
/// <param name="platform">平台标识</param>
/// <param name="unionId"></param>
/// <param name="options"></param>
/// <returns></returns>
public Task AssociateAuthDataAndUnionIdAsync(IDictionary<string, object> authData, string platform, string unionId,
AVUserAuthDataLogInOption options = null) {
if (options == null) {
options = new AVUserAuthDataLogInOption();
}
MergeAuthData(authData, unionId, options);
return LinkWithAuthDataAsync(platform, authData);
}
/// <summary>
/// 解绑第三方登录
/// </summary>
/// <param name="platform">平台标识</param>
/// <returns></returns>
public Task DisassociateWithAuthDataAsync(string platform) {
return LinkWithAuthDataAsync(platform, null);
}
#endregion
#region 重置密码 #region 重置密码
/// <summary> /// <summary>
@ -552,7 +533,7 @@ namespace LeanCloud {
/// <summary> /// <summary>
/// 关注某个用户 /// 关注某个用户
/// </summary> /// </summary>
/// <param name="userObjectId">被关注的用户Id</param> /// <param name="userObjectId">被关注的用户 Id</param>
/// <param name="data">关注的时候附加属性</param> /// <param name="data">关注的时候附加属性</param>
/// <returns></returns> /// <returns></returns>
public Task FollowAsync(string userObjectId, IDictionary<string, object> data) { public Task FollowAsync(string userObjectId, IDictionary<string, object> data) {
@ -570,7 +551,7 @@ namespace LeanCloud {
/// <summary> /// <summary>
/// 取关某一个用户 /// 取关某一个用户
/// </summary> /// </summary>
/// <param name="userObjectId"></param> /// <param name="userObjectId">用户 Id</param>
/// <returns></returns> /// <returns></returns>
public Task UnfollowAsync(string userObjectId) { public Task UnfollowAsync(string userObjectId) {
var command = new AVCommand { var command = new AVCommand {
@ -631,6 +612,28 @@ namespace LeanCloud {
#endregion #endregion
public Task<IEnumerable<AVRole>> GetRolesAsync() {
AVQuery<AVRole> query = new AVQuery<AVRole>();
query.WhereRelatedTo(this, "users");
return query.FindAsync();
}
Task LinkWithAuthDataAsync(string authType, IDictionary<string, object> data) {
AuthData = new Dictionary<string, IDictionary<string, object>> {
[authType] = data
};
return SaveAsync();
}
internal static async Task<AVUser> LogInWithAsync(string authType, IDictionary<string, object> data, bool failOnNotExist) {
var ret = await UserController.LogInAsync(authType, data, failOnNotExist);
AVUser user = FromState<AVUser>(ret, "_User");
user.AuthData = new Dictionary<string, IDictionary<string, object>> {
[authType] = data
};
CurrentUser = user;
return CurrentUser;
}
internal static async Task<AVUser> LogInWithParametersAsync(Dictionary<string, object> strs) { internal static async Task<AVUser> LogInWithParametersAsync(Dictionary<string, object> strs) {
IObjectState ret = await UserController.LogInWithParametersAsync("login", strs); IObjectState ret = await UserController.LogInWithParametersAsync("login", strs);